\NewDocumentCommand:为什么我不能将参数放在一行上?

\NewDocumentCommand:为什么我不能将参数放在一行上?

我遇到了一个与\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}!紧接着没有空格。这种可控制的行为很有用,因为根据用例,空格可能有意义,也可能没有意义。(经典示例是\\[...],它用于数学模式,而之前的空格或换行符则意味着[完全不同的东西。)

相关内容