10

This may be an odd question, but I'm having trouble writing information on the main .aux file when I split my documents through more than one .tex.

Here is the deal: I'm trying to calculate the size of the widest TOC label so that I can align all chapter/section names in the TOC based on this measure. Someone has already told me how to do this measuring, but I need to write this info in the .aux file so that in the first pass I calculate the size and in the second pass I make use of it.

What is troubling me is that the command that I'm using is not working, and I believe the reason is the said modularization of the document, since when I try it in a single-file document it works ok.

Here is the part of the code that should write the info:

\AtEndDocument{
    \protected@write\@auxout{}%
    {\string\global\string\setlength{\string\widesttoclabel}{\the\widesttoclabel}}
}

With \widesttoclabel being the macro that holds the length I've calculated.

But when I check the .aux file, that entry is not anywhere around, neither in the "master document's" aux nor in the others'.

Am I missing something?

OBS: I know I could workaround and replace \includes with \inputs, but this would be terrible, since my document has very many pages... So this shouldn't be an option if I could choose.

12

When LaTeX executes \end{document},

  1. it calls the hook for the collected stuff in \AtEndDocument,
  2. `\clearpage is called and
  3. the main .aux file is closed.

You are using \protected@write that is a deferred writing. It puts a write node in the output that is executed (actually written), when the page is output. However, if at the end of document the latest page is already output, nothing happens, because TeX does not create a page, if it only contains a write node. Therefore you need \immediate\write.

The order of the end of document hook is the order of \AtEndDocument calls. Thus the writing to the .aux file might come too early, if a section with a longer title is added via \AtEndDocument. Package atveryend provides the hook command \AfterLastShipout that is called after the \AtEndDocument hook (1.) and after the final \clearpage (2.) before the .aux file is closed (3.).

Thus the code example becomes:

\usepackage{atveryend}
\newdimen\widesttoclabel
\setlength{\widesttoclabel}{0pt}
\makeatletter
\AtBeginDocument{%
  \xdef\thewidesttoclabel{\the\widesttoclabel}%
}%
\AfterLastShipout{%
  \if@filesw
    \immediate\write\@mainaux{%
      \global\string\widesttoclabel=\the\widesttoclabel\relax
    }%
  \fi
}
\makeatother
% ...
\begin{document}
  % Macro \thewidesttoclabel contains the width of the widest toc label
  % from the previous run. Dimen register \widesttoclabel is initially 0pt
  % and should be updated for each longer entry found during the document.
\end{document}

Further remarks:

  • \global\setlength is not correct, because it depends on the implementation of macro \setlength. The documentation does not ensure that \global can be used to get a global assignment. In contrary, package calc redefines \setlength. Then a prefix \global fails. Correct variants:

    \setlength{\mylength}{...}%
    \global\mylength=\mylength
    

    or if in this case, there are not any calculations, thus we can use

    \global\widesttoclabel=\the\widesttoclabel\relax
    
  • LaTeX provides \nofiles that disables the writing to auxiliary files. \protected@write is redefined accordingly. And it sets the switch \if@filesw that can be asked, whether auxiliary files are writable. Since the solutions uses \immediate\write directly, the writing is put between \if@filesw and \fi to respect \nofiles.

Variant

The following is a variant that uses a global macro definition \xdef rather than a global assignment in the .aux file:

\documentclass{article}

\usepackage{atveryend}

% Dimen register \widesttoclabel is used for measuring and
% finding the maximal value that is written to the `.aux` file
% at the end of document.
\newdimen\widesttoclabel
\setlength{\widesttoclabel}{0pt}

% \thewidesttoclabel is a macro with the width of the
% widest toc label. It is defined in the `.aux` file.
% In the first run, the dummy value 0pt is used.
\AtBeginDocument{%
  \providecommand*{\thewidesttoclabel}{0pt}%
}

\makeatletter
% \set@widesttoclabel is used at the end of the main .aux file
\newcommand*{\set@widesttoclabel}[1]{%
  \xdef\thewidesttoclabel{#1}%
}
\AfterLastShipout{%
  \if@filesw
    \immediate\write\@mainaux{%
      \xdef\string\thewidesttoclabel{\the\widesttoclabel}%
    }%
  \fi
}

\begin{document}
Widest entry: \thewidesttoclabel
\settowidth{\widesttoclabel}{Hello World}% dummy
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.