我有一组文档,我想将它们读入 LaTeX 环境。问题是这些文档的格式并不完全符合我的要求。我想创建一个环境,在环境的持续时间内改变 LaTeX.
在句子末尾的解析方式。本质上,我想要类似这样的内容:
\begin{mycontent}
random content. more random content. some more random content.
\end{mycontent}
并解析它,就像我写了一样
\begin{mycontent}
random content.\formattingcommand more random content.\formattingcommand some more random content.\formattingcommand
\end{mycontent}
我无法控制传递给我的文件的内容,但我可以保证所有文件的结构都相同。我可以编写一个 Perl 脚本来处理这个问题,通常我会这样做。但这需要某种 LaTeX 包装器,其他人可以在不调用 Perl 的情况下使用它,并且可以无缝地工作。
如果我能写出类似下面的内容就太好了:
\let\oldperiod{.}
\def.{\oldperiod\formattingcommand}%
但.
不是命令。我查看了 Knuth 的The TeXbook
句子部分,但没有看到任何可以立即使用的内容。
我想我可以做点什么来改变 cat 代码.
在环境的持续时间内持续存在,但我需要旧的句点出现在这个新环境中。我不太确定该怎么做,也不想这么做。但是,我愿意在这一点上保持灵活(特别是如果有人真的有凉爽的以显示。)
编辑1
关于 catcodes:我以前从未真正使用过 catcodes。所以我现在有点盲目地独自探索这条小路。
编辑2
如果我遵循约瑟夫赖特的建议,我可能会担心我加载的其他一些包现在可能会在如何处理活动期方面发生冲突。以下代码没有被建议的原因是什么:
\documentclass{article}
\newcommand{\formattingcommand}{DEMO}
\newenvironment{mycontent}
{%
\let\normalperiod=.%
\catcode`\.=\active
\def.{\normalperiod\formattingcommand}%
}
{}
\begin{document}
\begin{mycontent}
random content. more random content. some more random content.
\end{mycontent}
\end{document}
我问这个问题是因为在我看来这个版本应该可以工作,但是当我尝试它时出现错误:
! Missing control sequence inserted.
<inserted text>
\inaccessible
l.11 \begin{mycontent}
?
编辑3
根据下面大家的反馈,以下内容是否安全?
\documentclass{article}
\newcommand{\formattingcommand}{DEMO}
\let\normalperiod=.%
\chardef\periodcatcode=\catcode`\.
\catcode`\.=\active
\newenvironment{mycontent}
{%
\catcode`\.=\active%
\def.{\normalperiod\formattingcommand}%
}
{}
\catcode`\.=\periodcatcode
\begin{document}
\begin{mycontent}
random content. more random content. some more random content.
\end{mycontent}
\end{document}
我说的安全是指:
\let
保存正确版本的句点(具有预期 catcode 的句点):假设我之前没有对 catcodes 进行任何其他奇怪的操作。- 我在制作之前保存了当前的 catcode
\active
- 我编写了cat
.
代码,\active
以确保它仅在我的环境范围内具有\active
我为其提供的定义。换句话说,我的定义在范围内是本地的,不会影响其范围之外的定义。 - 我已将 catcode 恢复
.
到创建新环境之前的状态,而无需再猜测它可能是什么。 - 如果其他包希望重新定义积极的
.
,我的修改对他们来说是不可见的(假设我没有使用与我的环境中打包的代码相关的任何代码)。
答案1
您对 catcode 更改的理解是正确的。关键是.
在应用更改之前用另一个名称保存旧的定义。标准方法看起来像
\documentclass{article}
\begingroup
\catcode`\.=\active
\gdef.{\normalperiod\formattingcommand}%
\endgroup
\newcommand{\formattingcommand}{DEMO}
\newenvironment{mycontent}
{%
\let\normalperiod=.%
\catcode`\.=\active
}
{}
\begin{document}
\begin{mycontent}
random content. more random content. some more random content.
\end{mycontent}
\end{document}
我使用了一个组来避免需要知道 catcode.
更具有什么特点。
你可能会对这里的全局定义感到惊讶.
。“技巧”在于.
只发生了变化本地,并且该定义只适用于其中.
处于活跃状态的情况。
与任何依赖 catcode 更改的东西一样,这只有在“内容”尚未被 TeX 读取(“标记化”)时才会正常工作。因此,如果您的内容将用于某些命令的参数,请不要使用它。还请注意,它babel
大量使用活动字符,如果正在使用,则存在冲突的风险。
原因是
\newenvironment{mycontent}
{%
\let\normalperiod=.%
\catcode`\.=\active
\def.{\normalperiod\formattingcommand}%
}
{}
失败的原因是,当 TeX 读取代码时,.
,不是活动,所以\def.
是不正确的(\def
必须后跟活动字符或宏名称)。\newenvironment
命令已读取所有“环境启动”代码,但不是执行了它,所以它包含一行的事实\catcode
对接下来的内容没有影响\def
。
你可以通过以下几种方式避免这种情况,例如
\catcode`\.=\active
\newenvironment{mycontent}
{%
\let\normalperiod=.%
\catcode`\.=\active
\def.{\normalperiod\formattingcommand}%
}
\catcode`\.=12 % Assuming the usual set up: could be risky
或者
\newenvironment{mycontent}
{%
\let\normalperiod=.%
\catcode`\.=\active
\lccode`\~=`.%
\lowercase{%
\def~{\normalperiod\formattingcommand}%
}%
}
~
它利用了在 LaTeX 文档中处于活动状态并且保留了 catcodes 的事实\lowercase
。
在上述两种替代方法中,我更喜欢第二种方法(使用\lowercase
),而不是将 的.
整个定义激活mycontent
。如果另一个包.
在某些有限的上下文中激活,那么就有可能
\catcode`\.=\active
\newenvironment{mycontent}
{%
\let\normalperiod=.%
选择一个.
实际上不正确的主动词定义(如果在一般文件中.
中不是积极的)。
答案2
在处理类别代码和特定活动字符时,需要注意一些问题。
当字符标记已经进入 TeX 时,它们的类别代码是固定的(除非
\scantokens
使用,但这会引起一系列麻烦)。如果一个活跃角色以某种方式潜入列表中
\write
,那么就一定有一个定义。babel
使一些角色活跃,但延迟这样做\begin{document}
假设使其.
处于活动状态并将其含义定义为“打印句点并执行\formatcommand
”可以解决您的问题(并且您没有任何东西可以潜入\write
诸如包含句点的标签之类的东西),让我们看看几个替代方案。
方法 1
\begingroup
\catcode`\.=\active
\gdef.{\normalperiod\formatcommand}
\endgroup
\newcommand\normalperiod{.}
\newcommand\formatcommand{whatever}
\newenvironment{mycontent}
{\catcode`\.=\active}
{}
babel
这种方法是最简单的。但是如果加载了使句点处于活动状态的语言,或者其他软件包也这样做,这种方法就会失效。
方法 2
\newcommand\formatcommand{whatever}
\edef\normalperiod{\string.}
\newenvironment{mycontent}
{\begingroup\lccode`~=`\.
\lowercase{\endgroup\def~}{\normalperiod\formatcommand}%
\catcode`\.=\active}
{}
您仍然不能将里面的句点mycontents
用于进入的东西\write
,但这是每种方法的常见限制。
这种方法对于 来说非常安全babel
,但当然它会覆盖它可能赋予活动句点的含义。 使用\edef
的\normalperiod
确保其替换文本是正常类别代码 12 句点,因此如果其他先前加载的包更改了类别代码,您不会受到影响。