5

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?

  • How important is it that the sub-files use \At<etc> commands? It would be easy to create a \myimport command that optionally executes something before and/or after each actual call of \input in a way that preserves the desired output structure. – jon Jan 23 '14 at 17:31
  • I am assuming you want the expected output to be "between, begin sub2, end sub2" and not how you have it written. – StrongBad Jan 23 '14 at 18:43
1

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

0

Since someone provided the tricky answer (+1), I don't feel bad about suggesting the simple answer, which may or may not be helpful depending on what you really want to happen near the 'edges' or your sub-files.

\documentclass{scrartcl}
\parindent 0pt
\usepackage[subpreambles]{standalone}
\AtBeginDocument{main.tex: begin main\par}
\AtEndDocument{main.tex:   end main\par}

\usepackage{xparse}
\NewDocumentCommand{\myinput}{omo}
{\IfNoValueTF{#3}%
  {\IfNoValueTF{#1}%
    {\input{#2}}%
    {#1\par\input{#2}}}%
  {\IfNoValueTF{#1}%
    {\input{#2}\par#3\par}%
    {#1\par\input{#2}\par#3\par}}%
}

\begin{document}%

before

\myinput{sub1}

between

\myinput[sub1: before (no after)]{sub1}

between

\myinput{sub1}[sub1: after (no before) ]

between

\myinput[sub2: before]{sub2}[sub2: after]

\end{document}

Then remove all the \At<etc.> arguments from your sub-files:

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

and

% sub1.tex
\documentclass{standalone}
% \AtBeginDocument{begin sub2 \\}
% \AtEndDocument{end sub2 \\}
\begin{document}%
sub2 -- main text
\end{document}
  • This doesn't work in the sense that if you compile the sub1 on its own you lose the before/after code. – StrongBad Jan 23 '14 at 19:21
  • @DanielE.Shub -- Not necessarily: standalone has commands like \ifstandalone which would easily solve that problem, depending on what the \At<etc.> stuff is supposed to do. I was merely waiting to see what that code really was before worrying about it. I assume it's not just a matter of inserting text in an awkward sort of way.... – jon Jan 23 '14 at 19:44

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.