[Tex/LaTex] \AtBeginDocument and \AtEndDocument for standalone

hooksstandalone

Using the commands \AtBeginDocument and \AtEndDocument with the standalone documentclass yields unexpected effects.

I have the following three files.

% main.tex
\documentclass{scrartcl}
\usepackage[subpreambles]{standalone}
\AtBeginDocument{begin main \\}
\AtEndDocument{end main \\}
\begin{document}%
  before
  \input{sub1}
  between
  \input{sub2}
  after
\end{document}

and

% sub1.tex
\documentclass{standalone}    
\AtBeginDocument{begin sub1 \\}
\AtEndDocument{end sub1 \\}
\begin{document}%
\end{document}

sub2.tex looks like sub1.tex except for the numbers. Compiling main.tex results in a document that orders the text fragments like this. (I inserted some indentation here just to point out the structure.)

begin sub1
 begin sub2
  begin main
   before
   between
   after
  end main
 end sub1
end sub2

But I would expect this.

begin main
 before
  begin sub1
  end sub1
 between
  end sub2
  begin sub2
 after
end main

How can I instead get the second result?

Best Answer

I am sure there are better ways of doing this, but my approach is to patch the \AtBeginDocument and \AtEndDocument macros during the loading of the subpreambles such that they append their arguments to temporary macros. I then patch the input (or more specifically \@iinput) macro to use the temporary macros in the document body. I do the patching with the etoolbox package, but you can do it however you want. In order to get the patching done during the loading of the subpreambles I write directly into the \jobname.sta file. My patching of \@iinput isn't particularly robust and requires you to use \input{sub1.tex} instead of `\input{sub1}.

By the way this type of patching of the \AtBeginDocument and \AtEndDocument macros is going to cause havoc if you load any packages in your sub files that depend on \AtBeginDocument and \AtEndDocument being expanded where they are supposed to be expanded.

% main.tex
\documentclass{scrartcl}
\usepackage{etoolbox}
\usepackage[subpreambles]{standalone}
\AtBeginDocument{begin main \\}
\AtEndDocument{end main \\}


\makeatletter
\pretocmd{\@iinput}{\csuse{AtBeginDocument#1}}{}{}
\apptocmd{\@iinput}{\csuse{AtEndDocument#1}}{}{}
{\@makeother\#%
    \AtBeginDocument{\immediate\write\sa@out{\unexpanded{%
        \renewcommand{\subpreamble}[1]{%
            \expandafter\def\csname AtBeginDocument#1\endcsname{}%
            \expandafter\def\csname AtEndDocument#1\endcsname{}%
            \renewcommand{\AtBeginDocument}[1]{\expandafter\apptocmd\expandafter{\csname AtBeginDocument#1\endcsname}{##1}{}{}}
            \renewcommand{\AtEndDocument}[1]{\expandafter\apptocmd\expandafter{\csname AtEndDocument#1\endcsname}{##1}{}{}}
        }
    }}}
}
\makeatother

\setlength{\parindent}{0pt}
\begin{document}%

  before

  \input{sub1.tex}

  between

  \input{sub2.tex}

  after

\end{document}

enter image description here

Related Question