19

As I understood the macro \AtBeginDocument, whatever it says will be run right after \begin{document}. In other words, it will follow whatever else there is in the preamble. But I've noticed that it matters when in the preamble \AtBeginDocument is run. Consider the following example, taken from Cite and sort author with lowercase prefix (biblatex).

When the line \AtBeginDocument{\toggletrue{blx@useprefix}} is placed before biblatex is loaded, the author van Helten is sorted under v in the bibliography. The biblatex option useprefix has in other words been changed to true. This is expected, since \toggletrue{blx@useprefix} is activated at the beginning of the document, thus overriding the option useprefix = false which was set in the preamble.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\AtBeginDocument{\toggletrue{blx@useprefix}}
\usepackage[style=authoryear, useprefix = false]{biblatex}
\renewbibmacro*{begentry}{\midsentence}
\begin{filecontents}{\jobname.bib}
@ARTICLE{vanhelten1891,
    AUTHOR = "W. van Helten",
    TITLE = "Grammatisches",
    JOURNALTITLE = "Beiträge zur Geschichte der deutschen Sprache und Literatur",
    YEAR = "1891",
    PAGES = "455--488",
    VOLUME = "15"}
@BOOK{mccartney1967,
    AUTHOR = "Paul McCartney",
    TITLE = "Hey Jude",
    YEAR = "1967"}
\end{filecontents}
\addbibresource{\jobname.bib}
\begin{document}
\cites{vanhelten1891}{mccartney1967}
\printbibliography
\end{document}

enter image description here

But when \AtBeginDocument{\toggletrue{blx@useprefix}} is placed after biblatex is loaded, the author van Helten is sorted under h in the bibliography. The biblatex option useprefix = false has in other words not been overridden by \toggletrue{blx@useprefix}. Why is this? Shouldn't \AtBeginDocument{\toggletrue{blx@useprefix}} be executed last anyway, and therefore override whatever the option useprefix is set to in the preamble?

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\usepackage[style=authoryear, useprefix = false]{biblatex}
\AtBeginDocument{\toggletrue{blx@useprefix}}
\renewbibmacro*{begentry}{\midsentence}
\begin{filecontents}{\jobname.bib}
@ARTICLE{vanhelten1891,
    AUTHOR = "W. van Helten",
    TITLE = "Grammatisches",
    JOURNALTITLE = "Beiträge zur Geschichte der deutschen Sprache und Literatur",
    YEAR = "1891",
    PAGES = "455--488",
    VOLUME = "15"}
@BOOK{mccartney1967,
    AUTHOR = "Paul McCartney",
    TITLE = "Hey Jude",
    YEAR = "1967"}
\end{filecontents}
\addbibresource{\jobname.bib}
\begin{document}
\cites{vanhelten1891}{mccartney1967}
\printbibliography
\end{document}

enter image description here

Sverre
  • 20,729
  • The \AtBeginDocument macro appends its contents to a token list, which is expanded right after \begin{document}. Hence, if you first issue \AtBeginDocument{\toggletrue{blx@useprefix}} and biblatex appends \togglefalse{blx@useprefix}, because it is loaded afterwards the togglefalse part stands last and "wins". – Henri Menke May 15 '14 at 15:37
  • @HenriMenke You mean that biblatex also appends \togglefalse{blx@useprefix} to the same "token list" that \AtBeginDocument appends \toggletrue{blx@useprefix} to? – Sverre May 15 '14 at 15:40
  • That's my guess. I don't know for sure, but you can of course look it up in the biblatex code. – Henri Menke May 15 '14 at 15:43
  • Just like I guessed: \AtBeginDocument{...\blx@bblinput...} where \def\blx@bblinput{...\blx@blxinit...} and \appto\blx@blxinit{...\def\ifuseprefix{\iftoggle{blx@useprefix}...}. Hence \toggle____{blx@useprefix} is buried deep inside \AtBeginDocument. – Henri Menke May 15 '14 at 15:49
  • Sorry, \AtBeginDocument is not a token list, but a macro, which is extended via \g@addto@macro on every occurrence. – Henri Menke May 15 '14 at 15:54
  • I don't really understand this. If you or someone could provide a dumbed-down answer, that would be appreciated. – Sverre May 15 '14 at 15:56

2 Answers2

18

The \AtBeginDocument macro appends its contents to the macro \@begindocumenthook which is expanded right after \begin{document}. Hence, if you first issue \AtBeginDocument{\toggletrue{blx@useprefix}} and biblatex appends \togglefalse{blx@useprefix} (due to useprefix=false), because it is loaded afterwards the togglefalse part stands last and "wins".

If we look inside biblatex1.sty, we can see

\AtBeginDocument{...\blx@bblinput...}
...
\def\blx@bblinput{...\blx@blxinit...}
...
\appto\blx@blxinit{...\def\ifuseprefix{\iftoggle{blx@useprefix}}...}

If we now consider expansion then this is equivalent to

\AtBeginDocument{...\def\ifuseprefix{\iftoggle{blx@useprefix}}...}

Keeping this in mind, your code

\AtBeginDocument{\toggletrue{blx@useprefix}}
\usepackage[style=authoryear, useprefix = false]{biblatex}

reduces to something like

\AtBeginDocument{\toggletrue{blx@useprefix}\togglefalse{blx@useprefix}}

where \togglefalse is being executed after \toggletrue, hence the switch is set to false at \begin{document}.

Henri Menke
  • 109,596
7

If you (or a packages you load) go

\AtBeginDocument{\newcommand\zz{}}

...

\AtBeginDocument{\zz}

Then just before the document starts, LaTeX will do

\newcommand\zz{}\zz

and nothing bad will happen.

Now, if you load packages in another order so the effective usage is:

\AtBeginDocument{\zz}

...

\AtBeginDocument{\newcommand\zz{}}

then at the start of the document LaTeX will do

\zz\newcommand\zz{}

and generate an undefined command error as \zz is used before it is defined.

David Carlisle
  • 757,742
  • But this is because the order of macros internally to \AtBeginDocument is wrong. That's not quite the scenario illustrated in my question, is it? – Sverre May 15 '14 at 15:55
  • @Sverre It is not exactly your scenario, but it shows, that the order of \AtBeginDocument statements is very important. – Henri Menke May 15 '14 at 15:56
  • @Sverre more or less but just using simpler code. Basically I wanted to highlight that it only matters if two things are added to the begin document hook as the order they are executed is the order they are added, so the expectation should be that it matters when you use this hook (if you suspect any package you are using uses it) the exact details of what goes wrong in each case differ of course – David Carlisle May 15 '14 at 15:57
  • @HenriMenke Yes, but this is about the order of multiple instances of \AtBeginDocument. It seems rather straightforward that that order matters when those commands are executed. – Sverre May 15 '14 at 15:58
  • @Sverre your question is all about multiple instances of AtBeginDocument the ones you do and the ones biblatex does – David Carlisle May 15 '14 at 15:59
  • @DavidCarlisle The implication here being that biblatex also adds something to the "begin document hook"? EDIT: Ok, I see (I didn't know that biblatex used \AtBeginDocument internally). – Sverre May 15 '14 at 15:59
  • @Sverre Well that is implied by your question otherwise the order wouldn't matter (I didn't actually look:-) but Henri already confirmed that is the case in a comment on your question. – David Carlisle May 15 '14 at 16:00
  • @DavidCarlisle It was precisely because I thought the order didn't matter that I couldn't understand why it did matter in this case ... :). – Sverre May 15 '14 at 16:02