如何调用一个接受用 `\NewDocumentCommand` 定义的 2 个可选参数的命令,并仅将第二个可选参数传递给它(跳过第一个)?

如何调用一个接受用 `\NewDocumentCommand` 定义的 2 个可选参数的命令,并仅将第二个可选参数传递给它(跳过第一个)?

如果\myB接受两个可选参数,\myB则将它们都设置为默认值,\myB[5]将第一个设置为 ,5将第二个设置为 ,\myB[5][10]将第一个设置为 ,5将第二个设置为10。但是我们如何只设置#2参数呢?这样做\myB[][10]不会将第一个参数设置为默认值(只会使其消失)。

\documentclass{standalone}
\usepackage{xparse}
% each of two optional arguments defaults to zero
\NewDocumentCommand{\myB}{O{0}O{0}}
  {%
    myB: #1, #2%
  }
\begin{document}
% how to call `myB` so that it only has #2 set? (not #1)
\myB[][6] % this is no good since `[]` removes default zero
\end{document}

答案1

作为Phelype Oleinik 建议您可以使用空的第一个可选参数,如果为空则分配默认值。我会使用参数处理器来做到这一点:

\ExplSyntaxOn
\cs_new_protected:Npn \__bdmmxvii_Oarg_proc:nn #1 #2
  {
    \tl_if_empty:nTF { #2 }
      { \cs_set:Npn \ProcessedArgument { #1 } }
      { \cs_set:Npn \ProcessedArgument { #2 } }
  }
\NewDocumentCommand \twooptsA { >{ \__bdmmxvii_Oarg_proc:nn { 0 } }O{} O{0} }
  {
    myB:~#1,~#2
  }
\ExplSyntaxOff

另外,我对星星的建议是:

\ExplSyntaxOn
\NewDocumentCommand \twooptsB { O{0} s O{0} }
  {
    myB:~#1,~#3
  }
\ExplSyntaxOff

第三种选择是 key=value 语法:

\ExplSyntaxOn
\keys_define:nn { bdmmxvii }
  {
    ,1 .tl_set:N  = \__bdmmxvii_arg_a_tl
    ,1 .initial:n = 0
    ,2 .tl_set:N  = \__bdmmxvii_arg_b_tl
    ,2 .initial:n = 0
  }
\NewDocumentCommand \twooptsC { O{} }
  {
    \group_begin:
    \keys_set:nn { bdmmxvii } { #1 }
    \__bdmmxvii_twooptsC:VV \__bdmmxvii_arg_a_tl \__bdmmxvii_arg_b_tl
    \group_end:
  }
\cs_new:Npn \__bdmmxvii_twooptsC:nn #1 #2
  {
    myB:~#1,~#2
  }
\cs_generate_variant:Nn \__bdmmxvii_twooptsC:nn { VV }
\ExplSyntaxOff

所有内容都包含在一个文档中:

\documentclass[]{article}

\usepackage{xparse}

\ExplSyntaxOn
\cs_new_protected:Npn \__bdmmxvii_Oarg_proc:nn #1 #2
  {
    \tl_if_empty:nTF { #2 }
      { \cs_set:Npn \ProcessedArgument { #1 } }
      { \cs_set:Npn \ProcessedArgument { #2 } }
  }
\NewDocumentCommand \twooptsA { >{ \__bdmmxvii_Oarg_proc:nn { 0 } }O{} O{0} }
  {
    myB:~#1,~#2
  }
\NewDocumentCommand \twooptsB { O{0} s O{0} }
  {
    myB:~#1,~#3
  }
\keys_define:nn { bdmmxvii }
  {
    ,1 .tl_set:N  = \__bdmmxvii_arg_a_tl
    ,1 .initial:n = 0
    ,2 .tl_set:N  = \__bdmmxvii_arg_b_tl
    ,2 .initial:n = 0
  }
\NewDocumentCommand \twooptsC { O{} }
  {
    \group_begin:
    \keys_set:nn { bdmmxvii } { #1 }
    \__bdmmxvii_twooptsC:VV \__bdmmxvii_arg_a_tl \__bdmmxvii_arg_b_tl
    \group_end:
  }
\cs_new:Npn \__bdmmxvii_twooptsC:nn #1 #2
  {
    myB:~#1,~#2
  }
\cs_generate_variant:Nn \__bdmmxvii_twooptsC:nn { VV }
\ExplSyntaxOff

\begin{document}
\twooptsA\ \twooptsA[1][2] \twooptsA[1] \twooptsA[][2]

\twooptsB\ \twooptsB[1][2] \twooptsB[1] \twooptsB*[2]

\twooptsC\ \twooptsC[1=1,2=2] \twooptsC[1=1] \twooptsC[2=2]
\end{document}

一切结果都一样:

在此处输入图片描述

答案2

这是错误的语法,您应该考虑避免它。

无论如何,你可以对参数进行预处理。当然,你不能将第一个可选参数设置为空。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\IfEmpty}{mm}
 {
  \tl_if_blank:nTF { #2 }
   { \tl_set:Nn \ProcessedArgument { #1 } }
   { \tl_set:Nn \ProcessedArgument { #2 } }
 }
\ExplSyntaxOff

\NewDocumentCommand{\myB}{>{\IfEmpty{0}}O{0}O{0}}{%
  \#1 is #1 -- \#2 is #2
}

\begin{document}

\myB

\myB[1]

\myB[1][2]

\myB[][3]

\end{document}

在此处输入图片描述

答案3

另一种选择:使用不同的参数分隔符,使用说明符D

\NewDocumentCommand{\myB}{ D(){0} O{0} }{%
  \#1 = #1, \#2 = #2%
}

\myB       % #1 = 0, #2 = 0
\myB(1)    % #1 = 1, #2 = 0
\myB[2]    % #1 = 0, #2 = 2
\myB(1)[2] % #1 = 1, #2 = 2

相关内容