(我知道之前也有过类似的问题,但这个问题有点不同)
我想要一个逐字宏,它使用一个不太可能的字符作为逐字结束标记(不太可能,因为它不太可能包含在将成为逐字的文本中),并从附录 D 中查找了一些建议TeXbook,直到有件事引起了我的注意:
另一种方法是保持一个字符不可触碰。例如,可以定义一些东西,以便
\verbatim⟨char⟩⟨text⟩⟨char⟩
逐字排版⟨text⟩
,其中不应⟨text⟩
包含任何重复的分隔符⟨char⟩
:\def\verbatim{\begingroup\setupverbatim\doverbatim} \def\doverbatim#1{\def\next##1#1{##1\endgroup}\next}
现在,将其与 XeTeX 结合使用,我可以使用来自广泛 Unicode 范围的字符作为结束标记。(基于我可以做的发现,例如\def\fi{foo}
,它可以工作。)
唉,在上面添加附录 D 中前面提到的宏:
\def\setupverbatim{\tt\def\par{\leavevmode\endgraf} \catcode`\`=\active \obeylines\uncatcodespecials\obeyspaces} \def\uncatcodespecials{\def\do##1{\catcode`##1=12 }\dospecials}
并尝试一下( fi 字符是 Unicode fi-ligature),
\verbatim fi |\%_^foo{\it bar}
baz
fi
\bye
给出有关 的错误Missing $
,这意味着\verbatim
宏有些地方无法正常工作。我就是搞不清楚是什么问题。
答案1
它是 后面的空格字符\verbatim
。
更改空格字符的 catcode 后,它不再被视为空格。考虑以下输出
\def\a#1\relax{`#1'}
\def\b{\catcode`\ =12 \a}
\a \relax
\b \relax
\bye
因此,您的示例仅以fi
逐字模式排版,并在遇到 后的第二个空格后恢复正常fi
。
因此你需要有一个分隔符立即地因此\verbatim
它的 catcode 不能是“字母”,否则它将被视为控制序列名称的一部分。
答案2
以下代码定义\verb
命令:
\catcode`\@=11%
\def\verb{\expandafter\verb@make\string}%
\def\verb@make#1{\begingroup\tt%
\let\verb@delim=#1% Save the delimiter.
\def\verb@print##1{%
\if##1\verb@delim% If we found the end delimiter, end the group.
\def\verb@print{\def\verb@print{}\endgroup}%
\else%
##1% Print the char
\fi%
\expandafter\verb@print\string% Continue reading the next char.
}%
\expandafter\verb@print\string% Start reading.
}%
\catcode`\@=12%
一些例子:
\verb|{$x^y{}$\abc}|
\verb!{$x^y{}$\abc}!
\verb~${x^y{}$\abc}~
以上所有内容均产生逐字结果${x^y{}$\abc}
。
答案3
问题出在 后面的空格上\verbatim
,Andrey 发现了这一点。需要注意的是, 后面的空格\verbatim
会终止对控制序列名称的扫描,但不会立即将其标记化,因为在控制序列名称之后,TeX 必须进入“跳过空白状态”;因此, 后面的空格实际上是\verbatim
被扩展并\setupverbatim
更改了空格的类别代码后读取的。
如果您不想对可以分隔逐字片段的字符进行限制,则可以进行改进\doverbatim
:
\def\doverbatim#1{%
\def\next{#1}%
\ifx\next\activespacemacro
\expandafter\doverbatim
\else
\def\next##1#1{##1\endgroup}%
\expandafter\next
\fi}
{\obeyspaces\gdef\activespacemacro{ }}
行尾不能用作分隔符(可以添加另一个测试)。后面可以跟任意数量的空格\verbatim
。
很好奇为什么你的代码会出现这个错误,但也很容易:fi
made之后的空格\verbatim
终止了它的效果,排版就像逐字逐句的一样fi
。