我一直在阅读有关使用 *-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}
将返回TRUE
,FALSE
否则返回。由于当没有时我们什么也不做,因此使用仅在存在时添加上标*
更为简单。\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}
\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
最后的强制参数。
这里我使用了etoolbox
for 来\ifblank
检查参数是否为空,严格来说这并不等同于未给出。
如果您愿意ifthen
,您可以删除\usepackage{etoolbox}
并添加
\usepackage{ifthen}
\newcommand*{\ifblank}[1]{\ifthenelse{\equal{}{#1}}}
这
\newcommand{\cmd}[2]{%
\@ifstar
...
}
并没有像预期的那样工作,因为这样的定义首先尝试获取两个强制(带括号的)参数,然后后抓取参数检查是否有星号跟随。
因为\cmd*{b}
这实际上意味着是#1
且*
是#2
。b
因为\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)}%
}%
}