In LaTeX, I'd like to know whether a documentclass has been loaded and whether code is inside a \begin{document}. In other words, is there a \ifpreamble similar to \ifvmode and friends?

Partially this is curiosity, partly this is to make it easy to compile a figure as a standalone or included in some larger document. In the past I've made the including document define a macro, and the figure tests for it, but it'd be nice if the figure could figure it out itself.

Things that don't work (because they aren't changed by \documentclass or \begin{document}):

  • \ifvmode is true immediately
  • \@currenvir is "document" immediately
  • \normalsize is defined immediately

LaTeX defines a lot of macros which are only supposed to be used in the preamble of a document (such as \usepackage, but also some internal kernel macros). It does this via \@onlypreamble\SomeMacro. This works by adding \SomeMacro to a list, which at \begin{document} are all set equal to \@notprerr, which is a macro that generates an error. In particular, the kernel declares \@onlypreamble\@onlypreamble. This means that we can test if we are in the preamble by doing

\ifx\@onlypreamble\@notprerr (document)\else (preamble)\fi

If we're in a package and would like to know if we are loaded before or after the \documentclass declaration, we can look at what \documentclass does: Among lots of other things, it says \let\documentclass\@twoclasseserror (which prevents invoking \documentclass twice). So testing if \documentclass is ifx-equal to \@twoclasseserror takes care of this.

  \ifx\documentclass\@twoclasseserror % after \documentclass
    \ifx\@onlypreamble\@notprerr % after \begin{document}
    \else % before \begin{document}
  \else % before \documentclass




foo says \foo; bar says \bar; baz says \baz

I think this is pretty robust; I don't think any packages change \documentclass or \@onlypreamble after they have been changed to their error-giving meanings.

  • Thanks for the neat technique. I was trying to use \ifx\document{the actual error message all written out} which was awful. \@notprerr was perfect. I very much like your test document. I had one very similar for ifvvmode and friends, but all it said was "foo says Hi; bar says Hi; baz says Hi" which was getting very frustrating. – Jack Schmidt Apr 21 '11 at 17:09
  • 1
    In view of, e.g., etoolbox's \AfterEndPreamble, this doesn't seem 'pretty robust'. When some code is hooked to the end of \document, \let\@onlypreamble=\@notprerr doesn't signify the end of \begin{document}. – Ahmed Musa Nov 17 '12 at 18:12
  • this does not work anymore :( it get's detected as preamble (goes in else) even after \begin{document} – Daniele Segato May 30 '18 at 9:07
  • Oh, I figured it out, to anyone trying this out, \ifx\@onlypreamble\@notprerr (document)\else (preamble)\fi doesn't work alone, you need \makeatletter and \makeatother for those checks to work – Daniele Segato May 30 '18 at 10:44

If all you need this for is to allow you to compile component files separately from the master document, then you might look at Martin Scharrer's standalone package, designed to do just that.

  • Thanks! This looks like a nice polished solution. I enjoy cobbling things together, but when I actually need the results to be dependable, I'll use the package. – Jack Schmidt Apr 21 '11 at 17:11
  • @Jack Schmidt: My feelings exactly. Sometimes it's a great learning experience to take an answer like @Villemoes' and adapt it to one's exact needs; sometimes "life's too short" and a regular old hammer out' the toolbox is what you need. – Brent.Longborough Apr 22 '11 at 11:10

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.