我正在尝试定义一个具有可选参数的宏,该宏可以将带有可选参数的宏作为参数。下面是一个最简单的示例,可以更清楚地解释该问题:
\documentclass{article}
\newcommand*{\inn}[1][a]{#1}
\newcommand*{\out}[1][\inn]{\underline{#1}}
% \newcommand*{\out}[1][\inn]{\underline{#1}} % this also doesn't work (1)
% \newcommand*{\out}[1][\inn]{{#1}} % this also doesn't work (2)
\begin{document}
$\out[\inn[b]]$
% $\out[{\inn[b]}]$ % this works (3)
\end{document}
我收到错误! Argument of \\inn has an extra }
。如所示,我可以根据具体情况修复该问题,但不能一般性地修复(使用宏的正确定义)。
\underline
我一开始以为这是由脆弱性引起的问题。但是使用\ensuremath
或\protected
并没有找到解决方案。
我怎样才能修复宏,让它们按照我的要求执行而不会出现错误?
答案1
LaTeX2e 获取可选参数的方法是使用 TeX 分隔宏,即寻找一个开口,[
然后使用以以下形式定义的宏
\def\foo[#1]{...
这将始终抓取第一个,]
而不是进行括号匹配。当然可以匹配括号。使用xparse
因为它是内置的
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\inn{O{a}}{#1}
\NewDocumentCommand\out{O{\inn}}{\underline{#1}}
\begin{document}
$\out[\inn[b]]$
\end{document}
请注意,使用 定义的命令xparse
使用与 不同的语法进行声明\newcommand
。这里,可选参数是 type O
,默认值作为 的参数给出O
。
答案2
如果您愿意接受xparse
,则可以\NewDocumentCommand
嵌套可选参数而无需附加参数。{}
的语法\NewDocumentCommand
与 不同,\newcommand
对于初学者来说有点令人困惑,但我最近改用了它,不会再怀念它了。我推荐xparse
和 它的宏,只要不需要扩展(除了功能\DeclareExpandableDocumentCommand
)
\documentclass{article}
\usepackage{xparse}
\newcommand*{\inn}[1][a]{#1}
\newcommand*{\out}[1][{\inn}]{\underline{#1}}
% \newcommand*{\out}[1][\inn]{\underline{#1}} % this also doesn't work
% \newcommand*{\out}[1][\inn]{{#1}} % this also doesn't work
\NewDocumentCommand{\Inn}{O{a}}{%
#1%
}
\NewDocumentCommand{\Out}{O{\Inn}}{%
\underline{#1}%
}
\begin{document}
\out[{\inn[b]}] % original version
\Out[\Inn[b]] % Double []
\Out[\Inn]
\end{document}