继先前的问题我改用了xparse
。现在我陷入了兼容性陷阱,并试图同时允许新旧内容。起源是臭名昭著的宏,带有两个可选参数。我的最小示例是:
\documentclass{minimal}
\usepackage{xparse}
\NewDocumentCommand \sidenotetext { o o m } {%
(#1), (#2), #3
}%
\begin{document}
\sidenotetext{arg} % case (1)
\sidenotetext[1]{arg} % \sidenotetext[mark=1]{arg}; case 2
\sidenotetext[][]{arg} % case 3
\sidenotetext[][2]{arg} %\sidenotetext[offset=2]{arg}; case 4
\sidenotetext[3][]{arg} %\sidenotetext[mark=3]{arg}; case 5
\sidenotetext[4][5]{arg} %\sidenotetext[mark=4,offset=5]{arg}; case 6
\end{document}
是否可以同时使左侧和右侧宏(注释掉)工作?如果不行,是否可以使情况 2 工作,即没有键始终表示标记,其余为键值?我认为,l3keys 是与 xparse 配合良好的正确选择?
答案1
如果两个可选参数处理的参数类型不兼容,则唯一可行的方法是将一个参数放在强制参数之前,将一个参数放在强制参数之后,因此
\NewDocumentCommand{\sidenotetext} { o m o }
{%
\IfNoValueTF{#1}...
}
或者
\NewDocumentCommand{\sidenotetext} { O{default} m O{default} }
{%
...
}
通过这种方式你可以调用
\sidenotetext{text}
\sidenotetext[1]{text}
\sidenotetext{text}[2]
\sidenotetext[1]{text}[2]
但是这种方法不太好用。最好采用键值方法。
\ExplSyntaxOn
\NewDocumentCommand{\sidenotetext}{ O{} m }
{
\group_begin:
\andy_sidenotetext:nn { #1 } { #2 }
\group_end:
}
\keys_define:nn { andy/sidenote }
{
mark .tl_set:N = \l_andy_sidenote_mark_tl,
offset .tl_set:N = \l_andy_sidenote_offset_tl,
offset .initial:n = 0,
}
\cs_new_protected:Npn \andy_sidenotetext:nn #1 #2
{
\keys_set:nn { andy/sidenote } { #1 }
<code using \l_andy_sidenote_mark_tl, \l_andy_sidenote_offset_tl
and #2 (the actual text)>
}
\ExplSyntaxOff
我不建议让这两个调用相互兼容:坚持使用一种语法。有一些宏允许这两种方法,但这是因为它们是在键值方法不可行时定义的。一个例子是\section
在 Koma-Script 类中,其中对键值语法的测试是基于是否=
出现在可选参数中,这不是很可靠。
如果您想要重新定义旧命令,我建议使用不同的名称。