环境如何运作?

环境如何运作?

据我了解,当我指定

\newenvironment{env}{
  start
}{
  end
}

LaTeX 实际上做的是定义两个宏

\env -> start 
\endenv -> end

以便

\begin{env}
  middle
\end{env}

解析为类似

{
  \env
  middle
  \endenv
}

  • 我的看法是否正确且完整?
  • 还有其他事吗\newenvionment\begin要做\end什么?
  • \newenvironment我是否可以不通过定义\env和来创建环境\endenv?是否有可能从中受益的情况?
  • 不使用\envand是否安全?例如,避免分组。\endenv\begin\end
  • 有何xparse不同\NewDocumentEnvironment

许多问题,都由一个请求相关:请解释环境和相关命令如何工作。

答案1

LaTe2e 环境实现的基础知识涵盖LaTeX 如何实现环境?。在xparse,该方法稍微复杂一些,以便允许#1ETC。在环境代码的末尾有一个动态定义。但是,对性能的影响很小。在 LaTeX2e 之上,仍然需要进行设置\foo\endfoo因为这就是\begin我们\end想要的。但是,长期愿景是为环境代码提供专用的命名空间,xparse因此为此目的包括第二层宏。

答案2

仅部分答案:

  • 环境\newenvironment确实定义了\env\endenv(如果用作env参数)

    但是\env...\endenv不是组安全的,请参见下面示例中长度变量的设置。

  • 无法定义\newcommand{\otherenv}\newcommand{\otherendenv},因为这会导致错误:

!LaTeX 错误:命令 \endotherenv 已定义。或名称 \end... 非法,请参阅手册第 192 页。

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.

\end...大约一年前,我曾问过有关宏的类似问题:\end.... 宏名称在 LaTeX2e 中保留吗?

但是,可以说\def\otherenv\def\endotherenv。事实上,LaTeX 核心或包中定义了多少个 LaTeX2e 环境——例如,enumerate\def\enumerate\def\endenumerate而不是使用\newenvironment{enumerate}


\documentclass{article}

\newenvironment{env}{}{}
\newlength{\mylength}
\setlength{\mylength}{10pt}

\begin{document}


\begin{env}
\addtolength{\mylength}{20pt}
\end{env}

Result after: \the\mylength $\longrightarrow$ safe!

\env

\addtolength{\mylength}{20pt}

\endenv

Result after: \the\mylength $\longrightarrow$ not safe!

% Now some grouping:    
{
\env

\addtolength{\mylength}{20pt}

\endenv
}

Result after: \the\mylength $\longrightarrow$ safe again!

\end{document}

在此处输入图片描述

此外,用 定义的环境\newenvironment具有“自我意识”(好吧 ;-))——它知道当前环境名称,但只有在\begin{env}...\end{env}使用 时才知道,而不是用\env...\endenv{\env...\endenv}

看第二个例子:

\documentclass{article}

\makeatletter
\newcommand{\ShowEnvName}{%
Current environment:  \@currenvir

}
\makeatother


\newenvironment{env}{}{}

\begin{document}
\begin{env}
\ShowEnvName  : Should be \texttt{env}
\end{env}

\env
\ShowEnvName  : Presumed to be \texttt{env}, but is \texttt{document}
\endenv

{
\env
\ShowEnvName  : Presumed to be \texttt{env}, but still is \texttt{document}
\endenv
}


\env
{
\ShowEnvName  : Presumed to be \texttt{env}, but still is \texttt{document}
}
\endenv


\end{document}

一旦没有\begin...\end配对,它就会显示外部环境名称 - 这就是\begin...\end设置\@currenvir宏所做的 -->。

在此处输入图片描述

来自(或参见 texdoc source2e)和latex.ltx的定义:\begin\end

\def\begin#1{%
  \@ifundefined{#1}%
    {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
    {\def\reserved@a{\def\@currenvir{#1}%
     \edef\@currenvline{\on@line}%
     \csname #1\endcsname}}%
  \@ignorefalse
  \begingroup\@endpefalse\reserved@a}
\def\end#1{%
  \csname end#1\endcsname\@checkend{#1}%
  \expandafter\endgroup\if@endpe\@doendpe\fi
  \if@ignore\@ignorefalse\ignorespaces\fi}
\def\@checkend#1{\def\reserved@a{#1}\ifx
      \reserved@a\@currenvir \else\@badend{#1}\fi}

\begin首先检查环境是否完全定义,并在错误分支中给出错误。如果成功,则将变量@currenvir设置为环境,\csname #1\endcsname\env调用并\begingroup启动。

\end检查正确的环境是否此时关闭,即如果之后尚未打开\begin{env}...\end{otherenv}\end{env}则会出错。otherenvenv

相关内容