[Tex/LaTex] \addtocontents at end of document not getting written to .toc file

auxiliary-filestable of contentswhatsit

I'm trying to find a more elegant solution for ToC, LoT, and LoF formatting for my university's thesis/dissertation style. The short form of their requirements means I need one page style for the first page of the ToC, a second page style for following pages up to where the appendix listings start, and yet a third style from the appendix listing through the end.

It looks like I've run into a bug, or else I'm just missing a better solution.

Minimal example 1

\documentclass{report}
\usepackage{lipsum}

\begin{document}
\addtocontents{toc}{\protect\thispagestyle{empty}\protect\pagestyle{plain}}
\tableofcontents

\input{twenty-chapters}
\appendix
\addtocontents{toc}{\protect\pagestyle{headings}\protect\thispagestyle{plain}}
\input{twenty-chapters}
\chapter{Foo} \include{a-chapter}
\addtocontents{toc}{\protect\thispagestyle{headings}}
\end{document}

Though I don't think it's relevant, the contents of twenty-chapters.tex is 20 lines of

\chapter{Foo} \include{a-chapter}

and a-chapter.tex is just:

\lipsum[1]
\section{Bar}
\lipsum[2-7]
\begin{figure}[tbp] \caption{Figure N} \end{figure}
\begin{figure}[tbp] \caption{Figure N} \end{figure}
\begin{figure}[tbp] \caption{Figure N} \end{figure}
\section{Baz}
\lipsum[8-9]
\begin{figure}[tbp] \caption{Figure N} \end{figure}
\begin{figure}[tbp] \caption{Figure N} \end{figure}
\begin{figure}[tbp] \caption{Figure N} \end{figure}

Here, I'm using the empty page style as a stand-in for the first page format, plain for the second page format, and headings for the third. This works fine on all but the last page of the ToC, which ends up with a plain page style instead of headings.

Minimal example 2:

\documentclass{report}
\usepackage{lipsum}

\begin{document}
\addtocontents{toc}{\protect\thispagestyle{empty}\protect\pagestyle{plain}}
\tableofcontents

\input{twenty-chapters}
\appendix
\addtocontents{toc}{\protect\pagestyle{headings}\protect\thispagestyle{plain}}
\input{twenty-chapters}
\addtocontents{toc}{\protect\thispagestyle{headings}}
\chapter{Foo} \include{a-chapter}
\end{document}

Exactly the same as the first document, but now my final \addtocontents is before the last chapter. On this one, everything works perfectly. Empty page style on ToC page 1, plain on ToC page 2, and headings on ToC pages 3-4.

Why would this make a difference? From looking at the .toc files for each example, my final \thispagestyle command is missing on the example that fails. Why would my \addcontents command not take effect in some situations?

Best Answer

Solution:

Replace the last \addtocontents with the following code:

\makeatletter
\immediate\write\@auxout{\noexpand\@writefile{toc}{\noexpand\thispagestyle{headings}}}
\makeatother

If this is required in more than one document, you can define a macro for it. In this case I would also set \protect properly (as the normal \addtocontents does). This is done inside a group of course (note the extra { } pair).

\makeatletter
\newcommand\immaddtocontents[1]{{%
   \let\protect\@unexpandable@protect
   \immediate\write\@auxout{\noexpand\@writefile{toc}{#1}}%
}}
\makeatother

which can be used like this:

\immaddtocontents{\protect\thispagestyle{headings}}

Explanation:

The problem is that \addtocontents is intended to be used together with material which is typeset. The underlying \write macro is a so called whatsit, i.e. it is only stored when found and executed later when its box is typeset, i.e. when the material is (virtually) written on the page. This is done, because only at this moment the final position of the material i.e. the page number is known.

Your last \addtocontents is never typeset, so comes never into the file. Using the code above will write the contents line directly without creating a whatsit. Please note that if you are using this code in the middle of the document your entries could be out of order.

Alternatives:

My first idea was to add an empty box \hbox{} after the last \addtocontents to force that the whatsit is executed. However because the last text was in an \include which executes \clearpage, adding this box afterwards would create a new empty page at the end of the document. However, if the last content of the document comes from the main file or an \input file (and does not end in an manual \clearpage) this solution should work.

Other possibility would be to use the filehook package to place the \addtocontents direct before the \clearpage of the last \include file:

\usepackage{filehook}
\AtEndOfIncludeFile{<last file>}{\addtocontents{toc}{\protect\thispagestyle{headings}}}

or place the following directly before the last \include:

\AtEndOfIncludes{\addtocontents{toc}{\protect\thispagestyle{headings}}}

Further Reading:

See The TeXBook it learn all abouts whatsits. For example in Chapter 21: Making Boxes, p.226.