xparse:如何使用复杂的参数规范包装文档命令?

xparse:如何使用复杂的参数规范包装文档命令?

假设我有一个具有复杂参数规范的函数,如下所示:

\DeclareDocumentCommand\backend{m moomm}{
    Type: #1, arguments: #2 #3 #4 #5 #6
}

我想声明一组包装器,为第一个参数插入一些内容,但保留其余参数不变(将它们传递给命令\backend),如下所示:

\DeclareDocumentCommand\typeA{moomm}{%
    \backend{A}{#1}[#2][#3]{#4}{#5}%
}

这似乎有效,但这真的是一种适用于所有类型参数的“安全”方法吗?或者这更好:

\def\typeB{\backend{B}} 

或者两者等同?什么是最佳实践?

这里有一个 MWE 可以玩一下:

\documentclass{article}
\usepackage{xparse}

\DeclareDocumentCommand\backend{m moomm}{
    Type: #1, arguments: #2 #3 #4 #5 #6
}

\DeclareDocumentCommand\typeA{moomm}{%
    \backend{A}{#1}[#2][#3]{#4}{#5}%
}

\def\typeB{\backend{B}}


\begin{document}

\typeA{Foo}[opt.]{m2}{m3}

\typeB{Bar}[opt.]{m2}{m3}

\end{document}

答案1

像这样吗?

\NewDocumentCommand除非\DeclareDocumentCommand您确定要覆盖任何现有命令,但通常情况并非如此。

基本思想是,xparse函数只是包装器,用于处理用户输入、调用适当的低级函数并适当地传递任何参数值。因此,在这种情况下,我们需要 3 个低级函数:分别用于 4、5 和 6 个参数。或者,如果您确实希望在未指定选项时使用默认值,则只需要一个低级函数,代码更简单。

假设更复杂的情况,每个xparse宏只需决定指定多少个参数并将相关值传递给适当的低级命令。

\cs_new_protected_nopar如果您确定要使用,则可以使用m而不是+mo而不是+o作为参数规范。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \latechneuse_backend:nnnnnn
{
  Type: ~ #1, ~ arguments: ~ #2 ~ #3 ~ #4 ~ #5 ~ #6
}
\cs_new_protected:Nn \latechneuse_backend:nnnnn
{
  Type: ~ #1, ~ arguments: ~ #2 ~ #3 ~ #4 ~ #5
}
\cs_new_protected:Nn \latechneuse_backend:nnnn
{
  Type: ~ #1, ~ arguments: ~ #2 ~ #3 ~ #4
}
\NewDocumentCommand \backend { mmoomm }
{
  \group_begin:
  \IfValueTF { #3 }
  {
    \IfValueTF { #4 }
    {
      \latechneuse_backend:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 }
    }{
      \latechneuse_backend:nnnnn { #1 } { #2 } { #3 } { #4 } { #5 }
    }
  }{
    \latechneuse_backend:nnnn { #1 } { #2 } { #3 } { #4 }
  }
  \group_end:
}
\NewDocumentCommand \altbackend { m m O {default} O {default} m m }
{
  \group_begin:
    \latechneuse_backend:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 }
  \group_end:
}
\NewDocumentCommand \typeA { m o o m m }
{
  \group_begin:
  \IfValueTF { #2 }
  {
    \IfValueTF { #3 }
    {
      \latechneuse_backend:nnnnnn { A } { #1 } { #2 } { #3 } { #4 } { #5 }
    }{
      \latechneuse_backend:nnnnn { A } { #1 } { #2 } { #4 } { #5 }
    }
  }{
    \latechneuse_backend:nnnn { A } { #1 } { #4 } { #5 }
  }
  \group_end:
}
\NewDocumentCommand \typeB { m o o m m }
{
  \group_begin:
  \IfValueTF { #2 }
  {
    \IfValueTF { #3 }
    {
      \latechneuse_backend:nnnnnn { B } { #1 } { #2 } { #3 } { #4 } { #5 }
    }{
      \latechneuse_backend:nnnnn { B } { #1 } { #2 } { #4 } { #5 }
    }
  }{
    \latechneuse_backend:nnnn { B } { #1 } { #4 } { #5 }
  }
  \group_end:
}
\NewDocumentCommand \alttypeA { m O {default} O {default} m m }
{
  \group_begin:
  \latechneuse_backend:nnnnnn { A } { #1 } { #2 } { #3 } { #4 } { #5 }
  \group_end:
}
\NewDocumentCommand \alttypeB { m O {default} O {default} m m }
{
  \group_begin:
  \latechneuse_backend:nnnnnn { B } { #1 } { #2 } { #3 } { #4 } { #5 }
  \group_end:
}
\ExplSyntaxOff


\begin{document}

\typeA{Foo}[opt.]{m2}{m3}

\typeB{Bar}[opt.]{m2}{m3}

\end{document}

很难想象这个界面真的是一个很好的设计选择,但如果没有更多有关实际用例的信息,就不可能说出如何以不同的方式实现它。(可能是键值接口,但正如我所说,仅凭这么少的信息就无法真正说出。)

相关内容