重新定义 \include

重新定义 \include

Leslie Lamport 做出的一个令人费解的选择是,在读取文件之前\include发出一个。这一直困扰着我一段时间,因为就作者界面而言,这不是一个很好的选择。这个问题有两个部分:\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 已经给出了额外的解释,即写入辅助文件数据的机制仅在\shipout无法(或至少不容易)确保诸如交叉引用或目录数据之类的内容不会丢失的情况下才起作用。从技术上讲,可以考虑一种管理这种情况的可能性,但每个包含使用多个辅助文件,但这无法解决上述问题。

最后,这不是 LaTeX 项目团队发明的东西,它可以追溯到 Leslie Lamport 的原始设计,并且自 LaTeX 2.08(至少)以来就已存在,即在 1986 年之前。

答案2

假设你有

\include{fileA}
\include{fileB}

如果没有结束\clearpage时间fileA,TeX 开始读取fileB,则可能存在\write与 相关的fileA挂起命令,并且该命令将会丢失:\write与 相关的命令\label在 shipout 时执行,而不是立即执行。当下一次 shipout 发生时,文件fileA.aux已经关闭。

如果你尝试在你的示例中添加\label在每个示例中添加一个命令,没有任何它们将被写入任何地方(但在.log文件中),因为发货时.aux文件已经关闭。

相关内容