
With this code
\usepackage{etoolbox}
\newcommand*\diff[2][]{\mathop{\mathrm{d}\ifblank{#1}{}{^{#1}}{#2}}}
\let\originalint\int
\def\int_#1^#2{\originalint_{#1}^{#2}\mathopen{}}
you remove space after the \int but your code must be written always with \int_{..}^{..} with limits and in that specific order. You could write some trickery so that if the limits are blank they are not added to the code. Or you could do some trickery with \@ifnextchar so that one checks for both limits in any order and the result is more clean. If it's wanted, I can add that. Here's the code (thanks to @kyle_the_hacker):
\usepackage{etoolbox}
\makeatletter
\newcommand*\diff[2][]{\mathop{\mathrm{d}\ifblank{#1}{}{^{#1}}{#2}}}
\let\int@original\int
\def\int{\int@checkfirstsb}
\def\int@checkfirstsb{\@ifnextchar_{\int@checksecondsp}{\int@checkfirstsp}}
\def\int@checkfirstsp{\@ifnextchar^{\int@checksecondsb}{\int@{}{}}}
\def\int@checksecondsp_#1{\@ifnextchar^{\int@grabsp{#1}}{\int@{#1}{}}}
\def\int@checksecondsb^#1{\@ifnextchar_{\int@grabsb{#1}}{\int@{}{#1}}}
\def\int@grabsb#1_#2{\int@{#2}{#1}}
\def\int@grabsp#1^#2{\int@{#1}{#2}}
\def\int@#1#2{\int@original\ifblank{#1}{}{_{#1}}\ifblank{#2}{}{^{#2}}\mathopen{}}
\makeatother
In any case, here's an oportunity to add a bit of code I wrote some time ago to add new kind of arguments to xparse.
\documentclass{scrartcl}
\usepackage[intlimits]{amsmath}
\usepackage{etoolbox,xparse}
\ExplSyntaxOn
\cs_new_protected:Npn \__xparse_count_type_k:w #1
{
\__xparse_single_token_check:n { #1 }
\quark_if_recursion_tail_stop_do:Nn #1 { \__xparse_bad_arg_spec:wn }
\__xparse_count_mandatory:N
}
\cs_new_protected:Npn \__xparse_count_type_K:w #1 #2
{
\__xparse_single_token_check:n { #1 }
\quark_if_recursion_tail_stop_do:nn { #2 } { \__xparse_bad_arg_spec:wn }
\__xparse_count_mandatory:N
}
\cs_new_protected:Npn \__xparse_add_type_k:w #1
{ \exp_args:NNo \__xparse_add_type_K:w #1 { \c__xparse_no_value_tl } }
\cs_new_protected:Npn \__xparse_add_type_K:w #1 #2
{
\__xparse_flush_m_args:
\__xparse_add_grabber_optional:N K
\tl_put_right:Nn \l__xparse_signature_tl { #1 { #2 } }
\__xparse_prepare_signature:N
}
\cs_new_protected:Npn \__xparse_add_expandable_type_k:w #1
{
\exp_args:NNo \__xparse_add_expandable_type_K:w #1 { \c__xparse_no_value_tl }
}
\cs_new_protected_nopar:Npn \__xparse_add_expandable_type_K:w #1 #2
{
\__msg_kernel_error:nnx { xparse } { invalid-expandable-argument-type } { K }
\__xparse_add_expandable_type_m:w % May be create this?
}
\cs_new_protected:Npn \__xparse_grab_K:w #1 #2 #3 \l__xparse_args_tl
{
\__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected_nopar:Npn
{ _ignore_spaces }
}
\cs_new_protected:Npn \__xparse_grab_K_long:w #1 #2 #3 \l__xparse_args_tl
{
\__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected:Npn
{ _ignore_spaces }
}
\cs_new_protected:Npn \__xparse_grab_K_trailing:w #1 #2 #3 \l__xparse_args_tl
{
\__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected_nopar:Npn
{ _ignore_spaces }
}
\cs_new_protected:Npn \__xparse_grab_K_long_trailing:w #1 #2 #3 \l__xparse_args_tl
{
\__xparse_grab_K_aux:NnnNn #1 { #2 } { #3 } \cs_set_protected:Npn
{ _ignore_spaces }
}
\cs_new_protected:Npn \__xparse_grab_K_aux:NnnNn #1 #2 #3 #4 #5
{
\exp_after:wN #4 \l__xparse_fn_tl ##1
{
\__xparse_add_arg:n { ##1 }
#3 \l__xparse_args_tl
}
\use:c { peek_meaning_remove #5 :NTF } #1
{ \l__xparse_fn_tl }
{
\__xparse_add_arg:n { #2 }
#3 \l__xparse_args_tl
}
}
\prop_put:Nnn \c__xparse_shorthands_prop { a } { k \sb }
\prop_put:Nnn \c__xparse_shorthands_prop { b } { k \sp }
\prop_put:Nnn \c__xparse_shorthands_prop { A } { K \sb }
\prop_put:Nnn \c__xparse_shorthands_prop { B } { K \sp }
\NewDocumentCommand \diff { o m }
{\mathop{\mathrm{d}\IfValueT{#1}{^{#1}}{#2}}}
\ExplSyntaxOff
\let\originalint\int
\RenewDocumentCommand \int { a b }
{\originalint\IfValueT{#1}{_{#1}}\IfValueT{#2}{^{#2}}\mathopen{}}
\begin{document}
\begin{equation}
\int_0^\infty \diff[3]{\boldsymbol r} f(\boldsymbol r)
\end{equation}
\end{document}
And it may be even better to check if \diff follows and in case it doesn't just have the original behaviour, just change the definition to this (it's a pity that spaces aren't skipped, so we need to explicitly check for a space and then check for \diff after that)
\makeatletter
\RenewDocumentCommand \int { a b t\@sptoken t\diff }
{\originalint\IfValueT{#1}{_{#1}}\IfValueT{#2}{^{#2}}%
\IfBooleanT{#4}{\mathopen{}\diff}}
\makeatother
After a few thoughts
Completed rethink code that I would use for a complete flexibility. This adds all possible combinations of sub-superscripts for the \int plus the natural input for differentials \dd x, \dd{\bm x}, \dd^2 x, \dd^{a_1}{x_1}.
\usepackage{mathtools,bm}
\usepackage{etoolbox}
\makeatletter
\def\dd{\@ifnextchar^{\dd@grabsp}{\dd@{}}}
\def\dd@grabsp^#1#2{\dd@{#1}{#2}}
\def\dd@#1#2{\mathop{d\ifblank{#1}{}{^{#1}}{#2}}}
\let\int@original\int
\def\int{\int@checkfirstsb}
\def\int@checkfirstsb{\@ifnextchar_{\int@checksecondsp}{\int@checkfirstsp}}
\def\int@checkfirstsp{\@ifnextchar^{\int@checksecondsb}{\int@{}{}}}
\def\int@checksecondsp_#1{\@ifnextchar^{\int@grabsp{#1}}{\int@{#1}{}}}
\def\int@checksecondsb^#1{\@ifnextchar_{\int@grabsb{#1}}{\int@{}{#1}}}
\def\int@grabsb#1_#2{\int@{#2}{#1}}
\def\int@grabsp#1^#2{\int@{#1}{#2}}
\def\int@#1#2{\int@original\ifblank{#1}{}{_{#1}}\ifblank{#2}{}{^{#2}}\mathopen{}}
\makeatother
that with the xparse code from before it would become
\NewDocumentCommand\dd{bm}{\mathop{d\IfValueT{#1}{^{#1}}{#2}}}
\let\originalint\int
\RenewDocumentCommand\int{ab}{\originalint\IfValueT{#1}{_{#1}}\IfValueT{#2}{^{#2}}\mathopen{}}
\diffbecause that command is used everywhere, and sometimes the integral sign is followed by a fraction containing the\diff... – rubenvb Mar 18 '15 at 15:10\Integralor something like this? – Mar 18 '15 at 15:24\int. – rubenvb Mar 18 '15 at 15:26\limitscommand which must be done first and then then negative spacing added – Mar 18 '15 at 15:28\def\int_#1^#2{\oldint_{#1}^{#2} \mspace{-4mu}}. In case you don't always have limits, it's a bit more trickier. In any case, let's see if someone comes with an “official” solution. – Manuel Mar 18 '15 at 15:29limitsis cumbersome – Mar 18 '15 at 15:31\limits, but the integration limits in general – Mar 18 '15 at 15:44\intto still add\limitsas well (I used theintlimitsoption toamsmathin my example, which does just that. – rubenvb Mar 18 '15 at 15:45\int_{..}^{..}then it's easy with the definition I did before. If not, with\@ifnextcharand a few auxiliar macros, or withxparse. – Manuel Mar 18 '15 at 16:10