我可以安全地这样做吗:
\newcommand\bfoo{\begin{foo}}
\newcommand\efoo{\end{foo}}
哪里foo
有标准的 LaTeX 环境?可能verbatim
环境有问题,但其他环境也有问题?这样就可以写
\bfoo
inside the foo environment
\efoo
而不是更长的
\begin{foo}
inside the foo environment
\end{foo}
我希望得到一个技术性声明,而不是“我不会这样做,因为它不可读”。事实上,我只是想知道它的含义,我不会这样做,因为我认为它不太可读。
答案1
正如您所说,任何基于查找\end{foo}
构造的操作都会失败。这包括任何逐字类操作,例如包括beamer
的frame
环境,也包括一些 AMS 数学环境,例如align
。
第二个问题是空间跳跃,因为
\begin{foo}
inside the foo environment
\end{foo}
inside
版本号前面有一个空格\bfoo
。您可能觉得这不是什么坏事,但它改变了界面的工作方式。(注意:某些环境故意\ignorespaces
在开始时加上,但这并不适用,例如lrbox
。)
答案2
在很多情况下可以使用这种快捷方式,但总的来说并不安全。
尸体收集者
突出的例子是包amsmath
。它具有这样的特点:在其显示的方程环境(收集、对齐等)中,方程编号的处理得到了改进。数字向下移动而不是与方程冲突。但为此amsmath
需要知道方程的宽度。因此,它定义了在参数文本中\collect@body
查找的宏\end
,以挖掘内部嵌套环境以找到\end
关闭环境的正确方法。
\def\collect@@body#1\end#2{...}% the relevant internal
因此\end
必须在同一级别可见,并且不能隐藏在宏、别名或组中。但是该\begin
部分不受影响,因此可以用于定义:
\newcommand{\bfoo}{}
\def\bfoo#1\efoo{\begin{foo}#1\end{foo}}
现在,\end{foo}
可以看到 中的代码\begin{foo}
。这种方法的缺点是正确嵌套存在问题:
\bfoo ... \bfoo ... \efoo ... \efoo
第一个\bfoo
会找到第一个\efoo
,而不是正确的最后一个\efoo
。解决方法:
\bfoo ... {\bfoo ... \efoo} ... \efoo
包environ
使得该方法amsmath
可以作为独立包使用。
逐字
使用已更改的 catcode 处理其主体的环境,主要是因为它们不希望主体中的宏和命令被执行。在逐字记录的情况下,它们应该不加改变地打印。但这也会影响结束宏,它被读取为字符序列,并且不会被构建和调用为宏标记。这包括\end{...}
。verbatim
环境通过查找字符序列\
、e
、n
、d
、{
、v
、 …… 作为结束标记来解决这个问题。因此\efoo
不会检测到类似的东西。
该包verbatim
使用略有不同的方法,它逐行扫描并收集标记,直到找到\end
其中包含匹配的环境名称的字符串。