[Tex/LaTex] What exactly does the \begin{document} command trigger

environments

Let us consider these two files first.


\documentclass{article}

\parindent 0.0mm

\hyphenpenalty 500
\tolerance 700

\usepackage{lipsum}


\begin{document}

\lipsum[1-10]

\end{document}

\documentclass{article}


\usepackage{lipsum}

\begin{document}

\parindent 0.0mm

\hyphenpenalty 500
\tolerance 700

\lipsum[1-10]

\end{document}

These two files have identical contents except some commands have been used
before and after \begin{document}. However, they produce completely identical outputs.

Now, if we want to add a \baselineskip command, it will work if it is used only after the \begin{document}.

Again there are commands which are allowed only in the preamble. \usepackage is the most common of them.

Definitely we understand that \begin{document} starts an environment, likely the highest or most major one, you know what I mean.

(Tried searching for something like \newenvironment{document} in
latex.ltx. Was not successful. May be I am not looking at the right place.)

But what exactly does this command do?

Please answer these two queries,

  1. What exactly the \begin{document} command triggers? What are the things it turns on?

  2. Why some commands are allowed only in the preamble?

Definitely other relevant issues will come in with the answers.

Best Answer

You should search for \document (and/or \enddocument) inside latex.ltx, since an environment env consists of the macro-pair \env and \endenv:

\def\document{\endgroup
  \ifx\@unusedoptionlist\@empty\else
    \@latex@warning@no@line{Unused global option(s):^^J%
            \@spaces[\@unusedoptionlist]}%
  \fi
  \@colht\textheight
  \@colroom\textheight \vsize\textheight
  \columnwidth\textwidth
  \@clubpenalty\clubpenalty
  \if@twocolumn
    \advance\columnwidth -\columnsep
    \divide\columnwidth\tw@ \hsize\columnwidth \@firstcolumntrue
  \fi
  \hsize\columnwidth \linewidth\hsize
  \begingroup\@floatplacement\@dblfloatplacement
    \makeatletter\let\@writefile\@gobbletwo
    \global \let \@multiplelabels \relax
    \@input{\jobname.aux}%
  \endgroup
  \if@filesw
    \immediate\openout\@mainaux\jobname.aux
    \immediate\write\@mainaux{\relax}%
  \fi
  \process@table
  \let\glb@currsize\@empty  %% Force math initialization.
  \normalsize
  \everypar{}%
  \ifx\normalsfcodes\@empty
    \ifnum\sfcode`\.=\@m
      \let\normalsfcodes\frenchspacing
    \else
      \let\normalsfcodes\nonfrenchspacing
    \fi
  \fi
  \@noskipsecfalse
  \let \@refundefined \relax
  \let\AtBeginDocument\@firstofone
  \@begindocumenthook
  \ifdim\topskip<1sp\global\topskip 1sp\relax\fi
  \global\@maxdepth\maxdepth
  \global\let\@begindocumenthook\@undefined
  \ifx\@listfiles\@undefined
    \global\let\@filelist\relax
    \global\let\@addtofilelist\@gobble
  \fi
  \gdef\do##1{\global\let ##1\@notprerr}%
  \@preamblecmds
  \global\let \@nodocument \relax
  \global\let\do\noexpand
  \ignorespaces}

Amongst a host of things, the document environment initiates the following:

  • Report on unused \documentclass options;
  • Set the page layout;
  • Read in the .aux file;
  • Open up a stream to start (over)writing to the .aux;
  • Initiate the font size for the document (\normalsize);
  • Execute whatever has been collected via \AtBeginDocument (\@begindocumenthook);
  • Disable preamble-only commands (via \@preamblecmds, which collects commands that are defined as being usable in the preamble only via \@onlypreamble).

Note that this is the default definition used in LaTeX. Some documents may alter or append to this definition, depending on the requirements.


Fundamentally, packages are meant to do a host of things, including intervene with things done during the initiation of the document environment (mentioned above). Clearly, geometry is one, as it needs to set up the page layout and dimensions before you can start writing certain content. However, as a more general rule, it's better to separate structure from content, and since package provide structural interface, they're better-suited for the preamble. You can load a fairly trivial package mypackage (say) within the document environment, using

\makeatletter
\input{mypackage.sty}% Load mypackage.sty
\makeatother

The \makeatletter...\makeatother pair avoid @-in-macro problems. However, some packages are written using commands that are itself only usable within the preamble. Circumventing that would be a tedious process and is not necessary.