显然,我一直误以为,如果你定义了一个名为<env_name>
then的环境\begin<env_name>
,它就能\<env_name>
完成同样的事情。但考虑到@egreg 的告诫和我尝试实施他的建议,我发现自己大错特错。
有时我想定义一个新环境或一个调用环境的命令,但过早扩展\begin{<env_name>}
会导致错误。以下是我所考虑的 MWE:
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{fancyvrb}
\makeatletter
\pgfkeys
{
/ae/mwe/.is family,
/ae/mwe,
usegobble/.initial=,
gobble/.style = { usegobble={gobble=#1,} },
}
\newenvironment{aetestingmwe}[1][]
{%%'
\pgfqkeys{/ae/mwe}{#1}%%'
\edef\ae@begin@verbatim
{%%'
\noexpand\Verbatim[\pgfkeysvalueof{/ae/mwe/usegobble}]}%%'
\ae@begin@verbatim
}
{
\endVerbatim
}
\makeatother
\pagestyle{empty}
\begin{document}
\begin{aetestingmwe}
[
gobble=2,
]
\textbf{Random stuff}
This line will get decapitated!
\end{aetestingmwe}
\end{document}
如果我尝试将环境定义为
\newenvironment{aetestingmwe}[1][]
{%%'
\pgfqkeys{/ae/mwe}{#1}%%'
\begin{Verbatim}[\pgfkeysvalueof{/ae/mwe/usegobble}]
}
{
\end{Verbatim}
}
我会收到一个错误:
! Package keyval Error: gobble=2, undefined.
See the keyval package documentation for explanation.
Type H <return> for immediate help.
...
l.27 ]
?
因此看来有时有必要用\<env_name>
代替\begin{<env_name>}
。
我如何知道何时可以安全地假设这两者相同?何时它们不同?环境是使用低级命令还是 LaTeX 定义的是否重要\newenvironment
?使用创建的环境又如何呢xparse
?
答案1
\begin{<env_name>}
并且\<env_name>
几乎从来不做同样的事情。
通常情况下
\begin{<env_name>}
(除了错误检查)与
\begingroup\<env_name>
根据所涉及的代码,额外的分组可能会或可能不会重要。
那么,有哪些不寻常的情况......
document
出于效率原因,
document
环境不构成组。 的定义\document
以 开头,\endgroup
因此如果您\document
单独使用,则会出现错误,但如上所述,您应该与之比较的是\begingroup\document
哪个实际上会起作用。(但无论如何您都不应该嵌套document
环境。)lrbox
与 一样
document
,lrbox
需要外部组,因此如果您想避免环境形式,则需要使用\begingroup\lrbox
...。\endlrbox\endgroup
这里的问题是lrbox
本地将其内容保存在盒子寄存器中,因此使用了一些\aftergroup
技巧,以便盒子寄存器具有该值后环境。如果您使用\lrbox
未被组包围的令牌,那么此\aftergroup
令牌将出现在某个地方,但可能不是您想要的位置。\ignorespacesafterend
其最终代码内包含的环境。此命令仅设置一个布尔标志,该标志在 的定义中被拾取,
\end
这会导致它发出\ignorespaces
。因此,如果您使用\end<env_name>
而不是 ,\end{env_name}
将由\ignorespaces
发出,这确实会结束当前组,如果组以或明确\end
结束,则根本不会发出。这可能是您想要的行为,但无论如何它都是有区别的。}
\endgroup
类似逐字的环境
内部
verbatim
和类似的宏\end
不会触发命令,\end
因为\
没有什么特别的,\end
只是四个标记\
e
n
d
。因此它像环境一样工作,定义使用分隔参数宏定义,就像通过\def\@@@something#1\end{verbatim}{...}
这意味着预期的环境名称
\end{verbatim}
必须逐字出现在文档中。\endverbatim
(即使使用合适的 catcode 设置)也不会形成此类宏的结束分隔符。verbatim
在LaTeX 的原始定义中,verbatim
代码中是明确的,因此环境根本不能嵌套在宏中。verbatim
(以及大多数后期软件包)使这一点更加灵活,因为如果您使用\verbatim
而不是\begin{verbatim}
代码\verbatim
将拾取当前的Verbatim
环境并使用它来定义终止环境的分隔宏(或其他测试)。因此,listings
如果它们被调用为宏,则可以嵌套在另一个环境定义中,但如果该\begin
\end
形式在内部使用,则不能嵌套。抓住他们的身体作为宏观参数的环境。
一些环境(值得注意的是并且可能最初是
amsmath
诸如 这样的环境align
)、tabularx
,以及通过包定义定义的任何环境environ
。使用类似于上面描述的机制来通过宏参数抓取它们的主体(在 的情况下verbatim
定义为)。\BODY
environ