Ошибка «Вышедший из-под контроля аргумент?» с \NewEnviron

Ошибка «Вышедший из-под контроля аргумент?» с \NewEnviron

У меня есть два файла. По сути, основной файл просто загружает пакет environ и вводит вторичный файл. Вторичный файл создает среду, которая по сути ничего не делает, и создает один экземпляр этой среды:

main.tex:

\documentclass{scrartcl}
\usepackage{environ}
\begin{document}
  \input{secondary.tex}
\end{document}

вторичный.tex:

\NewEnviron{myenv}{\BODY}
\begingroup
  \myenv
    Hello
  \endmyenv
\endgroup

Я получаю следующее сообщение об ошибке:

Runaway argument?
Hello \endmyenv \endgroup \par
! File ended while scanning use of \document.
<inserted text>
                \par
l.5 \input{secondary.tex}

Пример работает так, как и ожидалось, если я внесу любое (!) из следующих изменений:

  • Использовать \newenvironmentвместо\NewEnviron
  • Использовать \begin{myenv}...\end{myenv}вместо\begingroup\myenv...\endmyenv\endgroup
  • Поместите содержимое secondary.tex непосредственно в main.tex вместо ввода secondary.tex

Почему это не работает?

решение1

environсоздает среду, которая использует текст параметров TeX в определениях для захвата содержимого среды. Это определение стиля текста параметров позволяет пакету захватывать содержимое среды, но оно также требует очень строгого использования макросов/определений... чего вы не придерживаетесь при использовании среды в командном стиле ( \myenv... \endmyenvвместо \begin{myenv}... \end{myenv}).

В общем, \NewEnviron{myenv}создает макрос\myenv , который обозначает начало среды, и этот макрос находится в поискеточно \end{myenv}... ничего больше.

Пример не работает при использовании\input так как нетявный \end{<something>}который \myenvищет. Он достигает конца, secondary.texпрежде чем находит хоть какое-то сходство с \end. Он на самом деле ищет \end{document}(см. ниже).

Давайте рассмотрим три упомянутых вами случая устранения проблемы и выясним, почему это так:

  • Использовать \newenvironmentвместо\NewEnviron

    Должно быть очевидно, почему это работает. \newenvironment{myenv}определяет и , \myenvи \endmyenv, поэтому использование определения команды среды должно работать без проблем;

  • Использовать \begin{myenv}...\end{myenv}вместо\begingroup\myenv...\endmyenv\endgroup

    Это именно то, что environвы должны использовать, когда определяете среду с помощью\NewEnviron . Итак, это работает из коробки, поскольку выявноиспользовалось завершение среды \end{myenv};

  • Поместите содержимое secondary.texнепосредственно в main.texвместо вводаsecondary.tex

    Поскольку вы используете командную форму окружения, «текущее окружение» (известное LaTeX как \@currenvir) на самом деле никогда не меняется. То есть, оно остается внутри documentокружения (из-за вызова \begin{document}). Таким образом, ваш захват конца окружения фактически \end{document}соответствуетnewenviron настройке . Вашсреда«начинается» с \myenvи заканчивается на \end{document}. Странно, но именно так это и работает, когда вы не используете ожидаемую область видимости среды \begin{...}... \end{...}.

Для правильной работы в контексте newenvironиспользуйте область действия \begin{myenv}... \end{myenv}. Эта область действия обеспечивает необходимую группировку, которую вы реализуете посредством \begingroup... \endgroup.

В качестве альтернативы определите \myenvзахват содержимого до тех пор, пока оно не достигнет \endmyenv:

\documentclass{scrartcl}
\usepackage{filecontents}
\begin{filecontents*}{secondary.tex}
\long\def\myenv #1\endmyenv{#1}% Fake myenv environment that captures its body
\begingroup
  \myenv
    Hello
  \endmyenv
\endgroup
\end{filecontents*}
\begin{document}
\input{secondary.tex}
\end{document}

решение2

Оно делаетнетработает, если вы поместите содержимое в основной файл. Только не выдает ошибку. Попробуйте это:

\documentclass{scrartcl}
\usepackage{environ}
\begin{document}
\NewEnviron{myenv}{BEGIN\BODY END}
\begingroup
  \myenv
    Hello
  \endmyenv
\endgroup

World

\end{document}

Environ необходимо найти \end{myenv}, чтобы остановить синтаксический анализ.

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