使用星号版本作为可选参数

使用星号版本作为可选参数

我一直在阅读有关使用 *-options 定义命令的此页面。但我完全陷入困境。我想要以下内容。

带有可选参数和星号选项的命令。

可选参数:\cmd{b}-->N_b\cmd[a]{b}-->N_b(a)

带星号的论点:\cmd*{b}-->N^*_b\cmd*[a]{b}-->N^*_b(a)

不过,我不确定是否可以使用星号参数以及可选参数。

这些是我的尝试,但是没有效果。

\makeatletter
\newcommand{\cmd}[2]{%
    \@ifstar
    {%
        \ifthenelse{\equal{}{#1}}%
        {\NN^*_{#2}}%
        {\NN^*_{#2}(#1)}%
    }%
    {%
        \ifthenelse{\equal{}{#1}}%
        {\NN_{#2}}%
        {\NN_{#2}(#1)}%
    }
}
\makeatother

---------------

\makeatletter
\newcommand{\cmd}[2]{%
    \@ifstar
    \cmdStar[#1]{#2}%
    \cmdNoStar[#1]{#2}%
    \makeatother
}
\newcommand{\cmdStar}[2]{%
    \ifthenelse{\equal{}{#1}}
    {\NN_{#2}}
    {\NN_{#2}(#1)}
}
\newcommand{\cmdNoStar}[2]{%
    \ifthenelse{\equal{}{#1}}
    {\NN^*_{#2}}
    {\NN^*_{#2}(#1)}
}

答案1

您首先要区分是否*出现。

\newcommand{\cmd}{N\@ifstar{^*\@cmd}{\@cmd}}

然后你定义\@cmd

\newcommand{\@cmd}[2][]{%
  _{#2}%
  \if\relax\detokenize{#1}\relax
    % no or empty optional argument
  \else
    (#1)%
  \fi
}

因为我们使用@-commands,所以它前面\makeatletter和后面都应该是\makeatother。不过,也可以通过选择“奇怪的”名称来省去@命令名称。

用 就更简单了\NewDocumentCommand

\NewDocumentCommand{\bettercmd}{som}{%
  N_{#3}%
  \IfBooleanT{#1}{^*}% add the asterisk
  \IfValueT{#2}{(#2)}% there is an optional argument
}

笔记。

  • s引入一个可能的*变体;如果*出现,则命令\IfBooleanTF{#1}{TRUE}{FALSE}将返回TRUEFALSE否则返回。由于当没有时我们什么也不做,因此使用仅在存在时添加上标*更为简单。\IfBoolean{T}{#1}{^*}*
  • o引入可选参数;如果[在预期位置没有出现,\IfValueTF{#2}{TRUE}{FALSE}则返回FALSE,否则返回TRUE。同样,由于当可选参数不存在时我们什么也不做,因此使用更简单\IfValueT{#2}{(#2)}
  • m引入一个强制参数(通常在括号之间)。

测试文档

\documentclass{article}

\makeatletter
\newcommand{\cmd}{N\@ifstar{^*\@cmd}{\@cmd}}
\newcommand{\@cmd}[2][]{%
  _{#2}%
  \if\relax\detokenize{#1}\relax
    % no or empty optional argument
  \else
    (#1)%
  \fi
}
\makeatother

\NewDocumentCommand{\bettercmd}{som}{%
  N_{#3}%
  \IfBooleanT{#1}{^*}% add the asterisk
  \IfValueT{#2}{(#2)}% there is an optional argument
}

\begin{document}

$\cmd{b}+\cmd[a]{b}+\cmd*{b}+\cmd*[a]{b}$

$\bettercmd{b}+\bettercmd[a]{b}+\bettercmd*{b}+\bettercmd*[a]{b}$

\end{document}

在此处输入图片描述

答案2

使用当前版本的 LaTeX,您可以使用\NewDocumentCommand,这使得一次性编写带有星号版本和可选参数的命令变得非常容易。

\usepackage{xparse}(如果您使用的是旧版本的 LaTeX,则在 之前添加序言,以下代码很可能会起作用\ExplSyntaxOn。)

\documentclass{article}

\ExplSyntaxOn
\NewDocumentCommand{\cmd}{som}
  {
    N
    \sb{#3}
    \IfBooleanT{#1}
      {
        \sp{*}
      }
    \IfValueT{#2}
      {
        (#2)
      }
  }
\ExplSyntaxOff

\begin{document}
unstarred $\cmd{b}$ and $\cmd[a]{b}$

starred $\cmd*{b}$ and $\cmd*[a]{b}$
\end{document}

无星号的 N_b 和 N_b(a)//有星号的 N^∗_b 和 N^∗_b(a)

\sb可以用来替代_数学下标,也可以用来\sp替代^数学上标。

如果你不太喜欢\ExplSyntaxOn\ExplSyntaxOff你可以选择

\NewDocumentCommand{\cmd}{som}{%
  N_{#3}%
  \IfBooleanT{#1}{^{*}}%
  \IfValueT{#2}{(#2)}%
}

相反,我们需要%像往常一样避免出现虚假空间。


对于更经典的 LaTeX2e 方法,我建议使用类似

\documentclass{article}

\usepackage{etoolbox}

\makeatletter
\newcommand*{\cmd}{\@ifstar{\cmd@i{*}}{\cmd@i{}}}
\newcommand*{\cmd@i}[1]{%
  \@ifnextchar[%]
    {\cmd@ii{#1}}
    {\cmd@ii{#1}[]}}

\def\cmd@ii#1[#2]#3{%
  N_{#3}%
  \ifblank{#1}{}{^{#1}}%
  \ifblank{#2}{}{(#2)}%
}
\makeatother

\begin{document}
unstarred $\cmd{b}$ and $\cmd[a]{b}$

starred $\cmd*{b}$ and $\cmd*[a]{b}$
\end{document}

首先,我们用 检查星号\@ifstar。为了减少代码重复,如果星号存在,我们将它作为辅助命令的第一个参数传递。如果没有星号,我们只传递一个空参数。然后我们继续获取可选参数。同样通过辅助命令,[]如果没有可选参数,则插入。最后,我们可以将执行实际排版的宏定义为一个带有三个参数的宏,#1分别是星号、[#2]方括号中的可选参数([]如果没有提供),#3最后的强制参数。

这里我使用了etoolboxfor 来\ifblank检查参数是否为空,严格来说这并不等同于未给出。

如果您愿意ifthen,您可以删除\usepackage{etoolbox}并添加

\usepackage{ifthen}
\newcommand*{\ifblank}[1]{\ifthenelse{\equal{}{#1}}}

\newcommand{\cmd}[2]{%
    \@ifstar
    ...
}

并没有像预期的那样工作,因为这样的定义首先尝试获取两个强制(带括号的)参数,然后抓取参数检查是否有星号跟随。

因为\cmd*{b}这实际上意味着是#1*#2b因为\cmd[a]{b}我们将得到#1->[#2-> a

答案3

基于这个答案您可以执行以下操作:

\documentclass{article}
\usepackage{ifthen}
\makeatletter
\newcommand{\cmd}[0]{\@ifstar{\@cmdA}{\@cmdB}} % Create \cmd which has *no* arguments, it only checks whether '*' was used or not and then uses \@cmdA resp. \@cmdB.

\newcommand{\@cmdA}[2][]{ %     \@cmdA is the starred version.
   \ensuremath{%                Make sure everything is in math mode.
      N^{\ast}_{#2\ifthenelse{% Type 'N^*_{bXXX}' ...
       \equal{#1}{}}{}{(#1)}%   ... where 'XXX' is '', if there is no optional argument, otherwise '(a)'.
      }%
   }%
}

\newcommand{\@cmdB}[2][]{%      \@cmdB is the unstarred version.
   \ensuremath{%                Do exactly the same like in \@cmdA, but without the asterisk.
      N_{#2\ifthenelse{%
         \equal{#1}{}}{}{(#1)}%
      }%
   }%
}
\makeatother

\begin{document}
   \cmd{b}   \quad   \cmd[a]{b}   \quad   \cmd*{b}   \quad   \cmd*[a]{b}
\end{document}

上述代码的结果。


编辑:'(a)' 作为 'N' 的参数,而不是 'b' 的参数

在看到 Moewe 的回答后,我意识到(a)不应该是的论点b,而是的论点,所以这里是和N的更新版本:\@cmdA\@cmdB

\newcommand{\@cmdA}[2][]{ %     \@cmdA is the starred version.
   \ensuremath{%                Make sure everything is in math mode.
      N^{\ast}_{#2}\ifthenelse{% Type 'N^*_{b}XXX' ...
         \equal{#1}{}%
      }{}{(#1)}%                 ... where 'XXX' is '', if the optional argument is empty (default), otherwise '(a)'.
   }%
}

\newcommand{\@cmdB}[2][]{%      \@cmdB is the unstarred version.
   \ensuremath{%                Do exactly the same like in \@cmdA, but without the asterisk.
      N_{#2}\ifthenelse{\equal{#1}{}}{}{(#1)}%
   }%
}

生产 上述代码的结果。

相关内容