我很难创建一个可以接受多个选项的宏。我想创建的是\mycommand[up,middle]{Macro}
输出Macro with 'up' and 'middle' specified
。使用etoolbox
下面的 MWE,我可以输出单个选项,以及在没有给出任何选项或给出无效选项时输出。但我不知道如何输出多个选项。
我不需要使用etoolbox
,但我很喜欢这个语法。David Carlisle 建议使用类似的语法\newcommand\foo[2][]{\@for\tmp:=#1\do{.... something with \tmp and #2...}}
,但我不知道如何将其应用于我的示例。
\documentclass{article}
\usepackage{etoolbox}
\newrobustcmd{\mycommand}[2][]{%
\ifstrequal{#1}{up}{% option up
#2 with `up' specified
}{% option middle
\ifstrequal{#1}{middle}{%
#2 with `middle' specified
}{% nothing specified
\ifstrempty{#1}{%
#2 with nothing specified
}{% something specified
#2 is invalid
}{\relax}%
}{\relax}%
}%
}%
\begin{document}
\mycommand[up]{Macro}
\mycommand[middle]{Macro}
\mycommand[]{Macro}
\mycommand[bla]{Macro}
\end{document}
答案1
使用的建议\@for
可能会产生类似的效果
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newrobustcmd{\mycommand}[2][]{% first the options that are equal for all
\@for\tmp:=#1\do{%
\expandafter\ifstrequal\expandafter{\tmp}{up}
{'up' seen}%
{%
\expandafter\ifstrequal\expandafter{\tmp}{middle}
{'middle' seen}
{%
\expandafter\ifstrempty\expandafter{\tmp}
{}
{INVALID}%
}%
}%
}%
}%
\makeatother
\begin{document}
\mycommand[up]{Macro}
\mycommand[middle]{Macro}
\mycommand[]{Macro}
\mycommand[bla]{Macro}
\end{document}
由于我不知道您想要什么“有效载荷”,我只是排版了所看到的信息:在实际情况下,这可能会用于设置开关或宏以便在参数\do
完成后使用。
答案2
您可以尝试其中一个 keyval 包,例如xkeyval
\documentclass{article}
\usepackage{xkeyval}
\makeatletter
\define@choicekey+{myKeys}{foo}[\val\nr]{up,middle}{%
\ifcase\nr\relax
\def\keyval{up} \or
\def\keyval{middle}
\fi}{\def\keyval{\{not defined\}}}
\makeatother
\newcommand\mycommand[2][]{%
\ifx\relax#1\relax\def\keyval{\{empty\}}
\else\setkeys{myKeys}{#1}\fi
we do something which depends to \keyval
}%
\begin{document}
\mycommand[foo=up]{Macro}
\mycommand[foo=middle]{Macro}
\mycommand[]{Macro}
\mycommand[foo=bla]{Macro}
\end{document}
答案3
这是另一个解决方案:
\documentclass{article}
\usepackage{keyreader}
\usepackage{xcolor}
\makeatletter
\krddefinekeys[JKV]{jorg}[jorg@]{%
choice/key1/a+x/{
a+x.do=\def\currcolor{blue},
a+y.do=\def\currcolor{green},
b+x.do=\def\currcolor{red},
b+y.do=\def\currcolor{magenta}
}
/\def\val{Value of key1: #1}
;
choice/align/justified/{
center.do=\def\curralign{center},
right.do=\def\curralign{flushright},
left.do=\def\curralign{flushleft},
justified.do=\def\curralign{@justified},
}
;
}
\krdpresetkeys[JKV]{jorg}{key1=a+x,align=justified}
\def\@justified{}
\def\end@justified{}
% Tests:
\newcommand\jorgcommand[2][]{%
\krdsetkeys[JKV]{jorg}{#1}%
\endgraf\bigskip\noindent\textbf{\val}\endgraf
\begin{\curralign}%
\removelastskip
\textcolor{\currcolor}{#2}%
\end{\curralign}%
}
\makeatother
\begin{document}
\def\atext{%
\texttt{choice} keys of pre-version~0.5 of \texttt{keyreader} package will always check
their values against the state pattern and raise an error if
there is no match. So you don't have to specify a fallback error message.
}
\jorgcommand[key1=a+x,align=justified]{\atext}
\jorgcommand[key1=a+y,align=center]{\atext}
\jorgcommand[key1=b+x,align=right]{\atext}
\jorgcommand[key1=b+y,align=left]{\atext}
\jorgcommand{\atext}
% Invalid value for key1 ('x+y' not allowed):
% \jorgcommand[key1=x+y]{\atext}
\end{document}
注意回答 OP 关于预设键的问题
在我上面的例子中,你会发现调用\jorgcommand{\atext}
。这没有调用可选参数,因此参数#1
为空\jorgcommand
。因此,在这种情况下\jorgcommand
使用即时键的值
\krdpresetkeys[JKV]{jorg}{key1=a+x,align=justified}
如果我们使用
\newcommand\jorgcommand[2][]{%
\if\relax\detokenize{#1}\relax\else
\krdsetkeys[JKV]{jorg}{#1}%
\fi
...#2...
}
正如 Herbert 所建议的,不会调用预设的键值。因此,我们可能会无意中应用键的最新值,这不是预期或正确的步骤。仅在\setkeys
或\krdsetkeys
实例化时才会设置预设键。