Measure spacing of \int

I would like to be able to measure the space taken up by an \int and have that length stored in a \newlength{}. It is not as easy as

\settowidth{\@IntWidth}{\widthof{$\int$}}


In the MWE below, I attempt to apply a negative \kern of the measured spacing and redraw the symbol in red. If the measuring was done correctly, the red symbol should be exactly on top of the black symbol, but I get:

Notes:

• This ONLY address the case where there is both an upper and lower limit given, so the code that deals with the other options is commented out.

Code:

\documentclass{article}
\usepackage{amsmath}
\usepackage{calc}
\usepackage{xcolor}
\usepackage{xparse}

\newcommand{\dx}{\mathrm{d}x}%

\makeatletter
\let\OldIntOp\int
\newlength{\@IntWidth}

%% https://tex.stackexchange.com/a/345383/4301
\RenewDocumentCommand\int{e{_^}}{% underscore ALWAYS before ^
%\IfNoValueTF{#2}{% No upper limit
%  \IfNoValueTF{#1}{% No lower and upper limit
%    \OldIntOp
%  }{% Only lower limit
%    \OldIntOp_{#1}
%  }
%}{
%  \IfNoValueTF{#1}{% No lower, but do have upper limit
%    \OldIntOp^{#2}
%  }{% Both lower and upper limit
\OldIntOp
\settowidth{\@IntWidth}{\widthof{$\OldIntOp$}}% ????? How compute this ??????
\kern-\@IntWidth
{\color{red} \OldIntOp_{#1}^{#2}}
% }
%}%
}\makeatother

\begin{document}
\noindent
In inline math $\OldIntOp_a^b y\dx$, and in display math it is:
\begin{flalign*}
&\displaystyle\OldIntOp^b_a  y\dx
\textstyle\OldIntOp_a^b  y\dx
\scriptstyle\OldIntOp_a^b  y\dx
\scriptscriptstyle\OldIntOp_a^b  y\dx
&
\end{flalign*}
In inline math $\int_a^b y\dx$, and in display math it is:
\begin{flalign*}
&\displaystyle\int^b_a  y\dx
\textstyle\int_a^b  y\dx
\scriptstyle\int_a^b  y\dx
\scriptscriptstyle\int_a^b  y\dx
&
\end{flalign*}
\end{document}

• Is the problem to typeset only the integral sign red? I'm not sure I understand your aim – egreg May 31 '18 at 8:12
• @egreg: Am trying to detach the placement of the limits of integration from the placement of the actual integral symbol. – Peter Grill May 31 '18 at 8:19

Not sure about what you want to get. Anyway, the width can be computed with \mathpalette (there's also a \! to add and most likely some \mathop trickery).

\documentclass{article}
\usepackage{amsmath}
\usepackage{calc}
\usepackage{xcolor}
\usepackage{xparse}

\newcommand{\dx}{\mathrm{d}x}%

\makeatletter
\let\OldIntOp\int

\newcommand\kernint{\mathpalette\@kernint\relax}
\newcommand\@kernint[2]{%
\!\sbox0{$\m@th#1\OldIntOp$}\kern-\wd0
}

%% https://tex.stackexchange.com/a/345383/4301
\RenewDocumentCommand\int{e{_^}}{% underscore ALWAYS before ^
%\IfNoValueTF{#2}{% No upper limit
%  \IfNoValueTF{#1}{% No lower and upper limit
%    \OldIntOp
%  }{% Only lower limit
%    \OldIntOp_{#1}
%  }
%}{
%  \IfNoValueTF{#1}{% No lower, but do have upper limit
%    \OldIntOp^{#2}
%  }{% Both lower and upper limit
\OldIntOp\kernint
{\color{red} \OldIntOp_{#1}^{#2}}
% }
%}%
}
\makeatother

\begin{document}
\noindent
In inline math $\OldIntOp_a^b y\dx$, and in display math it is:
\begin{flalign*}
&\displaystyle\OldIntOp^b_a  y\dx
\textstyle\OldIntOp_a^b  y\dx
\scriptstyle\OldIntOp_a^b  y\dx
\scriptscriptstyle\OldIntOp_a^b  y\dx
&
\end{flalign*}
In inline math $\int_a^b y\dx$, and in display math it is:
\begin{flalign*}
&\displaystyle\int^b_a  y\dx
\textstyle\int_a^b  y\dx
\scriptstyle\int_a^b  y\dx
\scriptscriptstyle\int_a^b  y\dx
&
\end{flalign*}
\end{document}

\makeatother

\begin{document}
\noindent
In inline math $\OldIntOp_a^b y\dx$, and in display math it is:
\begin{flalign*}
&\displaystyle\OldIntOp^b_a  y\dx
\textstyle\OldIntOp_a^b  y\dx
\scriptstyle\OldIntOp_a^b  y\dx
\scriptscriptstyle\OldIntOp_a^b  y\dx
&
\end{flalign*}
In inline math $\int_a^b y\dx$, and in display math it is:
\begin{flalign*}
&\displaystyle\int^b_a  y\dx
\textstyle\int_a^b  y\dx
\scriptstyle\int_a^b  y\dx
\scriptscriptstyle\int_a^b  y\dx
&
\end{flalign*}
\end{document}


If you are interested in the actual measurements of the math box, the following example measures the math formula and writes its dimensions to the .aux file. This works around a limitation of \mathpalette/\mathchoice that set the formula in all math styles, but TeX decides much later, which version it will use (thanks to \over and friends).

\documentclass{article}
\usepackage{color}
\newcommand*{\diff}{\mathop{}\!\mathrm{d}}

\makeatletter

% Create new label type for the .aux file that takes
% the measurements of the math box.
% LaTeX takes care of re-run warnings Because of the usage of \@newl@bel.
\usepackage{auxhook}
\string\providecommand\string\New@MeasureMathBox[2]{}%
}
\newcommand*{\New@MeasureMathBox}{%
\@newl@bel{mmb}%
}

% Counter for identifying a math box
\newcounter{MeasureMathBox}
\renewcommand*{\theMeasureMathBox}{\the\value{MeasureMathBox}}

% Register that contain the measurement result
\newdimen\LastMathBoxWidth
\newdimen\LastMathBoxHeight
\newdimen\LastMathBoxDepth

% Measure the math box and write the label
% with the measurements to the .aux file
% in all styles via \mathpalette.
% When TeX later decides, which box it uses,
% only one write command of the correct
% math style remains.
\newcommand*{\MeasureMathBox}{%
% #1: math formula to be measured
% New identifier for the math box.
\stepcounter{MeasureMathBox}%
% Read the label if available.
\@ifundefined{mmb@\theMeasureMathBox}{%
\LastMathBoxWidth\z@
\LastMathBoxHeight\z@
\LastMathBoxDepth\z@
}{%
\expandafter\expandafter\expandafter
\Extract@MeasureMathBox
\csname mmb@\theMeasureMathBox\endcsname\@nil
}%
\mathpalette\@MeasureMathBox
}
\def\Extract@MeasureMathBox#1,#2,#3\@nil{%
\LastMathBoxWidth#1\relax
\LastMathBoxHeight#2\relax
\LastMathBoxDepth#3\relax
}
\newcommand*{\@MeasureMathBox}[2]{%
% #1: math style
% #2: math formula to be measured
% Do the actual measurement.
\setbox0=\hbox{$#1#2\m@th$}%
% Write the label to the .aux file.
\protected@write\@auxout{}{%
\string\New@MeasureMathBox
{\theMeasureMathBox}%
{\the\wd0,\the\ht0,\the\dp0}%
}%
}
\makeatother

\begin{document}

\def\Test{
\int
\MeasureMathBox{\int}
\kern-\LastMathBoxWidth
\! % negate horizontal spacing between two operators
\begingroup\color{red} \int_a^b \endgroup y\diff x
}
$\Test$
$\textstyle \Test$
$\scriptstyle \Test$
$\scriptscriptstyle \Test$
\end{document}


After the first compile run, the .aux file contains:

\relax
\providecommand\New@MeasureMathBox[2]{}
\New@MeasureMathBox{1}{10.00002pt,13.61122pt,8.61124pt}
\New@MeasureMathBox{2}{6.66667pt,8.0556pt,3.05562pt}
\New@MeasureMathBox{3}{6.66667pt,7.3056pt,3.80562pt}
\New@MeasureMathBox{4}{6.66667pt,6.8056pt,4.30562pt}


This is used in the second compile run:

If you are only interested in inserting the negative space of a math formula, the following works in one compile run (similar to egreg's answer, but more general):

\documentclass{article}
\usepackage{color}
\newcommand*{\diff}{\mathop{}\!\mathrm{d}}

\makeatletter
\newcommand*{\NegMathWidth}{%
% #1: math formula to be measured
\mathpalette{\@NegMathWidth}%
}
\newcommand*{\@NegMathWidth}[2]{%
% #1: math style
% #2: math formula to be measured
\settowidth\dimen@{$#1#2\m@th$}%
\kern-\dimen@
}
\makeatother

\begin{document}
\def\Test{
\int
\NegMathWidth{\int}
\! % negate horizontal spacing between two operators
\begingroup\color{red} \int_a^b \endgroup y\diff x
}
$\Test$
$\textstyle \Test$
$\scriptstyle \Test$
$\scriptscriptstyle \Test$
\end{document}


The result is the same as above.