\include の再定義

\include の再定義

\includeLeslie Lamport が行った不可解な選択は、ファイルを読み取る前にを発行するように を定義することでした\clearpage。これは、著者のインターフェースの観点からはあまり良い選択ではないため、しばらくの間私を困惑させていました。この質問には 2 つの部分があります。

  1. この決定には正当な理由があるのでしょうか?
  2. コマンドが再定義されると何が壊れる可能性がありますか?

以下の MWE は、そのような再定義を示しています (コマンドに という名前を付けました\includexが、 という名前でも問題なく動作します\include)。これは、 の問題を解決するために早い段階で導入されたのではないかと私は考えていますがtwocolumns、 にはこの決定を説明するものは何もありませんsource2e

\documentclass{book}
\usepackage{filecontents}
\makeatletter
\def\includex#1{\relax
  \ifnum\@auxout=\@partaux
    \@latex@error{\string\include\space cannot be nested}\@eha
  \else \@includex#1 \fi}

\def\@includex#1 {%
  %\clearpage
  \if@filesw
    \immediate\write\@mainaux{\string\@input{#1.aux}}%
  \fi
  \@tempswatrue
  \if@partsw
    \@tempswafalse
    \edef\reserved@b{#1}%
    \@for\reserved@a:=\@partlist\do
      {\ifx\reserved@a\reserved@b\@tempswatrue\fi}%
  \fi
  \if@tempswa
    \let\@auxout\@partaux
    \if@filesw
      \immediate\openout\@partaux #1.aux
      \immediate\write\@partaux{\relax}%
    \fi
    \@input@{#1.tex}%
    %\clearpage
    \@writeckpt{#1}%
    \if@filesw
      \immediate\closeout\@partaux
    \fi
  \else
    \deadcycles\z@
    \@nameuse{cp@#1}%
  \fi
  \let\@auxout\@mainaux
}
\begin{filecontents}{A.tex}
This is file A
This is the A file
\end{filecontents}
\begin{filecontents}{B.tex}
This is the B file
\end{filecontents}
\begin{filecontents}{C.tex}
This is the C file
\end{filecontents}
\includeonly{A,C}
\begin{document}
\includex{A}
\includex{B}
\includex{C}
\end{document}

答え1

このメカニズムの目的\includeは、ドキュメント全体を再コンパイルする必要なく、適度な量の変更を行うときにドキュメントを部分的にコンパイルし、相互参照などを正しく解決できるようにすることです (現在修正中の部分以外の部分に対しても)。

これが機能するには、含まれている部分が自己完結的である必要があります。つまり、その部分に対する変更によって、含まれていない他の部分の書式設定が自動的に (常に) 無効にならないようにする必要があります。これを可能にするには (少なくとも小さな変更の場合)、次の前提条件が必要です。

  • コンパイルされる部分のテキストの長さの小さな変更が、コンパイルされない他の部分の書式変更につながらないようにするメカニズムが必要です。
  • コンパイルされたパーツ内のフロートは、コンパイルされたパーツに配置する必要があります

上記のいずれかの点が有効でない場合、 を使用すると\include(ほぼ) 常に無効なドキュメントになりますが、現在のスキームでは、すべての部分を個別に含めても、有効なドキュメントに到達して維持できます。 (記録のために言うと、LaTeX Companion の最初のエディションを作成した際、この本をコンパイルするのに長い時間がかかり、2004 年の第 2 版でも、すべての例とすべてのページをコンパイルし、すべての相互参照を正常に解決するために本全体を再実行するのに約 30 分かかりました (5 回だったと思います)。したがって、章ごとに構築することが不可欠であり、それでもコンパイルに時間がかかりました :-)

もちろん、最初のポイントは、結果として得られるドキュメントが 1 ページ以上長くなったり短くなったりするなど、大量のテキストが追加または削除された瞬間に無効になります。

したがって、まず第一に、このメカニズムを価値あるものにするためには、含まれる部分の境界で改ページを使用する必要があるだけです\clearpage。また、フロートが含まれた部分内に留まり、内側または外側に移動しないようにするためにも、改ページを使用する必要があります。

@egreg はすでに、aux ファイル データを書き込むメカニズムは のみで機能するため、\shipout相互参照や目次のデータなどが失われないようにすることは不可能 (または少なくとも容易ではない) であるという追加の説明をしています。技術的には、1 つの include につき複数の aux ファイルを使用することでこれを管理する可能性を考えることができますが、それでは上記の点は解決されません。

最後に、これは LaTeX プロジェクト チームが発明したものではなく、Leslie Lamport のオリジナル設計に遡り、LaTeX 2.08 (少なくとも) 以降、つまり 1986 年より前から存在していました。

答え2

あなたが

\include{fileA}
\include{fileB}

\clearpageが終了せず、fileATeX が の読み取りを開始する場合、に対する相対パスが保留中になってfileBいる可能性があり、それが失われます。に対するコマンドは、即時ではなく、 shipout 時に実行されます。 次の shipout が発生するときには、ファイルはすでに閉じられています。\writefileA\write\labelfileA.aux

\labelそれぞれにコマンドを追加した例を試してみますと、なしファイルがすでに閉じられている.logときに shipout が発生するため、それらの一部はどこにでも (ファイル内以外) 書き込まれます。.aux

関連情報