在 \DeclareDocumentCommand 信号中缺少第一个可选参数

在 \DeclareDocumentCommand 信号中缺少第一个可选参数

如果\DeclareDocumentCommand我有两个连续的可选参数,我该如何表示第一个参数缺失了?

例如:

\documentclass{article}
\usepackage{xparse}
\begin{document}

\ExplSyntaxOn   
\DeclareDocumentCommand{\test}{o o}
{
\IfValueTF{#1}
    {#1}{#2}
}
\ExplSyntaxOff  

\test[][1]
\end{document}

不产生任何结果,我希望它产生 1。

答案1

不传递任何内容和不使用它之间是有区别的。事实上,你的测试\IfValueTF{#1}结果为真,因为它#1有一个值,即使这个值可能是空的。

要测试是否传递空参数(换句话说,不传递任何内容),请使用以下技术如何检查宏值是否为空或不会使用纯 TeX 条件创建文本?

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareDocumentCommand{\test}{o o}
{
  \if\relax\detokenize{#1}\relax
    #2%
  \else
    #1%
  \fi
}
\ExplSyntaxOff  

\begin{document}
\test[][1]
\end{document}

或者使用真正的 LaTeX3 检查:

\ExplSyntaxOn
\DeclareDocumentCommand{\test}{o o}
{
  \tl_if_blank:nTF { #1 }
    { #2 }
    { #1 }
}
\ExplSyntaxOff  

请注意,如果用户界面中有 2 个可选参数使用相同的分隔符,则会引起混淆。仅有的传递第二个参数的另一种方法是同时指定第一个参数,这样它就不是可选的了。为此xparse提供调整参数分隔符的方法:

\ExplSyntaxOn
\DeclareDocumentCommand{\test}{o d()}
{
  \IfValueTF{#1}
    {#1}{#2}
}
\ExplSyntaxOff  

上面的 定义\test[<first>](<second>)有两个可选参数。第一个使用 ,[]而第二个使用(),明确区分了它们的用法,并且它们是完全可选的,如\test(1)

对于更复杂(多个)的参数,通常建议创建键值接口

答案2

LaTeX 内核中有一些命令允许连续使用两个或三个可选参数:

\makebox[<length>][<alignment>]{<text>}

\parbox[<outer alignment>][<height>][<inner alignment>]{<width>}{<text>}

(请注意minipage接受与 相同的参数\parbox,当然没有最后一个)。在这两种情况下,第一个之后的可选参数只有在前一个参数出现时才有意义。例如,选项<alignment>只有\makebox<width>指定 a 时才有意义。 的情况\parbox略有不同,但如果未指定,第一个可选参数也用于第三个;可能更好的语法应该是

\parbox[<outer alignment>]{<width>}[<height>][<inner alignment>]{<text>}

以便永远不会要求一个可选参数。

(及其变体) 命令接受两个可选参数\citebiblatex

\cite[<postnote>]{<key>}
\cite[<prenote>][<postnote>]{<key>}

这里有一个空的<postnote> 必须<prenote>如果只需要a,则指定

\cite[See][]{mykey}

amsref提出了一种替代语法:而不是\cite[<postnote>]{<key>},对于典型的情况,人们希望

[3,引理 4]

传统上输入为\cite[Lemma~4]{mykey},该包提供

\cite{mykey}*{Lemma~4}

我觉得这很有趣,但它不符合标准做法。请注意,这将允许(但实际上并不允许)以下语法:

\cite[<prenote>]{key}*{<postnote>}

这可能会更具可读性。

您会发现,构建良好的用户界面并非易事。但每当出现可选参数几乎成为必需参数的情况时,就必须深思熟虑。

在这些情况下,一个好的替代方案是键值接口;\parbox例如

\PARBOX[
  outer=<character>,% c (default), t or b
  inner=<character>,% default=outer, c, t, b or s
  height=<length>,
]{<width>}{<text>}

并且可以很容易地使outer和选项接受更长的值,inner例如topbottom或。centerspread

当选项彼此独立时,应该优先使用键值接口。

xparse也就是说,你可以通过定义新的“检查命令”来增强功能

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\IfBlankTF}{mmm}
 {
  \tl_if_blank:nTF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff

以便您以后可以将命令定义为

\NewDocumentCommand{\test}{o o}
 {%
  \IfNoValueTF{#1}
   {%
    Something for the case of no optional argument%
   }%
   {%
    \IfNoValueTF{#2}
     {%
      Something with #1 for the case of just one optional argument%
     }%
     {%
      \IfBlankTF{#1}
       {%
        Something with #2 for the case \string\test[][...]%
       }%
       {%
        Something with #1 and #2%
       }%
     }%
   }%
 }

相关内容