Redefiniendo \include

Redefiniendo \include

Una decisión desconcertante tomada por Leslie Lamport fue definir \includede tal manera que se emitiera un aviso \clearpageantes de leer el expediente. Esto me ha estado desconcertando durante algún tiempo ya que no es una muy buena opción en términos de interfaz de autor. Esta pregunta tiene dos partes:

  1. ¿Existen razones válidas para esta decisión?
  2. ¿Qué puede fallar si se redefine el comando?

El MWE a continuación muestra dicha redefinición (nombré el comando \includexpero funciona bien incluso si se llama \include). Mi propia sospecha es que esto se introdujo desde el principio para resolver problemas con twocolumns, pero no hay nada que source2eexplique esta decisión.

\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}

Respuesta1

El propósito del \includemecanismo es permitir la compilación parcial del documento al realizar una cantidad modesta de cambios sin la necesidad de volver a compilar el documento completo y aun así obtener referencias cruzadas, etc. resueltas correctamente (incluso a partes fuera de la parte actual bajo el cuchillo).

Para que esto funcione, la parte o partes que se incluyen deben ser independientes en el sentido de que los cambios en ellas no invaliden automáticamente (y siempre) el formato de otras partes no incluidas. Para que esto sea posible (al menos para cambios más pequeños), se necesitan los siguientes requisitos previos:

  • El mecanismo debe garantizar que pequeños cambios en la longitud del texto en la parte que se está compilando no den como resultado cambios de formato en otras partes no compiladas.
  • Los flotadores en las partes compiladas deben colocarse en las partes compiladas.

Si alguno de los puntos anteriores no es válido, entonces su uso \includeresultaría (casi) siempre en documentos no válidos, mientras que en el esquema actual se pueden incluir todas las piezas individualmente y aun así llegar y mantener un documento válido. (Solo para que conste, cuando produjimos la primera edición de LaTeX Companion, nos tomó mucho tiempo compilar este libro e incluso la segunda edición tomó alrededor de 30 minutos en 2004 para compilar todos los ejemplos + todas las páginas y volver a ejecutar el libro completo (creo que 5 veces) para resolver correctamente todas las referencias cruzadas, por lo que desarrollar las cosas capítulo por capítulo fue esencial e incluso entonces la compilación llevó mucho tiempo :-)

Por supuesto, el primer punto no será válido en el momento en que se agregue o elimine una gran cantidad de texto, como cuando el documento resultante tiene una o más páginas más largas o más cortas.

Por lo tanto, usar saltos de página en los límites de las partes incluidas es simplemente necesario para que el mecanismo valga la pena en primer lugar y \clearpagees necesario usarlo para garantizar que los flotadores permanezcan dentro de la parte incluida y no se muevan hacia adentro o hacia afuera.

@egreg ya dio la explicación adicional de que el mecanismo para escribir datos de archivos auxiliares solo funciona, \shipoutpor lo que no sería posible (o al menos no fácil) garantizar que elementos como las referencias cruzadas o los datos para la tabla de contenido no se realicen. No estoy perdido. Técnicamente, se podría pensar en una posibilidad de gestionar esto, pero usando más de un archivo auxiliar por inclusión, pero eso no resolvería el punto anterior.

Finalmente, esto no es algo que inventó el equipo del Proyecto LaTeX, se remonta al diseño original de Leslie Lamport y existía desde LaTeX 2.08 (al menos), antes de 1986.

Respuesta2

Supongamos que tienes

\include{fileA}
\include{fileB}

Si no hay \clearpagecuándo fileAtermina y TeX comienza a leer fileB, puede haber un \writerelativo a fileApendiente y se perderá: los \writecomandos relativos a \labelse ejecutan en el envío, no inmediatamente. Cuando se produzca el próximo envío, el fileA.auxexpediente ya habrá sido cerrado.

Si prueba su ejemplo agregando un \labelcomando a cada uno,ningunode ellos se escribirán en cualquier lugar (menos en el .logarchivo), porque el envío se produce cuando los .auxarchivos ya se han cerrado.

información relacionada