
Почему следующий код .dtx
не компилируется, а эквивалентный .tex
файл компилируется? (Вы должны назвать файл error.dtx
, это то, что \DocInput
включено.)
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
Латекс:
\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}
решение1
Диагноз, из-за которого это происходит, \else
правильный. Альтернативный подход к решению этой проблемы — поместить новый код в часть Docstrip 'document'. Для этого необходимо преобразовать символы комментариев в определении в^^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
решение2
Когда документ обрабатывается во второй раз (вводится \DocInput
), TeX находит \iffalse
в верхней части файла. Предполагается, что это \iffalse
будет соответствовать \fi
следующему за комментарием знаку, тем самым пропуская преамбулу. Но этого не происходит. Он застревает \else
в определении \myitem
.
Обычно \ifpgfutil@in@
его безопасно использовать во вложенных условных операторах. Так почему же это происходит?
Ответ в том, что TeX не находит «no» \ifpgfutil@in@
при втором проходе, так как catcode — @
это другой, а не буква — \makeatletter
был пропущен тем самым \iffalse
, который застрял на \ifpgfutil@in@
«s» \else
...
Быстрое и грубое решение — предоставить комментарий \if
, который будет виден только TeX при втором проходе:
% \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
Или, может быть, даже лучше, поместить весь потенциально опасный код в отдельный файл...