我注意到具有可选参数的环境的行为会\obeylines
根据可选参数是否存在而改变。
我原本以为下面示例中的所有环境看起来都一样。但有一个环境不同。
发生了什么事?我是否可以在 的定义中添加一些内容,bbb
以使其在存在可选参数时表现得像所有其他内容一样?
\documentclass{article}
\NewDocumentEnvironment{aaa}{}{\obeylines ENV:}{}
\NewDocumentEnvironment{bbb}{o}{\obeylines ENV:}{}
\NewDocumentEnvironment{ccc}{o}{ENV:}{}
\begin{document}
\begin{aaa}
x
y
\end{aaa}
\begin{bbb}
x
y
\end{bbb}
\begin{bbb}[arg]
x
y
\end{bbb}
\begin{ccc}\par
x\par
y\par
\end{ccc}
\begin{ccc}[arg]\par
x\par
y\par
\end{ccc}
\end{document}
输出
答案1
问题“显然”是(*)可选参数抓取器尝试对换行符进行标记,该换行符在\obeylines
执行之前通常具有 catcode 5(“行尾”),这会将其 catcode 更改为 13(活动)。
由于需要对以下标记进行标记以确定是否存在可选参数,因此这是不可避免的。
(理论上,可以使用scantokens
它来“取消标记”。实际上,这会对性能造成影响,如果不设置,\everyeof
用户可能会遇到更令人困惑的错误,甚至可能还会造成混淆\errorcontextlines
)
解决方法是设置\endlinechar
前 解析可选参数。目前最简洁的方法是(据我所知)定义辅助宏/环境。
%! TEX program = lualatex
\documentclass{article}
\NewDocumentEnvironment{aaa}{}{\obeylines ENV:}{}
\NewDocumentEnvironment{innerbbb}{o}{ENV:}{}
\NewDocumentEnvironment{bbb}{}{\obeylines\innerbbb}{\endinnerbbb}
\NewDocumentEnvironment{ccc}{o}{ENV:}{}
\begin{document}
\begin{aaa}
x
y
\end{aaa}
\begin{bbb}
x
y
\end{bbb}
\begin{bbb}[arg]
x
y
\end{bbb}
\begin{ccc}\par
x\par
y\par
\end{ccc}
\begin{ccc}[arg]\par
x\par
y\par
\end{ccc}
\end{document}
附注:使用简单形式\innerbbb
是因为根据其他环境来定义环境:正确的方法是什么?
附注 2,这会使错误消息对于失控的可选参数(即你忘记输入]
)有点混乱,报告环境名称innerbbb
而不是bbb
! File ended while scanning use of \environment innerbbb .
(*)如果你有丰富的 TeX 编程经验