Document inclusion by checking existence of command

I am trying to exploit \ifdefined to write a document with multiple files. My idea is the following: I define \ifNotEmbedded as \let\ifNotEmbedded\iffalse in the main document and wrap the preamble of each included file in a checking \ifNotEmbedded.

For example, the main file:

% main.tex
\let\ifNotEmbedded\iffalse
\documentclass{article}
\begin{document}
\input{introduction.tex}
\end{document}


and the included file:

%introduction.tex
\ifdefined\ifNotEmbedded
\else
\let\ifNotEmbedded\iftrue
\fi

\ifNotEmbedded
\documentclass{article}
\begin{document}
\fi
The content of the introduction goes here.
\ifNotEmbedded
\end{document}
\fi


By doing this, I can write the content of introduction.tex and test it like a standalone document without having to compile the bigger main.tex over and over again and when everything is ready, I can just compile main.tex to get the complete article.

The issue I am getting is that: It works perfectly if I compile introduction.tex by itself but when I compile main.tex, the inclusion doesn't work: I get the following error

! Incomplete \ifdefined; all text was ignored after line 3.

How can I make this idea work?

• I can't compile introduction.tex ... – user31729 Jan 16 '18 at 20:46
• @ChristianHupfer Sorry, LaTeX doesn't seem to like empty document. I remove the comment and it should work. – An Hoa Jan 16 '18 at 20:51
• No, the error was \if\ifdefined... in your introduction.tex, but it compiles now; main.tex not yet... however – user31729 Jan 16 '18 at 20:53
• @ChristianHupfer I already fixed that mistake \if\ifdefined in some earlier edit. – An Hoa Jan 16 '18 at 21:02
• the reason it fails is the usual faq about tex conditionals, if the initial test is true the the \else clause is skipped but matching if..fi . As tex is skipping it does not see \let but it does see \ifNotEmbedded and \iftrue so it needs to see, and skip over two \fi before seeing a \fi that ends the test. – David Carlisle Jan 16 '18 at 21:26

\documentclass{article}

\begin{document}

\input{intro}
\end{document}


then intro.tex could be

\makeatletter
\ifx\documentclass\@twoclasseserror
\typeout{skipping preamble}
\long\def\zzbegin#1\begin#2{}
\long\def\zzend#1#2{}
\else
\typeout{using preamble}
\let\zzbegin\relax
\let\zzend\relax
\fi
\makeatother

\zzbegin
\documentclass{article}
\begin{document}

% The content of the introduction goes here
Foo stuff

\zzend
\end{document}


Alternatively of course you could use the standard \include mechanism which would have the advantage that you can process individual sections even if they have \ref to items in other sections.

I am replicating @DavidCarlisle explanation in the comment and give a fix to the original problem. @DavidCarlisle solution should be preferred since it doesn't depend on eTeX (works with Knuth's TeX as well).

The main issue is that conditionals within \else .. \fi are also matched to support the consecutive case scenario (#if ... #elseif ... #elseif ... #endif in C++ for example). In my code, if \ifNotEmbedded is defined (when compiling main.tex), the \else won't see \let but still see the conditionals \ifNotEmbedded\iftrue so it expects two matching \fi\fi.

Due to fragility of conditionals within conditional, an easy fix to my original code would be to avoid it by defining a meaningless guarding command, say \let\InMainFile\relax and then check if it is defined in those included files i.e. the main file

%main.tex
\let\InMainFile\relax
\documentclass{article}

\begin{document}
\input{introduction.tex}
\end{document}


and the included file

%introduction.tex
\unless\ifdefined\InMainFile
\documentclass{article}
\begin{document}
\fi

The content of the introduction goes here.

\unless\ifdefined\InMainFile
\end{document}
\fi


If one is familiar with C/C++, this is exactly the same as using #ifdef. I wonder why eTeX doesn't provide another primitive \ifundefined.