# Kerning for subscripts of \sigma?

Is there any way to reduce the distance inside σ₀ and between \sigma and its subscript in general in the following setup automatically? That is, each time you type in \sigma_0 (or \sigma_1 etc.), you wish the actual output to be more consistent with \sigma_{\!0} (or \sigma_{\!1} etc.).

Input:

\documentclass{book}
\usepackage{fontspec}
\usepackage[american,british,french,norsk,german,ngerman]{babel}
\usepackage{mathtools}
\mathtoolsset{mathic=true} %%% See http://tex.stackexchange.com/a/3496/
\usepackage{amssymb}
\usepackage{unicode-math}
\setmainfont[Ligatures=TeX]{TeX Gyre Termes}
\setsansfont{TeX Gyre Heros}[Scale=0.88]
\setmonofont{TeX Gyre Cursor}
\setmathfont[Ligatures=TeX]{TeX Gyre Termes Math}
\setmathfont[Ligatures=TeX,range={\setminus}]{Asana Math}
\setmathfont[Ligatures=TeX,Extension=.otf,range={"2A3E},BoldFont=XITSMath-Bold]{XITSMath-Regular}%%% The fat semicolon
\usepackage[babel=true,verbose=errors]{microtype}
\begin{document}
$\sigma_0 \sigma_0$
$\sigma_{\!0} \sigma_{\!0}$
\end{document}


Output so far:

As you see, in the upper line the left zero seems to be more close to the right σ (which doesn't make any sense) than to the left one (which would make sense). The kerning in the lower line makes more sense.

I guess, this would be easier than Subscript kerning for specific letters in XeLaTeX, since we already have \sigma as a macro and can redefine it.

For which letters in the subscript position the kerning should be improved (and how) is intentionally left unspecified; improving the kerning in \sigma_<any single arabic digit or any single Latin small letter> or \sigma_{<any nonempty sequence of arabic digits and Latin small letters>} would suffice as a start. Of course, for σ_{\mathrm{T}} we might need less kerning (e.g., only -1mu rather than -3mu), and that's why capital Latin letters would need more work (and are not asked for in the first step). As of now, I intend to use the following subscripts: all the digits, i, j, k, k (yes, this one upright), n, i + 1, i - 1.

• Do you want to change the behaviour for \sigma_<any single number>, or for \sigma_<any single character>, or \sigma_<anything>, or somthing else? – Phelype Oleinik Apr 11 '19 at 20:37

I defined a command \AddtoKernList{<token list>}{<mu kern>} which will add the first token of the <token list> to a lookup table (the assignment is local). Later on, the \sigma command is redefined to to check for a subscript; if the subscript is found, then it looks the first token in the subscript in the lookup list. If that token is found, \mkern<mu kern> is applied right before the subscript.

I search for the subscript using \peek_catcode_remove:NTF. I could've significantly reduced the code if I had used xparse's e-type arguments, as Henri Menke suggested (thanks :-) and egreg did. I'll keep my answer with the first approach, however.

With the defined commands, the input:

$\sigma_{abc} \sigma^a_0 \sigma_0^b \sigma^c_T$

$\sigma_{abc} \sigma_0^a \sigma^b_0 \sigma^c_T$

$\sigma_{abc} \sigma_0^a \sigma^b_0 \sigma^c_T$


produces (with LuaTeX and lua-visual-debug to show the negative kern):

Notice that the order of subscript and superscript does not matter (anymore, thanks to far too many lines of code) and notice also that the character is kerned only after the \AddtoKernList instruction. To add temporarily a token to this list, do the assignment in a group.

Code:

\documentclass[varwidth]{standalone}
\usepackage{lua-visual-debug}
\usepackage{luatexbase}
\usepackage{unravel}
\usepackage{fontspec}
\usepackage[american,british,french,norsk,german,ngerman]{babel}
\usepackage{mathtools}
\mathtoolsset{mathic=true} %%% See http://tex.stackexchange.com/a/3496/
\usepackage{amssymb}
\usepackage{unicode-math}
\setmainfont[Ligatures=TeX]{TeX Gyre Termes}
\setsansfont{TeX Gyre Heros}[Scale=0.88]
\setmonofont{TeX Gyre Cursor}
\setmathfont[Ligatures=TeX]{TeX Gyre Termes Math}
\setmathfont[Ligatures=TeX,range={\setminus}]{Asana Math}
\setmathfont[Ligatures=TeX,Extension=.otf,range={"2A3E},BoldFont=XITSMath-Bold]{XITSMath-Regular}%%% The fat semicolon
\usepackage[babel=true,verbose=errors]{microtype}

\ExplSyntaxOn
\tl_new:N \l__userxlixk_kern_case_tl
\AtBeginDocument{
\cs_new_eq:NN \__userxlixk_actual_sigma: \sigma
\RenewDocumentCommand\sigma{}
{ \__userxlixk_sigma: }
}
{
\tl_put_right:Nn \l__userxlixk_kern_case_tl
{ { #1 }{ \tex_mskip:D #2 \scan_stop: #1 } }
}
\cs_new_protected:Npn \__userxlixk_sigma:
{
\peek_catcode_remove:NTF \c_math_subscript_token
{ \__userxlixk_sigma_check_group:n }
{ \__userxlixk_sigma_check_superscript: }
}
\cs_new_protected:Npn \__userxlixk_sigma_check_group:n #1
{
\exp_args:NNf
\__userxlixk_actual_sigma: \c_math_subscript_token
{ \__userxlixk_check_kern_list_use:n {#1} }
}
\cs_new_protected:Npn \__userxlixk_sigma_check_superscript:
{
\peek_catcode_remove:NTF \c_math_superscript_token
{ \__userxlixk_sigma_check_sub_after_sup:n }
{ \__userxlixk_actual_sigma: }
}
\cs_new_protected:Npn \__userxlixk_sigma_check_sub_after_sup:n #1
{
\peek_catcode_remove:NTF \c_math_subscript_token
{ \__userxlixk_sigma_sub_after_sup:nn {#1} }
{ \__userxlixk_actual_sigma: \c_math_superscript_token {#1} }
}
\cs_new_protected:Npn \__userxlixk_sigma_sub_after_sup:nn #1 #2
{
\exp_args:NNf
\__userxlixk_actual_sigma: \c_math_subscript_token
{ \__userxlixk_check_kern_list_use:n {#2} }
\c_math_superscript_token {#1}
}

\cs_new:Npn \__userxlixk_check_kern_list_use:n #1
{ \__userxlixk_check_kern_list_use:Nw #1 \q_stop }
\cs_new:Npn \__userxlixk_check_kern_list_use:Nw #1 #2 \q_stop
{
\exp_args:NNo
\tl_case:NnF #1
{ \l__userxlixk_kern_case_tl }
{#1}
#2
}
\ExplSyntaxOff

\begin{document}

$\sigma_{abc} \sigma^a_0 \sigma_0^b \sigma^c_T$

$\sigma_{abc} \sigma_0^a \sigma^b_0 \sigma^c_T$

$\sigma_{abc} \sigma_0^a \sigma^b_0 \sigma^c_T$

\end{document}


If you prefer the e-type argument you can add my lookup list to egreg's answer:

\AtBeginDocument{%
\let\standardsigma\sigma
\let\sigma\kernedsigma
}
\ExplSyntaxOn
\tl_new:N \l__userxlixk_kern_case_tl
{
\tl_put_right:Nn \l__userxlixk_kern_case_tl
{ { #1 }{ \tex_mskip:D #2 \scan_stop: #1 } }
}
\cs_new:Npn \__userxlixk_check_kern_list_use:n #1
{ \__userxlixk_check_kern_list_use:Nw #1 \q_stop }
\cs_new:Npn \__userxlixk_check_kern_list_use:Nw #1 #2 \q_stop
{
\exp_args:NNo
\tl_case:NnF #1
{ \l__userxlixk_kern_case_tl }
{#1}
#2
}
\cs_new_eq:NN \CheckKernListUse \__userxlixk_check_kern_list_use:n
\ExplSyntaxOff

\NewDocumentCommand{\kernedsigma}{e{_^}}{%
\csname exp_args:NNf\endcsname
\standardsigma_
{\IfValueT{#1}{\CheckKernListUse{#1}}}%
\IfValueT{#2}{^{#2}}%
}

• To make it work for both \sigma_a^b and \sigma^b_a you could use an e-type argument (“embellishments”). – Henri Menke Apr 11 '19 at 21:57
• @HenriMenke Thanks for the idea :-) I completely forgot about those. I didn't know, however, that the order in which the arguments were used didn't matter. – Phelype Oleinik Apr 11 '19 at 23:33
• @user49915 If I understand correctly, you want to have a list of characters and the amount of kern to apply to each, is that it? – Phelype Oleinik Apr 11 '19 at 23:34
• @user49915 Not easily, sorry. The lookup table thingy relies on expl3's \tl_case:NnF whose first argument is an N type (if you don't know expl3, an N type is a single token argument). For a token list I'd need a \tl_case:nnF (with a lowercase n), which doesn't exist in expl3. I know how to build this \tl_case:nnF, but unfortunately I don't have the time right now, and it will be a very slow code. I suggest you to do \def\mathrmk{\mathrm{k}} and then use this \mathrmk for the time being. Once I have the time I'll make it for you. – Phelype Oleinik Apr 12 '19 at 13:21
• @user49915 Oops, my bad, I forgot it there. Yes, certainly remove it! – Phelype Oleinik Apr 12 '19 at 15:20

I'd use the e argument type of xparse.

\documentclass{book}
\usepackage{fontspec}
\usepackage[american,british,french,norsk,german,ngerman]{babel}
\usepackage{mathtools}
\usepackage{amssymb}
\usepackage{unicode-math}
\usepackage[babel=true,verbose=errors]{microtype}

\setmainfont{TeX Gyre Termes}
\setsansfont{TeX Gyre Heros}[Scale=0.88]
\setmonofont{TeX Gyre Cursor}
\setmathfont{TeX Gyre Termes Math}
\setmathfont{Asana Math}[
range={\setminus},
]
\setmathfont{XITSMath-Regular}[
Extension=.otf,
range={"2A3E},
BoldFont=XITSMath-Bold,
]

%\mathtoolsset{mathic=true} %%% See http://tex.stackexchange.com/a/3496/

\AtBeginDocument{%
\let\standardsigma\sigma
\let\sigma\kernedsigma
}

\NewDocumentCommand{\kernedsigma}{e{_^}}{%
\standardsigma
\IfValueT{#1}{_{\!#1}}%
\IfValueT{#2}{^{#2}}%
}

\begin{document}

$\sigma_0 \sigma_0^2 \sigma^2_0$
$\standardsigma_{\!0} \standardsigma_{\!0}^2 \standardsigma^2_{\!0}$

\end{document}


• @user49915 I'm not sure what could be the difference. One can quite easily exclude some symbols from being kerned. – egreg Apr 11 '19 at 22:23
• @user49915 I don't know what subscripts you want to use next to \sigma. You probably should kern less than -3mu generally. – egreg Apr 11 '19 at 22:56