在带有可选参数的命令中,如果我在可选参数中放入以 TeX 引号开头的字符串(例如“quote”),就会出错。请参阅下面示例中的底部条目。
这个例子比最简单的例子要多一些,因为我想在 PDF 中清楚地显示输入和输出。
\documentclass{article}
\usepackage{csquotes}
\newcommand{\optional}[2][\relax]{%
\ifx#1\relax
[\emph{no first arg}]
\else
[\emph{arg\#1:} #1]
\fi
\{\emph{arg\#2:} #2\}%
}
\begin{document}
\begin{tabular}{l}
%
\verb|\optional[first]{second}|\\
\optional[first]{second}\\[1ex]
%
\verb|\optional[]{second}|\\
\optional[]{second}\\[1ex]
%
\verb|\optional{only}|\\
\optional{only}\\[1ex]
%
\verb|\optional[\enquote{quote}]{second}|\\
\optional[\enquote{quote}]{second}\\[1ex]
%
\verb|\optional[``quote'']{second}|\\
\optional[``quote'']{second} % why does this go wrong?
\end{tabular}
\end{document}
答案1
在你的最后一个测试中,当宏扩展时,TeX 正在执行
\ifx``quote''\relax
它当然会返回 true,因为\ifx
比较了两个反引号。
仅当代码仅包含一个标记\ifx#1\relax
时,才可以依赖该代码。您可以执行;在这种情况下,最后一个测试将执行#1
\ifx\relax#1
\ifx\relax``quote''
并`quote''
会作为假枝的一部分消失。
看\ifx\\#1\\ 代表什么?寻找其他方法来测试可选参数是否缺失。
编写此宏的最佳方法是xparse
:
\usepackage{xparse}
\NewDocumentCommand{\optional}{om}{%
\IfNoValueTF{#1}
{[\emph{no first arg}]}
{[\emph{arg\#1:} #1]}%
\{\emph{arg\#2:} #2\}%
}
例子
\documentclass{article}
\usepackage{csquotes}
\usepackage{xparse}
\NewDocumentCommand{\optional}{om}{%
\IfNoValueTF{#1}
{[\emph{no first arg}]}
{[\emph{arg\#1:} #1]}%
\{\emph{arg\#2:} #2\}%
}
\begin{document}
\begin{tabular}{l}
%
\verb|\optional[first]{second}|\\
\optional[first]{second}\\[1ex]
%
\verb|\optional[]{second}|\\
\optional[]{second}\\[1ex]
%
\verb|\optional{only}|\\
\optional{only}\\[1ex]
%
\verb|\optional[\enquote{quote}]{second}|\\
\optional[\enquote{quote}]{second}\\[1ex]
%
\verb|\optional[``quote'']{second}|\\
\optional[``quote'']{second} % why does this go wrong?
\end{tabular}
\end{document}