Eu tenho dois arquivos. Basicamente, o arquivo principal apenas carrega o pacote ambiental e insere o arquivo secundário. O arquivo secundário cria um ambiente que basicamente não faz nada e cria uma instância desse ambiente:
principal.tex:
\documentclass{scrartcl}
\usepackage{environ}
\begin{document}
\input{secondary.tex}
\end{document}
secundário.tex:
\NewEnviron{myenv}{\BODY}
\begingroup
\myenv
Hello
\endmyenv
\endgroup
Eu recebi a seguinte mensagem de erro:
Runaway argument?
Hello \endmyenv \endgroup \par
! File ended while scanning use of \document.
<inserted text>
\par
l.5 \input{secondary.tex}
O exemplo funciona conforme esperado quando faço qualquer (!) das seguintes alterações:
- Use
\newenvironment
em vez de\NewEnviron
- Use
\begin{myenv}...\end{myenv}
em vez de\begingroup\myenv...\endmyenv\endgroup
- Coloque o conteúdo de secundário.tex diretamente em main.tex em vez de inserir secundário.tex
Por que isso não funciona?
Responder1
environ
cria um ambiente que usa texto de parâmetro TeX em definições para capturar o conteúdo do ambiente. Esta definição de estilo de texto de parâmetro permite que o pacote capture o conteúdo do ambiente, mas também requer um uso muito estrito das macros/definições... algo que você não está aderindo ao usar um ambiente de estilo de comando ( \myenv
... \endmyenv
em vez que \begin{myenv}
... \end{myenv}
).
Em termos gerais, \NewEnviron{myenv}
cria uma macro \myenv
que designa o início do ambiente, e esta macro está à procura deexatamente \end{myenv}
... nada mais.
O exemplo falha ao usar, \input
pois não háexplícito \end{<something>}
que \myenv
está procurando. Chega ao fim secondary.tex
antes de encontrar qualquer semelhança com \end
. Na verdade, está procurando \end{document}
(veja abaixo).
Vejamos as três instâncias mencionadas que corrigiram o problema e vejamos por que isso acontece:
Use
\newenvironment
em vez de\NewEnviron
Deveria ser óbvio por que isso funciona.
\newenvironment{myenv}
define ambos\myenv
e\endmyenv
, portanto, usar a definição de comando do ambiente deve funcionar sem problemas;Use
\begin{myenv}...\end{myenv}
em vez de\begingroup\myenv...\endmyenv\endgroup
Isso é exatamente o que
environ
você espera usar ao definir um ambiente usando\NewEnviron
. Então, isso funciona imediatamente, já que vocêexplicitamenteusou a terminação do ambiente\end{myenv}
;Coloque o conteúdo
secondary.tex
diretamentemain.tex
em vez de inserirsecondary.tex
Como você está usando a forma de comando de um ambiente, o "ambiente atual" (conhecido no LaTeX como
\@currenvir
) nunca muda realmente. Ou seja, permanece como estando dentro dodocument
ambiente (devido a uma chamada\begin{document}
). Portanto, sua captura de fim de ambiente está\end{document}
de acordo comnewenviron
a configuração de. Seuambiente"começa" com\myenv
e termina com\end{document}
. Estranho, mas é assim que funciona quando você não usa o escopo do ambiente esperado\begin{...}
....\end{...}
Para que funcione corretamente no contexto de newenviron
, use o escopo \begin{myenv}
... \end{myenv}
. Esse escopo fornece o agrupamento necessário que você implementa por meio de \begingroup
....\endgroup
Alternativamente, defina \myenv
capturar coisas até atingir \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}
Responder2
Isso acontecenãofuncionará se você colocar o conteúdo no arquivo principal. Só não dá erro. Experimente isto:
\documentclass{scrartcl}
\usepackage{environ}
\begin{document}
\NewEnviron{myenv}{BEGIN\BODY END}
\begingroup
\myenv
Hello
\endmyenv
\endgroup
World
\end{document}
O Environ precisa encontrar \end{myenv} para interromper a análise.