Почему \@checkend возникает после запуска \endenvironment?

Почему \@checkend возникает после запуска \endenvironment?

Кто-нибудь знает, почему в определении LaTeX \endкоманда \@checkendпоявляется после запуска кода конечной среды? Похоже, что для целей отлова ошибок лучше всего дать пользователю знать, что что-то не так, как можно скорее.

Я спрашиваю это, потому что я разрабатываю несколько сред envaи envbслучайно говорю

\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бы он был вызван прямо в начале кода «end», он был бы вызван внутри center, здесь.\@checkend послечасть «конец» ( \end<environment>) позволяет правильно закрыть другие среды, открытые в части «начало».

решение2

В дополнение кОтвет Хайко, также обратите внимание, что может быть необходимо, чтобы код конца среды работал с расширением, где задействованы таблицы. Это можно увидеть, не перемещая (нерасширяемое) определение, сделав макрос \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разработка.

Связанный контент