现希望定义一个具有多个可选参数的命令\cmd
\documentclass[12pt]{ctexart}
\usepackage[margin=1in]{geometry}
\setlength{\parindent}{0pt}
\NewDocumentCommand{\cmda}{O{default1} O{default2} m}{%
\textbf{The result of \texttt{\string\cmda}:} \par
optional param1: #1 \par
optional param2: #2 \par
mandattory param: #3 \par
}
\NewDocumentCommand{\cmdb}{O{default1} m O{default2}}{%
\textbf{The result of \texttt{\string\cmdb}:} \par
optional param1: #1 \par
mandattory param: #2 \par
optional param2: #3 \par
}
\begin{document}
\cmda{Explorer}
\cmda[anaconda][python]{Explorer}
\cmda[anaconda]{Explorer}
\cmda[][python]{Explorer} % 使用\cmda的定义方式,可否指定default2而让default1为默认值
\cmdb{Explorer}
\cmdb[anaconda]{Explorer}[python]
\cmdb[anaconda]{Explorer}
\cmdb{Explorer}[python]
\end{document}
如果采用\cmda
的定义顺序方式,使用\cmda[option1][option2]{mandatory3}
则无法使用\cmda[option2]{mandatory3}
指定#2
而让#1
为默认值
如果使用\cmdb
的方式,固然可实现\cmda{mandatory3}[option2]
,但是这种参数形式\cmd[]{}[]
并不优雅
如果不使用keyval
,kvoptions
或l3keys
等方式,是否可以将\cmda
优雅的实现只指定option#2
而让option#1
为默认值。
或者说,遇到连续的多个options用\xparse
处理确实存在上面的小障碍?
自己给一个基于kayval
的解答。
\documentclass[12pt]{ctexart}
\usepackage[margin=1in]{geometry}
\setlength{\parindent}{0pt}
\usepackage{keyval}
\makeatletter
\def\mwe@vala{defaulta}
\define@key{mwe}{opa}{\def\mwe@vala{#1}}
\def\mwe@valb{defaultb}
\define@key{mwe}{opb}{\def\mwe@valb{#1}}
\newcommand\foo[2][]{
\begingroup
\setkeys{mwe}{#1}%
The opa is: \mwe@vala. \par
The opb is: \mwe@valb. \par
The Parameter is: #2. \par
\endgroup
}
\makeatother
\begin{document}
\foo{Explorer}
\foo[opa=opa,opb=opb]{Explorer}
\foo[opb=opb]{Explorer}
\foo[opa=opa]{Explorer}
\end{document}
一般情况下,如果要实现类似的需求,是交换 1、2 个参数的顺序,或者用不同类型的定界符([]
()
<>
等)。
也可以用一个特殊的值表示默认值,遇到这个特殊值的时候把它替换为默认值。
\ExplSyntaxOn
\cs_new_protected:Npn \__my_make_default:nnn #1#2#3
{
\tl_if_eq:nnTF {#3} {#1}
{ \tl_set:Nn \ProcessedArgument {#2} }
{ \tl_set:Nn \ProcessedArgument {#3} }
}
\cs_new_eq:NN \TrueDefault \__my_make_default:nnn
\ExplSyntaxOff
\NewDocumentCommand{\cmdt}{
>{\TrueDefault{?}{default1}} O{?} % 如果参数为 ? 就替换为 default1
>{\TrueDefault{?}{default2}} O{?}
m
}{%
\textbf{The result of \texttt{\string\cmdt}:} \par
optional param1: #1 \par
optional param2: #2 \par
mandattory param: #3 \par
}
\cmdt{Explorer}
\cmdt[anaconda][python]{Explorer}
\cmdt[anaconda]{Explorer}
\cmdt[?][python]{Explorer}