有一个问题是关于在句号和逗号后自动添加空格。对此的回答包括修改类别代码。如下所示。
\documentclass{article}
\usepackage{expl3}
\makeatletter
\catcode`.13
\def.{\char`.\@ifnextchar'{}{\@ifnextchar.{}{ }}}
\makeatother
\def\Abbr{\catcode`.12}
\begin{document}
...
\end{document}
我对此有一些疑问。首先,为什么写成\catcode`.13
?我认为的语法\catcode
应该=
包含,表示字符及其新的类别代码。
第二,怎么就.
因为类别码是13就可以成为命令本身了呢?这样的字符有很多,没有一个可以不以\
开头就形成命令名。
答案1
分配中的=
是可选的。实际上,使用 稍微更有效=
,但优势很小。以收益\catcode`?13
率为基准\catcode`?=13
No =
1.02e-7 seconds (0.472 ops)
With =
9.25e-8 seconds (0.427 ops)
我使用了l3benchmark
多次重复代码,以便尽可能准确地给出估计值。顺便说一句,使用\active
而不是13
No =
7.94e-8 seconds (0.378 ops)
With =
6.93e-8 seconds (0.327 ops)
一旦您将某个字符的 catcode 设置为 13(活动字符),它就会像一个控制序列一样运行,因此您可以将其用作后面的标记\def
(或任何其他控制序列定义命令)来赋予它含义。
该功能可用于babel
引入简写。例如,当当前babel
语言为德语时,该组合"|
表示词素边界,这对于打破不必要的连字非常重要,因此可以输入Auf"|lage
清楚地表明该词是由“auf”和“lage”组成的。这是通过给出"
catcode 13 并根据以下标记为其分配适当的定义来实现的:"-
插入额外的换行符点,允许在其后进行连字符连接。
听起来很熟悉?是的,这和你的情况很相似,但有一个很大的区别:这个字符"
在 TeX 中很少使用,但句点在很多地方都是 TeX 语法的一部分。
一旦你这样做\catcode`.=13
,你将无法再指定
\vspace{1.5pt}
试试看。你需要说\vspace{1\string.5pt}
。或者你可以用逗号代替句号。你愿意这么做吗?
好的,我们假设您是。这个想法是定义活动.
以寻找下一个标记并决定要做什么。
在 LaTeX 中执行此操作的标准方法是使用\@ifnextchar
,向其提供要查找的令牌以及在“成功”或“失败”时要执行的代码。
给定的定义打印一个句点(而不是\char`.
我会做\string.
)然后执行
\@ifnextchar'{T}{F}
(此处T
和F
代表实际代码)。如果 TypeScript 中句点后面的字符是'
,则T
执行,否则执行F
。由于您不想执行任何操作,因此在本例中,T
实际上是空的。如果'
没有执行后,F
实际的代码是
\@ifnextchar.{}{ }
如果后面跟着句号,则不执行任何操作,否则会插入空格。为什么要进行此检查?我不确定,因为输入两个连续的句号并不常见,而三个句号是不正确的,因为\ldots
应该使用。
无论如何,代码完成了它的工作。但是,假设您愿意接受上述几个问题\vspace{1.5pt}
,那么这并不是最好的编程。
\documentclass{article}
\makeatletter
% define the desired action for the active period
\begingroup\lccode`~=`.\lowercase{\endgroup
\newcommand{\active@period}{.\@ifnextchar'{}{\@ifnextchar~{}{ }}}%
}
\AtBeginDocument{%
% assign the meaning of \active@period to the active period
\begingroup\lccode`~=`. \lowercase{\endgroup\let~}\active@period
% change the catcode
\catcode`.=\active
}
\makeatother
% to locally set the category code of . to 12
\newcommand{\Abbr}{\catcode`.=12 }% don't forget the space!
\begin{document}
...
\end{document}
这样,类别代码的设置就会延迟到文档开始时配置文件已经被读入的时候。
后面的空格12
是需要。 尝试
{\Abbr 1.2.3}
看看原始代码是否存在问题。事实上,你会得到
\catcode`.121.2.3
并且将 121 指定为 catcode 是非法的。如果使用空格,则
\catcode`.12 1.2.3
12
并且根据 TeX 规则,后面的空格将被忽略。
采用更现代的方法:
\documentclass{article}
\ExplSyntaxOn
% to locally set the category code of . to 12
\NewDocumentCommand{\Abbr}{}{\char_set_catcode_other:N .}
% define the desired action for the active period
\cs_new_protected:Nn \youthdoc_active_period:
{
.
\peek_charcode:NF .
{% a period doesn't follow
\peek_charcode:NF '
{% a quote doesn't follow, insert a space
\c_space_tl
}
}
}
% at begin document set the period to be active
\AtBeginDocument
{
\char_set_active_eq:NN . \youthdoc_active_period:
\char_set_catcode_active:N .
}
\ExplSyntaxOff
\begin{document}
A period.With a space.But ...has a space only at the end
`A quote.'
\end{document}
在定义中,没有扭曲的句点具有不同的 catcode。
答案2
您显示的代码在每个点后插入空格,但有两个例外。如果点后跟字符'
或字符后跟另一个点,则不会插入空格。
TeX 原始命令\catcode
将类别代码(16 个值之一)分配给字符。语法是\catode <number>=<number>
或\catcode <number><number>
(即 是=
可选的)。第一个数字是计算机中字符的数字表示(ASCII 或 Unicode),第二个数字在 0 到 15 范围内,表示分配的类别代码。如果您知道点的数字表示(它是 46),那么您可以说
\catcode 46 13
或\catcode 46=13
。您可以使用`
后跟一个字符或\
后跟一个字符代替数字常量,结果相同:\catcode`.=13
或\catcode`\.=13
或\catcode`.13
或\catcode`\.13
。
一旦字符具有类别代码 13,它就处于“活动”状态,这意味着它的行为就像另一个控制序列。您可以在、和许多其他情况下使用它\def<control sequence>
。\let<control sequence>
当\countef<control sequence>
它被定义为宏时,在常见情况下,当 TeX 扫描仪到达时,字符会扩展到其主体。
PlainTeX 将类别代码 13 设置为 ,~
并将其定义为一个宏,该宏将扩展为\penalty10000 \space
,即不可中断的空格。PlainTeX 没有将其他可见字符设置为类别 13。其他 TeX 格式(如 LaTeX)也这样做:它们仅将类别 13 设置为~
。您可以设置更多这样的字符,并在给出的代码中执行此操作。
这是一个 LaTeX 宏,它使用TeX 基元\@ifnextchar <character>{true}{false}
查找下一个字符(但在输入队列中保持不变),如果下一个字符是则运行,否则运行。您可能想知道代码会做什么。\futurelet
true
<character>
false
\@ifnextchar'{}{\@ifnextchar.{}{ }}
编辑\usepackage{expl3}
评论中有一个新问题:如果不使用,为什么代码在新版本的 LaTeX 中不起作用。首先:您的宏与 expl3 没有任何共同之处,但新版本的 LaTeX 将 expl3 内容实现到 LaTeX 内核。并且它需要l3backend-?.def
根据各种情况读取文件。如果您使用,则会立即读取此文件,但如果尚未读取,则会在新 LaTeX 内核中\usepackage{expl3}
读取它。\begin{document}
读取外部宏文件需要只有标准 catcode 设置。在此状态下,点无法处于活动状态。这会导致错误。(注意:如果您使用 OpTeX\load
加载外部宏,则不会出现此问题,因为它在读取此类文件时会临时设置标准 catcodes 向量。)
解决方案:您可以将带有活动点的宏放在后面\begin{document}
。或者\catcode`.=12
在宏代码的末尾设置,然后\catcode`.=13
在之后\begin{document}
或使用\AtBeginDocument
宏再次设置。