48

I attempted to redefine the document environment as follows, but get a complaint that:

LaTeX Error: \begin{MYdocument} on input line 13 ended by \end{document}.

\documentclass[12pt]{article}
\newtoks{\SpecialText} 
\SpecialText={Text to be printed after begin document}

\newenvironment{MYdocument}{%
  \begin{document}{}
  Note: \the\SpecialText
}{%
  \end{document}
} 

\begin{MYdocument}
 ... file contents ...
\end{MYdocument}

I want this to produce the following output

Note: Text to be printed after begin document

... file contents ...

If I could do this by just slightly modifying the environment that would be preferable so that I could just use \begin{document} ... \end{document}.

2
  • I tried to make the title of your question clearer by adding the word "text" - is that OK? Commented Mar 24, 2011 at 9:48
  • The latex-general tag (and also latex3) is for questions about LaTeX and the LaTeX project in general. A good example is Difference between LaTeX, LaTeX2e, LaTeX3?. Your question is about a specific task and therefore should not be tagged with it. Commented Mar 24, 2011 at 9:56

3 Answers 3

2

As of 2023 the answers suggesting to use \AtBeginDocument might be outdated. In fact, clsguide.pdf has on p. 16

The \AtBeginDocument hook should not be used for code that does any typesetting since the typeset result would be unpredictable.

Simplifying, the code \begin{document} expands to

\UseHook{env/document/before}
\begingroup
\def\@currenvir{document}
\UseHook{env/document/begin}
\UseOneTimeHook{begindocument/before}%
% ... global option check, size setting, aux file, font setup
\normalsize
\everypar{}%
% ... spacefactor codes, language, metadata, page size
\UseOneTimeHook{begindocument}%   <--- \AtBeginDocument goes in here
% ... other settings
\UseOneTimeHook{begindocument/end}%
\ignorespaces

I've marked where the content of \AtBeginDocument is inserted. While font sizes have been set up and \everypar has been "cleared" such that it doesn't throw the Missing \begin{document} error, other stuff goes on and, as the official guide tells, the result might be unpredictable. (Subjunctive: clearly you might also get lucky.) The very last hook executed by \begin{document}, just before \ignorespaces, is begindocument/end (see also lthooks-doc.pdf, p.25). Material to be typeset should thus come into this hook:

\documentclass{article}
\AddToHook{begindocument/end}{Hello world!\par}
\begin{document}
Hello world.
\end{document}

enter image description here

With a format later than 2020-10-01, etoolbox's own \AfterEndPreamble is simply mapped into \AddToHook{begindocument/end}. With older formats it can still be used safely, because the used hook is added at the very end of \document by something like this:

\edef\document{\unexpanded\expandafter{\document Hello world!\par}}

Doing this yourself is clearly evil. Fluffy little bunnies will die horribly any time you do so, unless you are a dark TeX wizard/witch who really knows what he/she is doing.

5
  • Thanks for noticing that and including that info here. So, does that comment also apply to \AfterEndPreamble or that still ok to use. Commented Oct 26, 2023 at 17:25
  • @PeterGrill Good point, I've edited. With a modern format they're the same.
    – campa
    Commented Oct 26, 2023 at 18:13
  • Interesting: The syntax >! for "spoilers" works in the preview but non in the main page. Does someone know why?
    – campa
    Commented Oct 26, 2023 at 18:42
  • Thanks for figuring out that \AfterEndPreamble is still safe. I suspect the >! doesn't work in TeX.SE as that feature is not really used here so was only enabeled in the sites that wanted/needed it. I suspect that it works in Preview by accident. But, probably a good question to ask on Meta. Commented Oct 26, 2023 at 21:05
  • 1
    @PeterGrill To be precise: \AfterEndPreamble works also with older formats, just in a slightly different way. I've rephrased a bit to make this clear.
    – campa
    Commented Oct 28, 2023 at 15:09
60

You can use the \AtBeginDocument command before the \begin{document} line to queue up code (even multiple pieces of code) so that it it executed when that line is hit. Here's a reference.

3
  • 2
    Thank You. That is a MUCH better solution that what I was attempting... Commented Mar 24, 2011 at 3:39
  • 3
    Note that the reference given is not up to date, see this version. An update of december 1996 states that no typesetting can (should) be done with \AtBeginDocument. Check out this for more information on why you should not do this. Commented Mar 3, 2015 at 12:21
  • 1
    @TonioElGringo: Just saw this now. The first link you provided no longer works. The problem file provided at the second link seems to compile fine by adding \usepackage{tikz}, so not sure if that is a reason to not use \AtBeginDocument{}. No idea why it needs tikz, but if someone posts that question on this site, people will explain or fix the package if it is a bug. Commented Sep 24, 2016 at 8:52
45

As already stated by Aaron, \AtBeginDocument{<code>} can be used to place code "at the begin of the document". This hook is executed after the old .aux is read in and the new one is opened, but before the preamble is officially closed. Therefore the code can still load packages and add already type-settable material which writes into the .aux file, like sectioning commands. So it is actually executed with one foot in the preamble and the other one in the document body.

The etoolbox package provides \AfterEndPreamble{<code>} (and other useful hooks) which is executed after the preamble is closed, so e.g. all preamble-only macros are disabled etc. Actually it is executed at the very end of \begin{document}, only followed by an \ignorespaces. I personally would prefer \AfterEndPreamble to \AtBeginDocument (already heavily used by packages) to add code at the very beginning of the document body.

You must log in to answer this question.

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