我有一个使用语法定义的命令xparse
:
\DeclareDocumentCommand \foo { O{} m } {}
在其他命令(例如\bar
)中,我想调用此命令。调用命令 ( \bar
) 必须构造要提供给 的参数\foo
。因此调用类似于:
\foo [\tl_use:N \l_my_temporary_tl] {}
我想确保在\foo
调用时,它是实际的令牌列表而不是传递的命令。
如果\foo
采用两个强制参数,那么我似乎可以这样做
\exp_args:No \foo {\tl_use:N \l_my_temporary_tl} {}
(我意识到这里的扩展次数可能不正确,但这不是重点。)
可选参数是否有类似的语法?
如果不是,下面会是什么样子:
\cs_new:Npn \exp_opt_args:No #1[#2] { \exp_after:wN #1 \exp_after:wN [#2] }
和类似的...
答案1
简短的回答是没有机制可以做到这一点,因为我们试图促进将用户界面(通过 xparse,以及选择可选、强制、分隔参数等)与编码部分分离。
在我能想到的大多数情况下,你可以将代码转换为
\DeclareDocumentCommand {\foo} { o m }
{
\IfValueTF {#1}
{ \mypkg_foo:nn {#1} {#2} }
{ \mypkg_foo:n {#2} }
}
然后您的调用将是\exp_args:NV \mypkg_foo:nn \l_my_temporary_tl {}
,使用内部版本并跳过解析。请注意,我使用V
参数类型来避免担心使用哪种变量:它将\the
在必要时插入。也可以使用o
,因为标记列表只需一步即可展开。\tl_use:N
是一个相当奇怪的野兽,到目前为止我从未见过它的用途。
也许你的情况无法实现。那么你可以使用
\use:x { \foo [ { \exp_not:V \l_my_temporary_tl } ] { } }
\foo
由于 xparse 的命令是受保护的(除非明确指定不受保护),因此不会扩展where ,并\exp_not:V
确保标记列表不会扩展得太远。或者,
\exp_args:NNV \foo [ \l_my_temporary_tl ] { }
这有点儿像一个临时解决方案。请注意,在这两种情况下,我都将括号放在括号内的可选参数上:如果\l_my_temporary_tl
括号不匹配,则将抓取错误的可选参数。
答案2
广义上讲,创建文档命令(即用户语法)应始终作为仅采用强制参数的内部函数的包装器来完成。因此,如果我们有两个函数\foo
和\bar
,在文档级别具有某种关系,那么在内部,它们应该使用代码级函数链接起来
\DeclareDocumentCommand \foo { O{} m }
{
\IfNoValueTF {#1}
{ \foo_int:n {#2} }
{ \foo_int:nn {#1} {#2} }
}
\DeclareDocumentCommand \bar { O{} m }
{
\tl_set:Nx \l_my_temporary_tl
{ \IfNoValueF {#1} { \exp_not:n {#1} : \exp_not:n {#2} }
\foo_int:Vn \l_my_temporary_tl {#2}
}
在这里,我\l_my_temporary_tl
以任意方式进行设置,只是为了演示一些内容。
(更一般地说,我希望\bar
在内部调用一个单独的函数,然后处理输入。)
答案3
由于某种原因(大量错误),其他答案都不适合我missing $ inserted
。我通过以下方法解决了这个问题:
\DeclareDocumentCommand{\fig}{O{t} +m}{
\edef\figPoss{[#1]}
\expandaftercmds{\begin{figure}}{\figPoss}
#2
\end{figure}
}
关键在于需要 edef 用文本参数扩展括号(例如\figPoss
is then [t]
),然后使用etextools
' \expandaftercmds
延迟处理\begin{figure}
直到选项到位。