Um \if@ perigoso no preâmbulo do dtx

Um \if@ perigoso no preâmbulo do dtx

Por que o seguinte .dtxnão é compilado, enquanto o .texarquivo equivalente sim? (Você deve nomear o arquivo error.dtx, é isso que \DocInputinclui.)

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

Látex:

\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}

Responder1

O diagnóstico a que isso se deve \elseestá correto. Uma abordagem alternativa para resolver isso é colocar o novo código na parte do 'documento' do Docstrip. Para fazer isso, os caracteres de comentário na definição precisarão ser convertidos para^^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

Responder2

Quando o documento é processado pela segunda vez (sendo inserido por \DocInput), o TeX fica \iffalseno topo do arquivo. A intenção é que \iffalsecorresponda ao \fisinal de comentário seguinte, pulando assim o preâmbulo. Mas isso não acontece. Fica preso \elsena definição de \myitem.

Normalmente, \ifpgfutil@in@é seguro usar em condicionais aninhadas, então por que isso acontece?

A resposta é que o TeX não encontra \ifpgfutil@in@na segunda passagem, já que o catcode de @é outro, não a letra --- \makeatletterfoi ignorado pelo mesmo \iffalseque ficou preso em \ifpgfutil@in@'s \else...

Uma solução rápida e suja é fornecer um comentário \ifque só ficará visível para o TeX na segunda passagem:

% \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

Ou, talvez ainda melhor, colocar todo o código potencialmente ofensivo em um arquivo separado...

informação relacionada