如何使用 expl3/xparse 传递扩展的可选参数?

如何使用 expl3/xparse 传递扩展的可选参数?

我有一个使用语法定义的命令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 用文本参数扩展括号(例如\figPossis then [t]),然后使用etextools' \expandaftercmds延迟处理\begin{figure}直到选项到位。

相关内容