Quando e como os comandos no argumento de \ AtBeginDocument são avaliados?

Oct 03 2020

Esta questão é motivada na sequência desta , onde encontrei um problema com diferenças sutis na ordem de execução entre um usepackagecomando e AtBeginDocument. Para simplificar a discussão, reproduzirei o código principal aqui:

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

Parafraseando um comentário que postei em resposta à resposta ali, minha suposição a partir da nomenclatura era que \AtBeginDocumentse comportaria como uma macro de pré-processador em C ou algo semelhante a isso, ou seja, seria lentamente expandido e avaliado quando fosse executado (no início de o documento). No entanto, o problema que encontrei foi causado pela execução de um \usepackagecomando no preâmbulo do meu documento depois de \AtBeginDocumentser chamado no meu arquivo cls e foi resolvido quando movi a usepackagechamada acima AtBeginDocument, indicando que ela está executando imediatamente os comandos, mas de alguma forma atrasando seu efeito até \begin{document}. Especificamente, essa ordem levou a cleverefnão saber como se referir às equações nas legendas das figuras copiadas em lof:

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

enquanto a troca desses dois comandos corrigiu esse problema. Portanto, minha pergunta é: como \AtBeginDocumentfunciona e que suposições posso realmente fazer sobre quando seus argumentos são avaliados e quando seus efeitos colaterais se tornarão aparentes?

Respostas

6 JosephWright Oct 03 2020 at 12:02

Os tokens adicionados usando \AtBeginDocumentaparecem exatamente na ordem em que são adicionados, e é por isso que reorganizar o preâmbulo faz a diferença. Desde a última versão LaTeX (2020/10/01), há um novo mecanismo de gancho que permite re-ordenação com base em regras de classificação: \AddToHook{begindocument}. No entanto, conforme comentado, \AtBeginDocumentou o novo \AddToHook{begindocument}equivalente não deve ser usado para nada formatado. Para isso, você deve usar \AddToHook{begindocument/end}com um novo formato LaTeX ou carregar etoolboxe usar o \AfterEndPreamblegancho.