dtx 前导中的危险 \if@

dtx 前导中的危险 \if@

为什么下面的代码.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“文档”部分中。为此,定义中的注释字符需要转换为^^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@在第二次传递时发现没有,因为 的 catcode@是其他的,而不是字母 ---\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

或者,也许更好的是,将所有可能有问题的代码放在单独的文件中......

相关内容