4

This question is motivated as a followup to this one, where I ran into an issue with subtle differences in execution order between a usepackage command and AtBeginDocument. To simplify the discussion, I'll reproduce the main code here:

\documentclass{report}
\AtBeginDocument{\listoffigures}
\usepackage{cleveref}
\begin{document}
\begin{figure} \caption{This caption cross-references \cref{eqn}.} \label{fig} \end{figure}
\begin{equation} F = ma \label{eqn}\end{equation}
\end{document}

Paraphrasing a comment I posted in response to the answer there, my assumption from the naming was that \AtBeginDocument would behave like a preprocessor macro in C or something similar to that, i.e. it would be lazily expanded and evaluated when it was run (at the beginning of the document). However, the issue I ran into was caused by running a \usepackage command in the preamble of my document after \AtBeginDocument was called in my cls file, and it was resolved when I moved the usepackage call above AtBeginDocument, indicating that it's immediately executing the commands but somehow delaying their effect until \begin{document}. Specifically, this order led to cleveref not knowing how to refer to equations in the figure captions copied into the lof:

\AtBeginDocument{...}
\usepackage{cleveref}

whereas swapping those two commands fixed that issue. So my question is, how does \AtBeginDocument work, and what assumptions can I actually make about when its arguments are evaluated and when their side effects will become apparent?

8
  • 2
    Traditionally \AtBeginDocument{<stuff>} would just append <stuff> to a hook that is executed at \begin{documen}. So \AtBeginDocument{<A>}\AtBeginDocument{<B>} would execute <A> and then <B> at \begin{document}. Since some packages use \AtBeginDocument you can sometimes get different results when you move \AtBeginDocument before or after a \usepackage. But the LaTeX version released tonight (LaTeX 2020-10-01) has a much more sophisticated hook mechanism that makes it possible to have finer control over \AtBeginDocument.
    – moewe
    Oct 3, 2020 at 11:48
  • 2
    See also tex.stackexchange.com/q/177397/35864 for an example that explains why order matters. Anyway, I think \AtBeginDocument{\listoffigures} might be a bit dangerous. I'm not sure if \AtBeginDocument is supposed to contain typesettable content. Usually it contains setup and config code.
    – moewe
    Oct 3, 2020 at 11:54
  • 1
    If you want to typeset stuff at the beginning of your document, etoolbox suggests \AfterEndPreamble (which probably has a 'native' LaTeX hook equivalent in the 2020-10-01 release).
    – moewe
    Oct 3, 2020 at 11:57
  • 2
    I haven't looked at the cleveref code to find out what is actually going on here, but I know that cleveref uses \AtBeginDocument quite extensively. So I'd guess if you say \AtBeginDocument{\listoffigures}\usepackage{cleveref} the begin document hook contains \listoffigures <cleveref initialisation code> and if you say \usepackage{cleveref}\AtBeginDocument{\listoffigures} you get <cleveref initialisation code> \listoffigures. The latter gives the expected result, the former doesn't if \litsoffigures uses cleveref commands.
    – moewe
    Oct 3, 2020 at 12:01
  • 1
    @moewe I hope you are OK with my answer: this is more or less the same as your comments but I was writing as you were commenting!
    – Joseph Wright
    Oct 3, 2020 at 12:02

1 Answer 1

6

Tokens added using \AtBeginDocument appear in exactly the order they are added, which is why reordering the preamble makes a difference. From the latest LaTeX release (2020-10-01) there is a new hook mechanism which allows re-ordering based on sorting rules: \AddToHook{begindocument}. However, as commented, \AtBeginDocument or the new \AddToHook{begindocument} equivalent should not be used for anything typeset. For that, you should use \AddToHook{begindocument/end} with a new LaTeX format or load etoolbox and use \AfterEndPreamble hook.

2
  • @Vyas - I think that the likely upshot of this answer is that because you can't (shouldn't?) assume that all users of your LaTeX document class will be using the 2020-10-01 (or later) version of the LaTeX kernel and hence won't have access to the \AddToHook device, you should replace \AtBeginDocument{\listoffigures} with \usepackage{etoolbox} \AfterEndPreamble{\listoffigures}. :-)
    – Mico
    Oct 3, 2020 at 12:22
  • Sounds like a good solution, thanks for the help!
    – Vyas
    Oct 3, 2020 at 18:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .