Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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
share|improve this question
add comment

2 Answers

up vote 18 down vote accepted

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.

\makeatletter
\def\MakeTest#1{%
  \edef#1{%
  \ifx\documentclass\@twoclasseserror % after \documentclass
    \ifx\@onlypreamble\@notprerr % after \begin{document}
      Hello
    \else % before \begin{document}
      Howdy
    \fi
  \else % before \documentclass
    Hi!
  \fi}}
\makeatother
\MakeTest\foo

\documentclass{minimal}

\MakeTest\bar

\begin{document}
\MakeTest\baz

foo says \foo; bar says \bar; baz says \baz
\end{document}

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.

share|improve this answer
    
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
    
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
add comment

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.

share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.