我正在研究 LamsTeX,一种旧的 TeX 格式,因为它有一些有趣的宏。我发现了这个文章关于它。在文章中我们可以读到
\bitem \LaTeX\ 中许多刚刚被解决的难题在 \LamSTeX{} 中根本不存在。例如,\LamSTeX{} 中不存在“脆弱”命令,也不用担心长 |\write| 和 |\write| 到辅助文件(如 |.toc| 文件)的意外扩展。任意长的文字模式材料可以拆分到多个页面。
因此,我开始感兴趣,并对 LamsTeX 进行了一些实验。查看.toc
自动生成的文件,我发现 LamsTeX 保存所有控制序列而不进行扩展,就像它们都使用 LaTeX 或 OPmac 术语“保护”一样。这让我产生了一个问题:在编写控制序列之前,为什么要对其进行扩展?直接编写而不进行扩展不是更好吗?
我查看了与此论点相关的其他问题,但我找不到这个问题的答案。
答案1
保存到临时文件时通常有四个字段包含有关部分的信息:
控制序列位于所有其他控制序列之前,当使用 再次读取数据时执行
\input
。在写入过程中不得扩展。章节等的数量必须立即扩充。
章节的标题。撰写时不应展开。
页码。在 期间必须展开
\shipout
。
LaTeX 将第三个字段管理为:“在 期间扩展它\shipout
,但使用\noexpand
所谓的健壮命令的扩展”。OPmac 做了类似的事情,只有标记为“受保护”的控制序列才会\relax
在 期间被设置\shipout
。但还有另一种方法,它绝对不会在 期间扩展章节标题\shipout
。例如,可以这样做(需要经典 TeX,不需要 eTeX)。
\newcount\secnum
\newwrite\outfile
...
\def\meaninga#1{\expandafter\meaningb\meaning#1\relax}
\def\meaningb#1->#2\relax{#2}
\def\sec#1\par{\advance\secnum by1
\def\tmp{#1}\edef\tmp{\string\secX{\the\secnum}{\meaninga\tmp}}%
\write\outfile\expandafter{\tmp{\the\pageno}}%
...
}
第一个字段\secX
在这里受 保护\string
。第二个字段在\the\secnum
这里在 期间扩展\edef\tmp
。第三个字段(章节标题)使用原始值保护\meaning
,即在\edef\tmp
处理时立即被反标记化。第四个字段是\the\pageno
,它在 期间扩展\shipout
。也许在 LamsTeX 中做了类似的事情(我不知道具体情况)。
当然,如果我们有 eTeX,那么我们可以使用\detokenize
原始方法更直接地进行去标记化。而替代的“保护”方法也可以更直接地完成:使用\protected\def
。
请注意,您不能将其用于\the\toks
部分标题的扩展保护,因为这不会进行目录代码更改,并且您无法及时使用,\the\toks
因为\shipout
一页上可以有多个部分。