У меня есть два файла. По сути, основной файл просто загружает пакет 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}, чтобы остановить синтаксический анализ.