在这个问题中我并不是要求代码。
在开始实施之前,我想问一下:您认为哪个方向最有意义?
我将要定义一个完全可扩展的宏,用于 LaTeX 2ε,它在某种尾部递归循环中逐个标记地检查其参数。
一项要求是:如果发现可扩展标记,则应在检查期间对其进行扩展,除非它前面有\noexpand
或\protect
和/或 是根据 定义的\protected
。
\protected
可以通过检查 来处理根据 定义的标记的情况\meaning
。尾部递归循环可以用一个参数来实现,该参数包含一个“标志”标记,指示在上一次迭代中处理的标记是控制字标记还是\protect
具有与 -primitive 相同的含义\noexpand
。
检查\noexpand
-meaning 和“为下一次迭代设置标志”可以通过 -comparison 来处理\ifx
。(您可能\noexpand
在某个时间点“复制” -primitive,而此时它肯定还没有被重新定义。)
剩下的问题是如何处理边缘情况:
- 某些人可能暂时重新定义了控制字标记,
\protect
以使其暂时不再是 LaTeX 2ε 保护机制的组成部分。 - 某些人可能会暂时使用一个令牌
\protectcopy
(这\let
相当于\protect
在某个处理阶段)。
如何检查该令牌\protect
当前是否被用作 LaTeX 2ε 保护机制的组成部分?
\protect
如何检查其他标记当前的使用方式是否与 LaTeX 2ε 中通常使用该标记的方式相同?
我倾向于做两件事:
- 检查控制字标记
\protect
本身,例如通过分隔参数。 \protect
检查作为 LaTeX 2ε 保护机制的组成部分时可能具有的含义之一。
这够了吗?
所讨论的标记既是控制字标记\protect
,又具有可以具有的含义之一\protect
(\relax
/ \string
/ \noexpand
/ \noexpand\protect\noexpand
),这是否足以假设所讨论的标记用作 LaTeX 2ε 保护机制的组成部分?
顺便问一下: expl3 相当于什么\protect
?
答案1
在 的代码中\text_expand:n
,旨在采用“广泛文本”并扩展任何隐藏内容,所采用的方法如下。
首先,请注意工作顺序的重要性。特别是,在进行各种“过滤”测试后,必须考虑宏或基元的扩展。
LaTeX2e 中的标记\protect
必须具有完全相同的名称才能使用\protected@edef
等等。因此,\text_purify:n
通过名称而不是定义对其进行测试:这是通过使用来完成的,\pdfstrcmp
因为这使得基于字符串的可扩展测试变得容易。因此,此过程不会拾取具有同等含义的其他标记。
不使用标志,如果找到\protect
,则可以抓取下一个标记并在一次循环中处理它。无论如何,这种“向前看”的能力对于任何扩展都是必需的。在中\text_purify:n
,我选择重新组合\protect\foo[space]
到\foo
如果该构造存在 - 需要一点努力,但“撤消”了原本令人困惑的扩展。
在这种方案中,不仅需要扩展宏,还需要扩展可扩展原语。这涉及 'raw' \noexpand
,它将完成其工作,以便将下一个标记视为\relax
。
从expl3
术语上讲,没有直接等效于\protect
e-TeX。因此,不可扩展的宏可能是\protected
,并且更多的机器周期的可用性意味着这种类型的 token-ise 分析是可行的。这意味着expl3
token 在或类似中应该始终是“安全的” \edef
。(内部宏以及记录的 API 遵循相同的规则:\protected
在扩展上下文中可以安全使用。)