R's Workshop

Define LaTeX Command with More than One Optional Arguments

以前自訂 LaTeX command 的時候, 通常是用 \newcommand 來做. \newcommand 的缺點是只能定義一個 optional argument, 要定義兩個以上的 optional arguments 就要用 command relaying 的方法, 很不直覺. Google 了一下, 幾個常見的解決方式有 twoopt, optparams, xargs, xparse. 這邊介紹 xparse 的用法.

xparse

xparse 除了支援定義多個 optional arguments 外, 另一個優點是 optional arguments 不需要寫在 mandatory arguments 前面, 可以交錯定義.

格式為 \NewDocumentCommand{command_name}{argument_spec}{code}

下面是一個簡單的範例.

\documentclass{article}
\usepackage{xparse}

% 2 mandatory arguments
\NewDocumentCommand{\myCmdA}{ m m }{#1~#2}

% 1st argument is mandatory, and 2nd is optional
\NewDocumentCommand{\myCmdB}{ m o }{#1~#2}

% 1st argument is optional, and 2nd is mandatory
\NewDocumentCommand{\myCmdC}{ o m }{#1~#2}

% 1st argument is optional, and 2nd is mandatory
% If 1st argument is empty, print `New` instead
\NewDocumentCommand{\myCmdD}{ o m }{ %
  \IfNoValueTF{#1}%
    {New~#2}%
    {#1~#2}%
}

% The first 2 arguments are optional with default value
% The last argument is mandatory
\NewDocumentCommand{\myCmdE}{ O{default1} O{default2} m }{#1~#2~#3}

\begin{document}

\begin{itemize}

  \item \textbf{\textbackslash myCmdA\{Hello\}\{World\}} \par
  \myCmdA{Hello}{World}
  
  \item \textbf{\textbackslash myCmdB\{Hello\}[World]} \par
  \myCmdB{Hello}[World]
  
  \item \textbf{\textbackslash myCmdB\{Hello\}} \par
  \myCmdB{Hello}

  \item \textbf{\textbackslash myCmdC[Hello]\{World\}} \par
  \myCmdC[Hello]{World}
  
  \item \textbf{\textbackslash myCmdC\{World\}} \par
  \myCmdC{World}

  \item \textbf{\textbackslash myCmdD[Hello]\{World\}} \par
  \myCmdD[Hello]{World}
  
  \item \textbf{\textbackslash myCmdD\{World\}} \par
  \myCmdD{World}

  \item \textbf{\textbackslash myCmdE\{foo\}} \par
  \myCmdE{foo}

  \item \textbf{\textbackslash myCmdE[nondefault1]\{foo\}} \par
  \myCmdE[nondefault1]{foo}

  \item \textbf{\textbackslash myCmdE[nondefault1][nondefault2]\{foo\}}\par
  \myCmdE[nondefault1][nondefault2]{foo}

\end{itemize}

\end{document}

Output 如下

• \myCmdA{Hello}{World}
  Hello World

• \myCmdB{Hello}[World]
  Hello World

• \myCmdB{Hello}
  Hello -NoValue-

• \myCmdC[Hello]{World}
  Hello World

• \myCmdC{World}
  -NoValue- World

• \myCmdD[Hello]{World}
  Hello World

• \myCmdD{World}
  New World

• \myCmdE{foo}
  default1 default2 foo

• \myCmdE[nondefault1]{foo}
  nondefault1 default2 foo

• \myCmdE[nondefault1][nondefault2]{foo}
  nondefault1 nondefault2 foo

Reference

LaTeX