重新定義\include

重新定義\include

Leslie Lamport 所做的一個令人費解的選擇是在讀取檔案之前\include以發出 a 的方式定義。\clearpage這讓我困惑了一段時間,因為就作者介面而言,這不是一個很好的選擇。這個問題有兩個部分:

  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 年的第二版也花了大約30 分鐘來編譯所有示例+ 所有頁面並重新運行整本書(我認為 5次)才能成功解決所有交叉引用,因此逐章構建內容至關重要,即使如此,編譯也需要很長時間:-)

當然,當新增或刪除大量文字時,例如產生的文件增加或減少了一頁或多頁,第一點將無效。

因此,在所包含部分的邊界處使用分頁符號對於使該機制值得一開始是必要的,並且\clearpage需要使用分頁符號來確保浮動留在所包含部分內並且不會移入或移出。

@egreg 已經給出了額外的解釋,即寫入 aux 檔案資料的機制僅適用,\shipout因此不可能(或至少不容易)確保交叉引用或目錄資料等內容不存在。從技術上講,人們可以想到管理此問題的可能性,但每個包含使用多個輔助文件,但這並不能解決上述問題。

最後,這不是 LaTeX 專案團隊發明的,它可以追溯到 Leslie Lamport 的原始設計,並且從 LaTeX 2.08(至少)到 1986 年之前就已經存在。

答案2

假設你有

\include{fileA}
\include{fileB}

如果沒有\clearpagewhenfileA結束並且 TeX 開始讀取fileB,則可能存在\write與待處理相關的命令fileA,並且它將丟失:\write與 相關的命令\label在發貨時執行,而不是立即執行。當下次發貨發生時,該fileA.aux文件將已經關閉。

如果您嘗試\label為每個範例新增一個命令,沒有任何其中一些將被寫入任何地方(但在.log文件中),因為發貨發生在.aux文件已經關閉時。

相關內容