我遇到了一个与\NewDocumentCommand
参数有关的问题。如果参数中的名称很长,我想将它们分别放在一行中。前两个参数没有问题,后两个参数有问题,如 MWE 中所示。这是正常现象,还是错误,或者我做了什么蠢事?
\documentclass{article}
\usepackage{xparse}
% 12 3 4 56
\NewDocumentCommand\TestArg{st+ O{\empty}D(){\empty}mD()%
{\empty}O{\empty}}{%
% 7
\noindent
3: #3 \\
4: #4 \\
5: #5 \\
6: #6 \\
7: #7
}
\begin{document}
\TestArg[Three](Four){Five}(Six)[Seven]
\par\vspace{2\baselineskip}
\TestArg
[Three]
(Four)
{Five}
(Six)
[Seven]
\end{document}
答案1
让我们考虑一个更简单的例子:
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\TestArg{mO{x}}{%
1: #1, 2: #2
}
\begin{document}
\TestArg{a}[b]
\TestArg{a} [b]
\end{document}
这产生了
您可以清楚地看到,在第二种情况下,它不被识别为可选参数;而是使用[b]
默认值并单独打印,前面有一个空格。x
[b]
换行符算作一个空格,因此
\TestArg
{a}
[b]
产生相同的结果。
这是在开发 接口时做出的精确选择xparse
。团队遵循 的示例,amsmath
该示例不允许在 的可选参数前留空格\\
,因为 臭名昭著
\left[\begin{array}{cc}
1 & 2 \\
[1] & [2]
\end{array}\right]
这会引发错误,因为[1]
被误认为是 的可选参数\\
。相反
\begin{bmatrix}
1 & 2 \\
[1] & [2]
\end{bmatrix}
运行完美。
输入\TestArg{a} [b]
被视为含糊不清。有两种选择,团队遵循以下路径进行考虑[b]
不是一个可选参数。
你会得到同样的行为
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\TestArg{mD(){x}}{%
1: #1, 2: #2
}
\begin{document}
\TestArg{a}(b)
\TestArg{a} (b)
\end{document}
我认为,永远不应该定义带有七个参数的宏。在您的例子中,两个参数用于变体,四个参数是可选的,一个参数是必需的。
键值接口会更好:
\TestArg[
var-a=true,
var-b=false,
opt-A=Three,
opt-B=Four,
opt-C=Six,
opt-D=Seven,
]{Five}
顺便说一句,{\empty}
没有指定空的默认值:如果用测试\tl_if_empty:nTF{#3}
,缺少第一个可选参数将使 LaTeX 遵循错误的分支。
答案2
在最后一个强制参数后面的可选参数之前不能有空格,因此这是可行的。
\documentclass{article}
\usepackage{xparse}
% 12 3 4 56
\NewDocumentCommand\TestArg{st+ O{\empty}D(){\empty}mD()%
{\empty}O{\empty}}{%
% 7
\noindent
3: #3 \\
4: #4 \\
5: #5 \\
6: #6 \\
7: #7
}
\begin{document}
\TestArg[Three](Four){Five}(Six)[Seven]
\par\vspace{2\baselineskip}
\TestArg
[Three]
(Four)
{Five}%
(Six)%
[Seven]
\end{document}
这是设计使然,这样(就像中的可选参数一样amsmath
)你就不会在类似的事情中产生误解
.... 25\\
[foo] & 26 \\
其中,[foo]
是数组单元格中的数据,而不是\\
答案3
使用最新版本的xparse
,您会发现 已b
按预期被拾取。我们改进了尾随可选参数的处理,以便可以允许或禁止空格:
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\TestArgOne{m O{x}}{%
1: #1, 2: #2
}
\NewDocumentCommand\TestArgTwo{m!O{x}}{%
1: #1, 2: #2
}
\begin{document}
\TestArgOne{a}[b]
\TestArgOne{a} [b]
\TestArgTwo{a}[b]
\TestArgTwo{a} [b]
\end{document}
如您所见, 无论是否有空格,\TestArgOne
都会将作为可选参数。相比之下,对于我使用的语法,其中意味着可选参数[b]
\TestArgTwo
!O{x}
!
有紧接着没有空格。这种可控制的行为很有用,因为根据用例,空格可能有意义,也可能没有意义。(经典示例是\\[...]
,它用于数学模式,而之前的空格或换行符则意味着[
完全不同的东西。)