为什么运行 \endenvironment 后会出现 \@checkend?

为什么运行 \endenvironment 后会出现 \@checkend?

有人知道为什么在 LaTeX 定义中\end\@checkend命令在运行结束环境代码后出现吗?似乎出于捕获错误的目的,最好尽快让用户知道出了问题。

我问这个问题是因为我正在开发几个环境envaenvb并且不小心说了

\begin{enva}
% some stuff
\end{envb}

在 中抛出一些低级错误\endenvb。为了防止这种情况,我必须\@checkend在 中放入自己的样式检查\endenvb,这似乎是\begin我们\end应该为我做的一部分。

作为该问题的一个简单示例,请考虑以下代码:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\def\test{}
\begin{test}
\end{tikzpicture}
\end{document}

这会出现错误:

! Undefined control sequence.
\endtikzpicture ...r@layerlist@globally \endscope 
                                                  \let \pgf@baseline =\pgf@s...
l.10 \end{tikzpicture}

这并没有我所期望的那么有启发性。我想防止类似的无用错误出现在我自己的代码中。

\end作为参考,我为解决这个问题所做的就是编写以下命令,将其放在每个环境的代码开头:

% #1 -- the name of the environment being ended
\def\mypkg@checkend#1{
    \def\mypkg@tempa{#1}
    \ifx\mypkg@tempa\@currenvir\else % mismatch
        \mypkg@error{endenv-mismatch}
        \csname end\@currenvir\endcsname % run the \end code for the correct environment
        \def\@currenvir{#1} % Prevent \@checkend from throwing a second redundant error
        \expandafter\mypkg@break % don't run the rest of \endthisenvironment
    \fi
}

答案1

一个环境的实现可以包含其他环境:

\newenvironment{foo}{\begin{center}}{\end{center}}

如果\@checkend在“结束”代码的开头被调用,它将在center这里的内部被调用。\@checkend “结束”部分(\end<environment>)允许正确关闭在“开始”部分打开的其他环境。

答案2

此外Heiko 的回答,还要注意,在涉及表的地方,环境结束代码可能需要通过扩展来工作。可以通过将\end...宏设为受保护的宏来看到这一点,而无需移动(不可扩展的)定义:

\documentclass{article}
\newenvironment{foo}[1]
  {\begin{tabular}{#1}}{\end{tabular}}
\begin{document}
\fbox{%
  \begin{foo}{ccc}
    \hline
    Test & a & b \\
    \hline
  \end{foo}
}
\protected\edef\endfoo{\unexpanded\expandafter{\endfoo}}
\fbox{%
  \begin{foo}{ccc}
    \hline
    Test & a & b \\
    \hline
  \end{foo}
}
\end{document}

例如,xparse发展

相关内容