Macro for integrals, a problem with limits
The problem is, that your \temp
in the tried fix is read as one token and not parsed correctly. Inserting a few \expandafter
s fixes this:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\usepackage{xstring}
\NewDocumentCommand{\Int}{ >{\SplitList{;}}o}{%
\IfValueT{#1}{\ProcessList{#1}{\IntLimitONE}}\,%
}
\NewDocumentCommand{\IntLimitONE}{m}{%
\IfSubStr{#1}{*}{\StrSubstitute{#1}{*}{}[\temp]\oint\expandafter\IntSplitLimits\expandafter{\temp}}{\int\IntSplitLimits{#1}}
}
\NewDocumentCommand{\IntSplitLimits}{ >{\SplitArgument{1}{,}}m}{%
\IfValueT{#1}{\IntLimits#1}%
}
\NewDocumentCommand{\IntLimits}{mm}{%
_{#1}^{\IfNoValueTF{#2}{}{#2\!\!}}%
}
\begin{document}
\begin{equation}
\Int[a,b;*c,d;e,f] f(x,y,z) dxdydz \quad , \quad \Int[*a,b] f(x) dx
\end{equation}
\end{document}
The outer part is good.
For deciding whether *
appears, I use \SplitArgument
for at most one occurrence of *
; this will produce two arguments, the second of which is -NoValue-
in case no asterisk appears.
The rest is just splitting at the comma.
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\NewDocumentCommand{\Int}{>{\SplitList{;}}O{}}{%
\ProcessList{#1}{\IntA}%
}
\NewDocumentCommand{\IntA}{>{\SplitArgument{1}{*}}{m}}{%
\IntB#1%
}
\NewDocumentCommand{\IntB}{mm}{%
\IfNoValueTF{#2}
{\IntC{\int}{#1}}% no *
{\IntC{\oint}{#2}}% *
}
\NewDocumentCommand{\IntC}{m >{\SplitArgument{1}{,}}m}{%
\IntD{#1}#2%
}
\NewDocumentCommand{\IntD}{mmm}{%
#1_{#2}^{#3}%
}
\begin{document}
\begin{equation}
\Int[a,b;*c,d;e,f] f(x,y,z) \,dx\,dy\,dz \quad , \quad \Int[*a,b] f(x)\,dx
\end{equation}
\end{document}
With expl3
functions, you can split the argument at ;
and map on the sequence so obtained. If the item starts with *
, discard it and choose \oint
, otherwise choose \int
.
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\Int}{O{}}
{
\simon_int:n { #1 }
}
\seq_new:N \l_simon_int_args_seq
\cs_new_protected:Nn \simon_int:n
{
\seq_set_split:Nnn \l_simon_int_args_seq { ; } { #1 }
\seq_map_inline:Nn \l_simon_int_args_seq
{
\str_if_eq_x:nnTF { \tl_head:n { ##1 } } { * }
{% * case
\simon_int_inner:Nf \oint { \tl_tail:n { ##1 } }
}
{% no * case
\simon_int_inner:Nn \int { ##1 }
}
}
}
\cs_new_protected:Nn \simon_int_inner:Nn
{
#1 \sb{ \clist_item:nn { #2 } { 1 } }
\sp{ \clist_item:nn { #2 } { 2 } }
}
\cs_generate_variant:Nn \simon_int_inner:Nn { Nf }
\ExplSyntaxOff
\begin{document}
\begin{equation}
\Int[a,b;*c,d;e,f] f(x,y,z) \,dx\,dy\,dz \quad , \quad \Int[*a,b] f(x)\,dx
\end{equation}
\end{document}
A variant that checks for the asterisk even if not leading the item:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\Int}{O{}}
{
\simon_int:n { #1 }
}
\seq_new:N \l__simon_int_args_seq
\tl_new:N \l__simon_int_ast_tl
\cs_new_protected:Nn \simon_int:n
{
\seq_set_split:Nnn \l__simon_int_args_seq { ; } { #1 }
\seq_map_inline:Nn \l__simon_int_args_seq
{
\tl_if_in:nnTF { ##1 } { * }
{% * case
\tl_set:Nn \l__simon_int_ast_tl { ##1 }
\tl_remove_once:Nn \l__simon_int_ast_tl { * }
\simon_int_inner:NV \oint \l__simon_int_ast_tl
}
{% no * case
\simon_int_inner:Nn \int { ##1 }
}
}
}
\cs_new_protected:Nn \simon_int_inner:Nn
{
#1 \sb{ \clist_item:nn { #2 } { 1 } }
\sp{ \clist_item:nn { #2 } { 2 } }
}
\cs_generate_variant:Nn \simon_int_inner:Nn { NV }
\ExplSyntaxOff
\begin{document}
\begin{equation}
\Int[a,b;*c,d;e*,f] f(x,y,z) \,dx\,dy\,dz \quad , \quad \Int[*a,b] f(x)\,dx
\end{equation}
\end{document}