When I thought I understood the concept of the doc
package, LaTeX proved me wrong.
I was trying to make a file to use with ltxdoc
when I realised I could not use conditionals in the preamble because they would break things by making TeX read stuff in the preamble from that point on, as it shouldn't. Then I tried to MWE-ify that code and stumbled upon a bigger problem.
When I thought I understood the concept of conditionals and expansion, TeX proved me wrong :)
Consider the following code (lines numbered to make reading easier):
01 % \tracingall
02 % \iffalse meta-comment ^^A This /iffalse
03 \documentclass{ltxdoc}
04 \def\showfi{\immediate\write0{{/fi\ on line \the\inputlineno}}}%
05 \title{Doc Test}%
06 \newif\ifitsme\itsmetrue
07 \ifitsme\author{Me :)}%
08 \else \author{Not me :/}%
09 \fi\showfi
10 \begin{document}%
11 \DocInput{\jobname}%
12 \tracingnone
13 \end{document}%
14 % \fi\showfi ^^A should match this /fi
15 % \fi\showfi ^^A but it's matching this one
16 % \tracingnone
17 % \maketitle
18 % \endinput
When LaTeX starts, comments are comments, so everything goes normally: load ltxdoc
; define the \showfi
(to log on what line the \fi
appears); give it a title to avoid an error; define a new \ifitsme
, set it to true, which makes Me :)
the author. Then I call \showif
just in case (not important now).
So far so good...
Then I \DocInput
this same file. Not comments aren't comments anymore and things go off the rails :)
\DocInput
starts reading the file from start. I turn on full-logging with \tracingall
and then comes the usual \iffalse meta-comment
from .dtx
files. This \iffalse
usually goes up to the \fi
right after the \end{document}
to continue reading the source.
What I think it should do:
This won't be the case because when TeX finds a false conditional it skips code without expansion until the next \else
or \fi
, which here is the \else
in line 08
(because TeX doesn't expand \ifitsme
to find out it's an \iftrue
). I would expect TeX to read that \else
and execute \author{Not me :/}
, then read the \fi
from line 09
and show {/fi\ on line 9}
in the log (Then another \begin{document}
would come up and break things, but this is an error for another day).
What it does:
TeX doesn't skip to the \fi
on line 09
, neither to the one on line 14
, but to an extra \fi
(that I added because it would throw an error otherwise) on line 15
. The log shows:
{\iffalse: (level 1) entered on line 2}
{false}
{\fi: \iffalse (level 1) entered on line 2}
\showfi ->\immediate \write 0{{/fi\ on line \the \inputlineno }}
{\immediate}
\write->{/fi\ on line \the \inputlineno }
{/fi\ on line 15}
What:
What is TeX actually doing that it does not behave as I expected? Why does it skip not only the 08 \else... 09 \if
, but also the 14 \fi
, requiring an additional \fi
inserted there for no (apparent) good reason?
Code without line-numbers for copy-pasting:
% \tracingall
% \iffalse meta-comment ^^A This /iffalse
\documentclass{ltxdoc}
\def\showfi{\immediate\write0{{/fi\ on line \the\inputlineno}}}%
\title{Doc Test}%
\newif\ifitsme\itsmetrue
\ifitsme\author{Me :)}%
\else \author{Not me :/}%
\fi\showfi
\begin{document}%
\DocInput{\jobname}%
\tracingnone
\end{document}%
% \fi\showfi ^^A should match this /fi
% \fi\showfi ^^A but it's matching this one
% \tracingnone
% \maketitle
% \endinput