怎么\detokenize
運作?
e-TeX 简短参考手册指出:
当后面跟着一个 时
<general text>
,会扩展为产生一个字符标记序列,该序列由\catcode
10 个字符(空格)或 12 个字符(其他)组成,对应于<balanced text>
未扩展的 的 标记的分解<general text>
;参见\showtokens
。效果就像是 在只有 10 和 12 的范围内\scantokens
应用于。请注意,为了保留控制字和任何后续字母之间的边界,每个控制字(包括最后一个控制字)后都会产生一个空格。<general text>
\catcodes
用简单的英语来说这是什么意思?我想理解这段代码:
\def\task#1{\@task#1::\@nil}
\def\@task#1:#2:#3\@nil{%
\if\relax\detokenize{#2}\relax
...
我认为\task
被定义为一个宏,它接受一个参数,并调用\@task
。我不知道这是什么\@nil
意思——它可能用于结束宏调用。我也不知道\relax
和\detokenize
做什么,但 detokenize 接受 参数的第二部分task macro
(各部分用分号分隔)。
答案1
\task
接受一个参数,将其传递给 ,\@task
其定义方式是,它的参数是分隔;如果调用的是
\@task xyz:AB:cde:u\@nil
第一个参数是xyz
,第二个参数是 ,AB
第三个参数是cde:u
。这里\@nil
没有任何意义,它只是 的语法所要求的,\@task
而 TeX 会将其丢弃。
\relax
是 TeX 的一个原语,它的功能是“不做任何事”。测试
\if\relax\detokenize{#2}\relax
是确定参数是否#2
为空的安全方法。如果为空,\detokenize{#2}
则扩展为零,因此\if
比较标记\relax
和\relax
,它们确实相等,因此遵循“真”分支,该分支在第二个之后立即开始\relax
,直到并且不包括\else
。如果#2
不为空,假设它是30
,\if
将\relax
与哪些不同,因此遵循“假”分支,该分支在直到并且不包括3
之后开始。[1]\else
\fi
类似的构造\if\relax#2\relax
并非在所有情况下都有效,因为“就 \if 而言,所有控制序列都是相等的” [2]。如果#2
是\relax
(或任何其他控制序列,可能后面跟着其他标记),它将不起作用!因此,我们使用它,正如 Joseph 所解释的那样,将所有内容拆分成一个字符串。因此\detokenize
,即使在奇怪的情况下,也会将标记与#2
\relax
\if
\relax
特点 \
,它们是不同的。
[1] 这并非完全正确,但对于本描述的目的而言,这是一个近似的事实。
[2] TeX 按主题分类(第 13.2.1 节)
答案2
该\detokenize
原语将其所有输入转换为类别代码 12(“其他”)标记,但空格除外,空格仍保留为类别代码 10(“空格”)。它用于将标记转换为字符串。例如,如果我们有
\detokenize{\foo}
那么\foo
就是一个控制词,IE一个标记,它被转换成 5 个字符串字符(\
、f
、o
、o
、),所有这些都是除空格之外的“其他”字符,空格是“空格”。请注意此处末尾的额外空格:
\detokenize
在每个“控制字”后添加一个空格(见下文)。
我将一步一步地介绍你的例子。首先,\@nil
在这里用作分隔符。的定义\@task
意味着参数必须包含:
,然后:
再次包含,最后包含\@nil
。这用于“整理”尴尬的输入
\task{stuff:more stuff}
将会变成
\@task stuff:more stuff::\@nil
意思#1
是 是stuff
,#2
是more stuff
和#3
是:
。这样可以确保所有东西都“用完了”:这是常见的要求。
要查看\detokenize
实际效果,请尝试以下操作
\documentclass{article}
\usepackage[T1]{fontenc}
\edef\test{\detokenize{\test}}
\show\test
\begin{document}
\detokenize{\test}
\end{document}
关于用 增加空格的更多\detokenize
信息,实际上更一般地讲。每当 TeX 将可以作为一个或多个标记的内容写成“字符串”时,它总是在每个“控制字”(转义字符后跟一个或多个“字母”)后插入一个空格,以避免混淆。例如,使用
\catcode`\X=12 % 'Other'
\def\foo{\barX}
\meaning\foo
你得到
macro:-> \bar X
原文中没有空格,但告诉我们这\bar
是控制序列,后面跟着X
,而不是只打印\barX
,这看起来是不同的东西。这是有道理的,因为 TeX 会跳过控制字后的空格,所以就 TeX 而言,这两个版本是等效的。
遵守了这种“插入空格”行为\detokenize
,这意味着每个控制字后都会有一个空格。TeX 唯一不插入这些空格的地方是\string
,它只能在单个标记上使用,因此在不可能“混淆”的地方使用。