Ein gefährliches \if@ in der DTX-Präambel

Ein gefährliches \if@ in der DTX-Präambel

Warum wird das Folgende .dtxnicht kompiliert, die entsprechende .texDatei jedoch schon? (Sie müssen die Datei benennen error.dtx, denn das \DocInputschließt sie ein.)

DTX:

% \iffalse meta-comment
%<*driver>
\documentclass{ltxdoc}
\input pgfutil-common
\makeatletter
\def\myitem#1{%
  \pgfutil@in@{,}{#1}%
  \ifpgfutil@in@
    \myitem@#1\@end
  \else
    \myitem@#1,\@end
  \fi
}
\def\myitem@#1,#2\@end{\item\texttt{#1}\quad\marginpar{\small\it#2}}
\makeatother
\begin{document}
  \DocInput{error.dtx}
\end{document}
%</driver>
% \fi
% \begin{description}
%   \myitem{align,key} This is documentation for key \emph{align}.
% \end{description}
% \endinput

Latex:

\documentclass{ltxdoc}
\input pgfutil-common
\makeatletter
\def\myitem#1{%
  \pgfutil@in@{,}{#1}%
  \ifpgfutil@in@
    \myitem@#1\@end
  \else
    \myitem@#1,\@end
  \fi
}
\def\myitem@#1,#2\@end{\item\texttt{#1}\quad\marginpar{\small\it#2}}
\makeatother
\begin{document}
  \begin{description}
    \myitem{align,key} This is documentation for key \emph{align}.
  \end{description}
\end{document}

Antwort1

Die Diagnose, auf die dies zurückzuführen ist, \elseist richtig. Ein alternativer Lösungsansatz besteht darin, den neuen Code in den Docstrip-Teil „Dokument“ einzufügen. Dazu müssen die Kommentarzeichen in der Definition in^^A

% \iffalse meta-comment
%<*driver>
\documentclass{ltxdoc}
\input pgfutil-common %
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%\makeatletter
%\def\myitem#1{^^A
%  \pgfutil@in@{,}{#1}^^A
%  \ifpgfutil@in@
%    \myitem@#1\@end
%  \else
%    \myitem@#1,\@end
%  \fi
%}
%\def\myitem@#1,#2\@end{\item\texttt{#1}\quad\marginpar{\small\it#2}}
%\makeatother
% \show\myitem
% \begin{description}
%   \myitem{align,key} This is documentation for key \emph{align}.
% \end{description}
% \endinput

Antwort2

Wenn das Dokument zum zweiten Mal verarbeitet wird (und von eingegeben wird \DocInput), findet TeX \iffalseam Anfang der Datei. Dies soll mit dem folgenden Kommentarzeichen \iffalseübereinstimmen und so die Präambel überspringen. Aber das tut es nicht. Es bleibt bei in der Definition von hängen .\fi\else\myitem

Normalerweise \ifpgfutil@in@ist die Verwendung in verschachtelten Bedingungen sicher. Warum passiert das?

Die Antwort ist, dass TeX \ifpgfutil@in@beim zweiten Durchgang keins findet, da der Catcode von „ @other“ und nicht „letter“ ist --- \makeatletterwurde von „very“ übersprungen, das bei „s“ \iffalsehängen geblieben ist ...\ifpgfutil@in@\else

Eine schnelle und einfache Lösung besteht darin, einen Kommentar bereitzustellen \if, der für TeX erst beim zweiten Durchgang sichtbar ist:

% \iffalse meta-comment
%<*driver>
\documentclass{ltxdoc}
\input pgfutil-common
\makeatletter
\def\myitem#1{%
  \pgfutil@in@{,}{#1}%
  \ifpgfutil@in@          %\if
    \myitem@#1\@end
  \else
    \myitem@#1,\@end
  \fi
}
\def\myitem@#1,#2\@end{\item\texttt{#1}\quad\marginpar{\small\it#2}}
\makeatother
\begin{document}
  \DocInput{error.dtx}
\end{document}
%</driver>
% \fi
% \begin{description}
%   \myitem{align,key} This is documentation for key \emph{align}.
% \end{description}
% \endinput

Oder, vielleicht noch besser, den gesamten potenziell schädlichen Code in einer separaten Datei zu speichern ...

verwandte Informationen