\NewEnviron で「引数が暴走しましたか?」というエラーが発生する

\NewEnviron で「引数が暴走しましたか?」というエラーが発生する

ファイルは 2 つあります。基本的に、メイン ファイルは environ パッケージをロードし、セカンダリ ファイルを入力します。セカンダリ ファイルは基本的に何もしない環境を作成し、その環境のインスタンスを 1 つ作成します。

メイン.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を入力する代わりに、secondary.texの内容をmain.texに直接配置します。

なぜこれが機能しないのでしょうか?

答え1

environ定義で TeX パラメータ テキストを使用して環境の内容をキャプチャする環境を作成します。このパラメータ テキスト スタイルの定義により、パッケージは環境の内容をキャプチャできますが、マクロ/定義の非常に厳格な使用も必要になります。これは、コマンド スタイルの環境 ( \myenv...\endmyenvではなく) を使用する場合には従わない\begin{myenv}ことです\end{myenv}

大まかに言えば、環境の開始を指定する\NewEnviron{myenv}マクロを作成し、このマクロは\myenvその通り \end{myenv}...他には何もありません。

この例は\input明示的な \end{<something>}を探しています。の類似点が見つかる前に\myenvの終わりに到達します。 実際に探しているのは です(下記参照)。secondary.tex\end\end{document}

問題が解決したとあなたが言及した 3 つの例を見て、なぜそうなるのかを見てみましょう。

  • \newenvironment代わりに使用する\NewEnviron

    これが機能する理由は明らかです。 はと の\newenvironment{myenv}両方を定義しているため、環境のコマンド定義を使用すると問題なく機能するはずです。\myenv\endmyenv

  • \begin{myenv}...\end{myenv}代わりに使用する\begingroup\myenv...\endmyenv\endgroup

    environこれはまさに、を使って環境を定義するときに使用すべきものです\NewEnviron。つまり、これはすぐに使えるので、明示的に環境終了を使用しました\end{myenv}

  • を入力する代わりに、内容をsecondary.tex直接入力してくださいmain.texsecondary.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} を見つける必要があります。

関連情報