防止 xparser 剥离括号?

防止 xparser 剥离括号?

因此,我尝试实现一个应该支持以下语法的COOL-style宏:\Sum

\Sum{\ldots}  % -> \sum \ldots
\Sum[i]{\ldots}  % -> \sum_{i} \ldots
\Sum[i \in I]{\ldots}  % -> \sum_{i \in I} \ldots
\Sum[i, 0, N]{\ldots}  % -> \sum_{i=0}^{N} \ldots
\Sum[{i,j}, 0, N]{\ldots}  % -> \sum_{i,j=0}^{N} \ldots
\Sum[{i,j,k}]{\ldots}  % -> \sum_{i,j,k} \ldots

重要的是,我希望使用括号保护第一个参数中的逗号。实际的实现是在expl3用户界面中使用xparse。不幸的是,xparse如果括号包围了整个参数,则似乎总是会删除参数中的括号,因此无论我的内部代码做什么,这种保护都不会在所有情况下都起作用。查看文档,我找不到阻止这种情况的方法。

我尝试了表单的宏签名

\DeclareDocumentCommand \Sum { s >{ \SplitArgument{2}{,} } o m }
  { ... }
\DeclareDocumentCommand \Sum { s o m }
  { ... }

我是不是漏掉了什么?有没有一种(未记录的)方法可以让 xparse 不去掉这些括号,而只需绕过 xparse 并手动实现接口(也许使用参数处理器?)?如果没有,这是否需要在 latex github 上提交错误报告/功能请求?

答案1

您可以通过在左括号后插入另一个标记(如果有的话)来解决这个问题(如答案中的概念证明)。\Wisperwind_Sum_original_code:nnn用原始代码替换以排版总和(包括使用 处理可选星号\IfBooleanTF)。

\documentclass[]{article}

\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \l_Wisperwind_clist
\NewDocumentCommand \Sum { s t[ }
  {
    \IfBooleanTF { #2 }
      { \Sum_two { #1 } [ \use_none:n {} }
      { \Sum_two { #1 } }
  }
\NewDocumentCommand \Sum_two { m O{ \use_none:n {} } m }
  {
    \Wisperwind_Sum_original_code:non { #1 } { #2 } { #3 }
  }
\cs_new:Npn \Wisperwind_Sum_original_code:nnn #1 #2 #3
  {
    \sum
    \clist_set:Nn \l_Wisperwind_clist { #2 }
    \int_case:nn { \clist_count:N \l_Wisperwind_clist }
      {
        { 1 } { \sb { \clist_item:Nn \l_Wisperwind_clist { \c_one_int } } }
        { 2 }
          {
            \sb { \clist_item:Nn \l_Wisperwind_clist { \c_one_int } }
            \sp { \clist_item:Nn \l_Wisperwind_clist { 2 } }
          }
        { 3 }
          {
            \sb
              {
                \clist_item:Nn \l_Wisperwind_clist { \c_one_int }
                =
                \clist_item:Nn \l_Wisperwind_clist { 2 }
              }
            \sp { \clist_item:Nn \l_Wisperwind_clist { 3 } }
          }
      }
    #3
  }
\cs_generate_variant:Nn \Wisperwind_Sum_original_code:nnn { non }
\ExplSyntaxOff

\begin{document}
$\Sum{\ldots}$  % -> \sum \ldots
$\Sum[i]{\ldots}$  % -> \sum_{i} \ldots
$\Sum[i \in I]{\ldots}$  % -> \sum_{i \in I} \ldots
$\Sum[i, 0, N]{\ldots}$  % -> \sum_{i=0}^{N} \ldots
$\Sum[{i,j}, 0, N]{\ldots}$  % -> \sum_{i,j=0}^{N} \ldots
$\Sum[{i,j,k}]{\ldots}$  % -> \sum_{i,j,k} \ldots
\end{document}

enter image description here

答案2

这里使用 LaTeX2e(有关 Plain TeX 请参见下文):

\documentclass{article}
\usepackage{listofitems}
\makeatletter
\newcommand\Sum{\@ifnextchar[{\Sumaux[\@gobble}{\sum}}
\makeatother
\def\Sumaux[#1]#2{
  \sum
  \setsepchar{,}
  \readlist\sumargs{#1}
  \ifnum\listlen\sumargs[]>1\relax
    _{\sumargs[1]=\sumargs[2]}
    \ifnum\listlen\sumargs[]>2\relax^\sumargs[3]\fi
  \else
    _{\sumargs[1]}
  \fi
  #2
}
\begin{document}
\[\Sum{\ldots}  \]% -> \sum \ldots
\[\Sum[i]{\ldots}  \]% -> \sum_{i} \ldots
\[\Sum[i \in I]{\ldots}  \]% -> \sum_{i \in I} \ldots
\[\Sum[i, 0, N]{\ldots}  \]% -> \sum_{i=0}^{N} \ldots
\[\Sum[{i,j}, 0, N]{\ldots}  \]% -> \sum_{i,j=0}^{N} \ldots
\[\Sum[{i,j,k}]{\ldots}  \]% -> \sum_{i,j,k} \ldots
\end{document}

enter image description here

这种方法也可以在 Plain TeX 中实现:

\input listofitems
\def\gobble#1{}
\def\Sum{\futurelet\next\doSum}
\def\doSum{\ifx[\next%
  \expandafter\Sumaux\expandafter[\expandafter\gobble\else\sum\fi}
\def\Sumaux[#1]#2{
  \sum
  \setsepchar{,}
  \readlist\sumargs{#1}
  \ifnum\listlen\sumargs[]>1\relax
    _{\sumargs[1]=\sumargs[2]}
    \ifnum\listlen\sumargs[]>2\relax^\sumargs[3]\fi
  \else
    _{\sumargs[1]}
  \fi
  #2
}
$$\Sum{\dots}  $$% -> \sum \ldots
$$\Sum[i]{\ldots}  $$% -> \sum_{i} \ldots
$$\Sum[i \in I]{\ldots}  $$% -> \sum_{i \in I} \ldots
$$\Sum[i, 0, N]{\ldots}  $$% -> \sum_{i=0}^{N} \ldots
$$\Sum[{i,j}, 0, N]{\ldots}  $$% -> \sum_{i,j=0}^{N} \ldots
$$\Sum[{i,j,k}]{\ldots}  $$% -> \sum_{i,j,k} \ldots
\bye

答案3

括号的剥离是经过深思熟虑的,因为\newcommand生成的命令需要括号来表示情况

\foo[{]}]{bar}

xparse- 生成的则不然。没有括号剥离,

\foo[{bar}]

\foo[bar]

可以区别对待。

在您的例子中,您有一个带有一个条目的逗号列表。显而易见的解决方案是提供第二个空条目

\Sum[{i,j},]{\ldots}

因为这是一个无操作。

相关内容