在此邮政,一个答案指出\obeylines
定义为
\def\obeylines{\catcode`\^^M\active \let ^^M\par }
然而当我尝试编译以下代码时,TeX 会抱怨
\def\obeylines{\catcode`\^^M\active \let ^^M\par }
\def\disobeylines{\catcode`\^^M=5 }
\obeylines
We obey, and end up on separate lines.
We obey.
\disobeylines
We disobey, and end up on the same line.
We disobey.
\bye
当我将第一行改为
\def\obeylines{\catcode`\^^M=13 \let^^M=\par }
这段代码为什么不起作用?
答案1
当 TeX 执行 时\def
,它只会将标记与其当前的类别代码一起存储。在你的情况下,你正在存储
\catcode
•`
12 •\^^M
•\active
•\let
^^M
5 •\par
(项目符号分隔标记)。因此,当您的\obeylines
宏被调用时,^^M
它将变为活动状态,但\let^^M
会抛出“缺少控制序列”的错误。
其实,这种分析并不完全正确,因为^^M
定义主体中的 with 类别代码 5 将导致该行结束并被\par}
忽略。所以你得到的错误是不同的。对其他字符执行类似操作也会遇到上述相同的问题。
如果你往里看,plain.tex
你会看到
% In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
% since this allows, for example, `\let\par=\cr \obeylines \halign{...'
{\catcode`\^^M=\active % these lines must end with %
\gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
\global\let^^M\par} % this is in case ^^M appears in a \write
所以实际存储的是
\catcode
•`
12 •\^^M
•\active
•\let
^^M
13 •\par
它可以完成这项工作。\global\let^^M\par
可以不带\global
,但如果出现分页符,则可能会出现问题。
答案2
您需要^^M
在定义时处于活动状态,以便\let^^M\par
合法。查看 plain.tex 了解一种方法。