如何定义 xparse \NewDocumentCommand 命令的包装器?

如何定义 xparse \NewDocumentCommand 命令的包装器?

我经常想定义一个命令(使用 xparse),如下所示

\NewDocumentCommand{\Comon}{oo}{
    \IfNoValueTF{#1}{
        \mathsf{Mod}
    }{
        \IfNoValueTF{#2}{
            \mathsf{Mod}_{#1}
        }{
            \mathsf{Mod}_{#1}(#2)
        }
    }
}

\Mod这样,具有不同数量可选参数的相同命令名将显示不同的结果。

理想情况下,我可以编写自己的命令\NewCommandAlts,调用方式如下

\NewCommandAlts{\Mod}{2}
    {\mathsf{Mod}}
    {\mathsf{Mod}_{#1}}
    {\mathsf{Mod}_{#1}(#2)}

并将定义一个\Mod与上面定义的命令等效的命令。

我所拥有的最好的东西是

\newcommand{\NewCommandAltsTwo}[4]{
    \NewDocumentCommand{#1}{oo}{
        \IfNoValueTF{##1}{#2}{\IfNoValueTF{##2}{#3}{#4}}
    }
}

\NewCommandAltsTwo{\Mod}
    {\mathsf{Mod}}
    {\mathsf{Mod}_{#1}}
    {\mathsf{Mod}_{#1}(#2)}

有效。对于如何编写处理任意数量参数的案例,您有什么想法吗?

答案1

只要仅在前 (k-1) 个可选参数也被指定的情况下指定第 k 个可选参数,您就可以执行以下操作:

\newcommand\Firstoftwo[2]{#1}%
\newcommand\Secondoftwo[2]{#2}%
\newcommand\NewCommandAlts[2]{%
  \ifcat$\detokenize\expandafter{\Firstoftwo#2{}{}}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
  {\NewDocumentCommand{#1}{}{}}%
  {\NewCommandAltsReverseLoop{0}{#1}{}{}#2{}{}\NewCommandAlts{}}%
}%
\csname @ifdefinable\endcsname\NewCommandAltsReverseLoop{%
  \long\def\NewCommandAltsReverseLoop#1#2#3#4#5#6\NewCommandAlts#7{%
    %#1 amount of items processed so far.
    %#2 command to define
    %#3 o-collection
    %#4 reversed list
    %#5 this item
    %#6 remaining items
    %#7 array of argument-numbers.
    \ifcat$\detokenize\expandafter{\Firstoftwo#6{}{}}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
    {%
      \expandafter\NewCommandAltsLoop\expandafter{\Firstoftwo{}#3}{#2}{}#4{}{}\NewCommandAlts{0}#7\NewCommandAlts
    }{%
      \expandafter\NewCommandAltsReverseLoop\expandafter{\number\numexpr#1+1\relax}{#2}{#3o}{{#5}#4}#6\NewCommandAlts{{#1}#7}%
    }%
  }%
}%
\csname @ifdefinable\endcsname\NewCommandAltsLoop{%
  \long\def\NewCommandAltsLoop#1#2#3#4#5\NewCommandAlts#6#7\NewCommandAlts{%
    %#1 o-collection
    %#2 command to define
    %#3 result
    %#4 this item
    %#5 remaining items
    %#6 this argument number
    %#7 remaining argument-numbers
    \ifcat$\detokenize{#5}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
    {%
      \NewDocumentCommand{#2}{#1}{#3}%
    }{%
      \ifnum#6=0 \expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
      {%
        \NewCommandAltsLoop{#1}{#2}{#4#3}#5\NewCommandAlts#7\NewCommandAlts
      }{%
        \NewCommandAltsLoop{#1}{#2}{\IfNoValueTF{###6}{#4}{#3}}#5\NewCommandAlts#7\NewCommandAlts
      }%
    }%
  }%
}%
\NewCommandAlts{\Mod}{%
    {\mathsf{Mod}} % Tokens in case no optional arguments
    {\mathsf{Mod}_{#1}} % Tokens in case one optional argument
    {\mathsf{Mod}_{#1}(#2)} % Tokens in case two optional arguments
    %{...} % Tokens in case three optional arguments
    %{...} % Tokens in case four optional arguments
    %{...} % Tokens in case five optional arguments
    %{...} % Tokens in case six optional arguments
    %{...} % Tokens in case seven optional arguments
    %{...} % Tokens in case eight optional arguments
    %{...} % Tokens in case nine optional arguments
}%

% \expandafter\show\csname Mod code\endcsname
% \ShowDocumentCommandArgSpec\Mod

\documentclass{article}
\begin{document}

$\Mod$

$\Mod[A]$

$\Mod[A][B]$

\end{document}

在此处输入图片描述

相关内容