什么时候可以安全地假设 \begin{} 和 \做同样的事

什么时候可以安全地假设 \begin{} 和 \做同样的事

显然,我一直误以为,如果你定义了一个名为<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

    与 一样documentlrbox需要外部组,因此如果您想避免环境形式,则需要使用\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定义为)。\BODYenviron

相关内容