定义宏的规范方法是什么(大概现在首选 xparse),它根据一组离散选择之一采取不同的行为。
\mymacro[a]{does one thing, e.g., print this in red}
\mymacro[b]{does another thing, e.g., print this in footnotesize}
\mymacro[c]{yet something else, e.g., shows a dagger}
\mymacro[uuu]{throw a latex error, because uuu is undefined}
我自己已经写过几次了(用ifthenelse
),但我不知道我是否破坏了意图。有没有规范的方法?
答案1
您可以使用\str_case
\documentclass{article}
\usepackage{color}
\ExplSyntaxOn
\cs_new:Npn\tmp_case:n#1{
\str_case:nnF{#1}{
{}{nothing}
{a}{does~one~thing,~e.g.,~print~this~in~\textcolor{red}{red}}
{b}{does~another~thing,~e.g.,~print~this~in~{\footnotesize footnotesize}}
{c}{yet~something~else,~e.g.,~shows~a~dagger~$\dagger$}
}
{\PackageError{tmp}{bad~string:~#1}{}}
}
\NewDocumentCommand\mymacro{O{}}% why optional?
{\tmp_case:n{#1}}
\ExplSyntaxOff
\begin{document}
\mymacro
\mymacro[a]
\mymacro[uuu]
\end{document}
这使
! Package tmp Error: bad string: uuu.
See the tmp package documentation for explanation.
Type H <return> for immediate help.
...
l.25 \mymacro[uuu]
?
答案2
\ifcase
在我的评论中,我建议在选项以整数替代形式提供时使用。但是,如果您坚持使用字符串选项...
我不确定你的问题是否有一个规范的答案,因为你在 MWE 中指定的结果不符合模式……例如“显示匕首”没有使用提供的参数,而“用红色打印”则使用了。
因此我制定了一种方法,基本上要求你定义所有行动就单个参数宏而言。此类操作通常不需要参数,但您必须创建一个需要参数的宏。
基本上,\setoption[<option name>]{<action>}
用于定义的语法行动s(如上所述,行动负责吸收提供给 的主要参数\mymacro
。 调用是通过 完成的\mymacro[<option name>]{<argument>}
。
\documentclass{article}
\usepackage{xcolor}
\def\setoption#1#2{\expandafter\def\csname option#1\endcsname{#2}}
\newcommand\mymacro[1][undefined]{\ifcsname option#1\endcsname
\def\next{\csname option#1\endcsname}%
\else
\def\next{\setundef{#1}}%
\fi
\next
}
\setoption{a}{\textcolor{red}}
\setoption{b}{\setfootsize}
\setoption{c}{\setdag}
\newcommand\setfootsize[1]{{\footnotesize#1}}
\newcommand\setdag[1]{$\dag$}% #1 discarded
\newcommand\setundef[2]{Undefined option: #1}% #2 discarded
\begin{document}
\mymacro[a]{does one thing, e.g., print this in red}
\mymacro[b]{does another thing, e.g., print this in footnotesize}
\mymacro[c]{yet something else, e.g., shows a dagger}
\mymacro[uuu]{throw a latex error, because uuu is undefined}
\end{document}
答案3
一定不是with \ifthenelse
:如果选择过多,则嵌套变得无法进行:
\newcommand{\mymacro}[1][]{%
\ifthenelse{\equal{#1}{}}{nothing}{%
\ifthenelse{\equal{#1}{a}}{\textcolor{red}{Something}}{%
\ifthenelse{\equal{#1}{b}}{{\footnotesize something}}{%
\ifthenelse{\equal{#1}{c}}{\textdagger}{%
\ERROR
}%
}%
}%
}%
}
(我甚至不想尝试看看它是否正确)。
可能的替代方法
\documentclass{article}
\usepackage{xcolor}
\makeatletter
\newcommand{\defineswitchmacro}[2]{%
\@ifdefinable{#1}{%
\newcommand#1[1][]{%
\@ifundefined{\string#1@##1}{\ERROR}{\@nameuse{\string#1@##1}}%
}%
\defineswitchmacro@{#1}#2\relax\relax
}%
}
\newcommand{\defineswitchmacro@}[3]{%
\ifx#2\relax
\expandafter\@gobble
\else
\@namedef{\string#1@#2}{#3}
\expandafter\@firstofone
\fi
{\defineswitchmacro@{#1}}%
}
\makeatother
\defineswitchmacro{\mymacro}{
{}{nothing}
{a}{\textcolor{red}{Something}}
{b}{{\footnotesize Something}}
{c}{\textdagger}
}
\begin{document}
\mymacro\par
\mymacro[a]\par
\mymacro[b]\par
\mymacro[c]\par
\mymacro[uuu]
\end{document}
使用比所获更有意义的错误消息\ERROR
。
更现代的方法
\documentclass{article}
\usepackage{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\defineswitchmacro}{mm}
{% #1 = macro to define
% #2 = cases
\NewDocumentCommand{#1}{O{}}
{
\str_case:nnF { ##1 } { #2 } { \ERROR }
}
}
\ExplSyntaxOff
\defineswitchmacro{\mymacro}{
{}{nothing}
{a}{\textcolor{red}{Something}}
{b}{{\footnotesize Something}}
{c}{\textdagger}
}
\begin{document}
\mymacro\par
\mymacro[a]\par
\mymacro[b]\par
\mymacro[c]\par
\mymacro[uuu]
\end{document}