dtx 序言中的危險 \if@

dtx 序言中的危險 \if@

為什麼以下內容.dtx無法編譯,而等效.tex檔案卻可以編譯? (您必須命名該文件error.dtx,這就是\DocInput包含的內容。)

數位傳輸:

% \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 的「文件」部分。為此,定義中的註解字元需要轉換為^^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\ifpgfutil@in@在第二遍中找不到任何內容,因為 的目錄代碼@是其他,而不是字母 ---\makeatletter被卡\iffalse\ifpgfutil@in@\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

或者,也許更好,將所有潛在的違規代碼放在一個單獨的文件中...

相關內容