4

This question has led to a new package: leftindex

It is a well-known problem that there seems to be no automatic way of getting nice spacing for left indices, particularly left superscripts. The most standard choice of command seems to be \prescript from mathtools, but superscripts suffer from the same problem as with other options:

enter image description here

\documentclass{article}

\usepackage{mathtools}

\begin{document}

\[
    \prescript{a}{b}{f},
    \qquad
    \prescript{a}{b}{\int}
\]

\end{document}

What I would like is a low-level, manual solution to this problem: A command

\manualprescript{<height>}{<superscript indentation>}{<subscript indentation>}
        {<superscript>}{<subscript>}{<symbol>}

where I can manually specify the height and the indentation of the indices. This could be either using TeX dimensions (e.g. .3em) or as tokens to be plugged into \vphantom and \hphantom. Either solution will be fine by me (or both, if you have the time). I could probably come up with some (very) bad solution to this myself using boxes and \phantom’s, which is why I am asking in here in order to obtain the right solution. (If possible, I would prefer a solution in LaTeX3 syntax since this is usually more readable and future-proof).

2
  • \documentclass{article} \usepackage{mathtools} \begin{document} \[ \prescript{\rlap{a}}{b}{\int} \] \end{document} ?
    – Zarko
    Aug 6, 2020 at 17:26
  • @Zarko, well, then if the upper index is too long, it will just run into the integral. And it does not allow me to manually control the spacing the way I want to.
    – Gaussler
    Aug 6, 2020 at 17:30

2 Answers 2

5

You can do it automatically.

\documentclass{article}
\usepackage{amsmath,mathtools,xparse}

\makeatletter
\NewDocumentCommand{\preint}{e{^_}}{\mathpalette\pre@int{{#1}{#2}}\!\int}
\newcommand{\pre@int}[2]{\pre@@int#1#2}
\newcommand{\pre@@int}[3]{%
  \sbox0{$#1\int\sb{xxxxxx}$}%
  \sbox2{$#1{\int}\sb{xxxxxx}$}%
  \setlength{\dimen4}{\dimexpr\wd2-\wd0\relax}%
  % compute the spacing
  \settowidth{\dimen0}{$\m@th#1^{\IfValueT{#2}{#2}}$}%
  \addtolength{\dimen0}{-\dimen4}%
  \settowidth{\dimen2}{$\m@th#1_{\IfValueT{#3}{#3}}$}%
  % start the business
  \mathop{}\!%
  \ifdim\dimen0>\dimen2 \kern\dimen0\else\kern\dimen2\fi
  % print the scripts
  {\mbox{$#1\vphantom{\int}$}}
  ^{\mathmakebox[0pt][l]{\mathmakebox[\dimen4][r]{\IfValueT{#2}{#2}\mspace{-1mu}}}}
  _{\mathmakebox[0pt][r]{\IfValueT{#3}{#3}}}
 }
\makeatother

\begin{document}

\[
x\preint_a^b f(x)\,dx + \preint_a^{b+c+d} f(x)\,dx
\]
\begin{center}
$x\preint_a^b$
\end{center}

\end{document}

enter image description here

12
  • Thanks for the solution! But how can one adjust it so that it does not just fit \int, but arbitrary symbols? I suspect that one will have to specify some dimensions (or degrees of slanting) manually, since the symbols f, M, and \Gamma have different slanting and therefore require different spacing. Can one turn this solution into a general, low-level command like I suggested in the original post?
    – Gaussler
    Aug 7, 2020 at 7:31
  • 1
    @Gaussler The integral is quite special. A general command? I’m afraid it’ very hard, if not impossible, because it depends on the shape of the symbol.
    – egreg
    Aug 7, 2020 at 8:21
  • 1
    But that’s why I wanted a very low-level command as specified in the original post, where I can specify all those dimensions manually. One could add another factor: The slanting factor of the symbol. For \Gamma, this slanting factor is 0, and for f, it’s probably about 0.2, i.e. you have to indent by about 0.2 times the height of the symbol. (This requires more thorough testing, but the important thing is to get a manual, low-level command that allows you to plug in all this information and get a result.)
    – Gaussler
    Aug 7, 2020 at 8:28
  • @Gaussler The ideas are there: the vertical dimensions can be emulated; add an argument for a horizontal displacement for both subscript and superscript, instead of computing it like I did for the integral. Then compensate the space in a similar way.
    – egreg
    Aug 7, 2020 at 8:34
  • 1
    @Gaussler OK, convincing.
    – egreg
    Nov 24, 2023 at 13:28
1

This solution is now available as a package: leftindex

I tried adjusting egreg’s answer to the general case. It is not built specifically for \int and therefore does not produce quite as perfect an output for that particular symbol. The benefit is that it provides relatively nice results in the general case. I provide the command

\leftindex^{<left superscript>}_{<left subscript>} {<symbol>}

This will indent the left superscript with the same value as the negative indentation of the right subscript. Sometimes, this yields wrong results. Therefore, the command takes two additional, optional arguments:

\leftindex[<slanting phantom>][<height phantom>]
    ^{<left superscript>}_{<left subscript>} {<symbol>}

This one will instead calculate the left superscript indentation using the <slanting phantom>. If provided, it will calculate the height based on the <height phantom>.

There is also another, underlying command

\manualleftindex
    {<height phantom>}
    {<slanting phantom>}
    {<subscript>}
    {<superscript>}

which is mainly intended for use in other commands (or packages).

\documentclass{article}

\usepackage{expl3,mathtools,kpfonts}

\ExplSyntaxOn

\DeclareDocumentCommand\manualleftindex { mmmm }
{
    % #1 = height phantom
    % #2 = slanting phantom
    % #3 = left superscript
    % #4 = left subscript
    \mathpalette \__leftindex_auxiliary_mathpalette_command:nn { {#1}{#2}{#3}{#4} }
}

\ExplSyntaxOff

\DeclareDocumentCommand\leftindex { o o E{^_}{{}{}} m }
{
    % #1 = slanting phantom
    % #2 = height phantom
    % #3 = left superscript
    % #4 = left subscript
    % #5 = symbol
    \IfValueTF {#1}
    {
        \IfValueTF{#2}
        {
            \manualleftindex { #2 } { #1 } { #3 } { #4 }
        }
        {
            \manualleftindex { #1 } { #1 } { #3 } { #4 }
        }
    }
    {
        \manualleftindex { #5 } { #5 } { #3 } { #4 }
    }
    #5
}

\DeclareDocumentCommand\LeftIndex { o o E{^_}{{}{}} }
{
    % #1 = slanting phantom
    % #2 = height phantom
    % #3 = left superscript
    % #4 = left subscript
    \IfValueTF {#1}
    {
        \IfValueTF{#2}
        {
            \manualleftindex { #2 } { #1 } { #3 } { #4 }
        }
        {
            \manualleftindex { #1 } { #1 } { #3 } { #4 }
        }
    }
    {
        \manualleftindex { } { } { #3 } { #4 }
    }
}

\ExplSyntaxOn

\cs_new_protected:Npn\leftindex_kern_horizontal:n#1
{
    \kern #1 \relax
}

\cs_new_protected:Npn\leftindex_set_mathsurround_to_zero:
{
     % This is equivalent to "\m@th"
    \dim_set:Nn \mathsurround { 0pt }
}

\cs_new_protected:Npn\__leftindex_auxiliary_mathpalette_command:nn#1#2
{
    \__leftindex_auxiliary:nnnnn { #1 } #2
}

\dim_new:N\l__leftindex_phantom_height_dim

\box_new:N \l__leftindex_slanting_phantom_with_subscript_box
\dim_new:N \l__leftindex_slanting_phantom_with_subscript_dim

\box_new:N \l__leftindex_slanting_phantom_with_subscript_without_indentation_box
\dim_new:N \l__leftindex_slanting_phantom_with_subscript_without_indentation_dim

\dim_new:N \l__leftindex_indentation_of_slanting_phantom_subscript

\box_new:N \l__leftindex_superscript_temp_box
\dim_new:N \l__leftindex_width_of_superscript_dim

\box_new:N \l__leftindex_subscript_temp_box
\dim_new:N \l__leftindex_width_of_subscript_dim

\cs_new_protected:Npn\__leftindex_auxiliary:nnnnn#1#2#3#4#5
{
    \group_begin:
        \hbox_set:Nn \l__leftindex_slanting_phantom_with_subscript_box
            { $ #1 #3 \sb{xxxxxx} $ }
        \dim_set:Nn \l__leftindex_slanting_phantom_with_subscript_dim
            { \box_wd:N \l__leftindex_slanting_phantom_with_subscript_box }
        \hbox_set:Nn \l__leftindex_slanting_phantom_with_subscript_without_indentation_box
            { $ #1 \hbox:n {$ #1 #3 $} \sb{xxxxxx} $ }
        \dim_set:Nn \l__leftindex_slanting_phantom_with_subscript_without_indentation_dim
            { \box_wd:N \l__leftindex_slanting_phantom_with_subscript_without_indentation_box }
        \dim_set:Nn \l__leftindex_indentation_of_slanting_phantom_subscript
        {
            \l__leftindex_slanting_phantom_with_subscript_without_indentation_dim
            -
            \l__leftindex_slanting_phantom_with_subscript_dim
        }
        \tl_if_blank:nTF { #4 }
        {
            \dim_zero:N \l__leftindex_width_of_superscript_dim
        }
        {
            \hbox_set:Nn \l__leftindex_superscript_temp_box
            {
                $
                \leftindex_set_mathsurround_to_zero:
                #1 \sp { #4 }
                $
            }
            \dim_set:Nn \l__leftindex_width_of_superscript_dim
            {
                \box_wd:N \l__leftindex_superscript_temp_box
                -
                \l__leftindex_indentation_of_slanting_phantom_subscript
            }
        }
        \tl_if_blank:nTF { #5 }
        {
            \dim_zero:N \l__leftindex_width_of_subscript_dim
        }
        {
            \hbox_set:Nn \l__leftindex_subscript_temp_box
            {
                $
                \leftindex_set_mathsurround_to_zero:
                #1 \sb { #5 }
                $
            }
            \dim_set:Nn \l__leftindex_width_of_subscript_dim
            {
                \box_wd:N \l__leftindex_subscript_temp_box
            }
        }
        \mathop{}
        \leftindex_kern_horizontal:n
        {
            \dim_max:nn
                { \l__leftindex_width_of_superscript_dim }
                { \l__leftindex_width_of_subscript_dim }
        }
        \mathopen{ \vphantom { #2 } }
        \tl_if_blank:nF { #4 }
        {
            \sp {
                \mathmakebox[0pt][l]{
                    \mathmakebox[ \l__leftindex_indentation_of_slanting_phantom_subscript ][r]{ #4 }
                }
            }
        }
        \tl_if_blank:nF { #5 }
        {
            \sb {
                \mathmakebox[0pt][r]{ #5 }
            }
        }
    \group_end:
}

\ExplSyntaxOff

\begin{document}

\[
    x \leftindex^{a+b}_{c+d} {\int} f(x)\, dx
\]


\[
    \leftindex^{1}_{0} {f}^u_v
    \neq
    \leftindex^{pq}_{0} {H}^u_v
\]

\[
    \leftindex^{a}_{b} {\Gamma}^c_d
    \neq
    \leftindex[]^{a}_{b} {\Gamma}^c_d
\]


\end{document}

enter image description here

6
  • @egreg Any comments? :-)
    – Gaussler
    Aug 23, 2020 at 11:59
  • The kerning is appropriate for the integral, definitely not for Gamma.
    – egreg
    Aug 23, 2020 at 14:17
  • @egreg I don’t quite follow. Is the second solution, \manualleftindex{\Gamma}{}{a}{b}, not appropriate for \Gamma? On the surface, it looks good to me.
    – Gaussler
    Aug 23, 2020 at 14:29
  • Yes, the right-hand side is good, which I can't say about the left-hand side.
    – egreg
    Aug 23, 2020 at 14:37
  • 1
    Remark: when using this package, it's best to only put a single symbol in the argument, otherwise there may be issues. e.g. tex.stackexchange.com/q/701911/250119
    – user202729
    Nov 21, 2023 at 16:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .