Prevent xparse from stripping braces?

You can trick this by inserting another token after the opening bracket if there is one (proof of concept like answer). Replace \Wisperwind_Sum_original_code:nnn with your original code to typeset the sum (including the handling of the optional star with \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


Here using LaTeX2e (see below for 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

This approach can also be implemented in 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

The brace stripping is quite deliberate as \newcommand-generated commands requires braces for the case

\foo[{]}]{bar}

whereas xparse-generated ones do not. Without brace stripping,

\foo[{bar}]

and

\foo[bar]

could be treated differently.

In your case, you have a comma list with one entry. The obvious solution is to provide a second, empty, entry

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

as this is a no-op.

Tags:

Xparse