# Subscript kerning for specific letters in XeLaTeX

I have used the following code, which is a minor modification of @egreg's code provided in Making f active in math mode, to change the subscript kerning for specific letters (e.g. f in this example).

However, there are two concerns:

a) the kerning of superscripts is also affected e.g. in $f_{a}^{b}$

b) if a superscript precedes the subscript, as e.g. in $f^{b}_{a}$, nothing is affected.

I understand (at least in principle) what the code does and why these issues come up. However, I haven't been able to resolve them.

\documentclass{article}
\usepackage{fontspec}
\usepackage{xunicode}

\makeatletter
\DeclareRobustCommand{\fixsubkerning}[3]{
\AtBeginDocument{%
\edef\SAVEfCODE{\the\Umathcodenum#1 } % just for the test
\Umathcharnumdef#3\Umathcodenum#1
\mathcode#1=\string"8000 }
\begingroup\lccode~=#1
\lowercase{\endgroup
\def~{%
#3
\ifnum\mathgroup=\m@ne
\expandafter\@firstofone
\else
\expandafter\@gobble
\fi
{\@ifnextchar_{\mkern-#2mu}{\relax}}%
}
}
}
\makeatother

\fixsubkerning{f}{5}{\mathf}

\begin{document}
$f_{a}$
\end{document}


Any help is appreciated.

You can use the e feature of xparse. But, really, mathspec is a set of kludges and we're adding kludges to kludges.

\documentclass{article}
\usepackage{mathspec}
\setmainfont{Hoefler Text}
\setmathfont(Digits,Latin)[Numbers=Lining]{Hoefler Text}
\setmathrm[Numbers=Lining]{Hoefler Text}

\AtBeginDocument{%
\Umathcharnumdef\mathematicalf\Umathcodenumf
\mathcodef=\string"8000
}

\NewDocumentCommand{\usemathematicalf}{e{_^}}
{
\usemathematicalfaux#1
}
\ExplSyntaxOn
\NewDocumentCommand{\usemathematicalfaux}{mm}
{
\mathematicalf
\IfValueTF{#1}{\sb{#1}}{ \int_compare:nT { \mathgroup=-1}{\,} }
\IfValueT{#2}{\sp{\mkern4mu\scan_stop: #2}}
}
\char_set_active_eq:NN f \usemathematicalf
\ExplSyntaxOff

\begin{document}

$f(x)f_1(x)\mathbf{f}(x)\mathbf{f}_1(x)\mathbf{f_1}(x)$

$f(x)f_1(x)f_1^2(x)f^2_1(x)\mathbf{f}_1^{\,2}(x)$

\end{document}


I've pieced together a solution from the code you mentioned and this answer to catch sub- and superscripts after a macro. The idea is to have the active character's macro catch following sub- and superscripts so that we can kern them separately.

\makeatletter
\DeclareRobustCommand{\fixkerning}[4]{
\AtBeginDocument{%
\Umathcharnumdef#4\Umathcodenum#1
\mathcode#1=\string"8000 }
\begingroup\lccode~=#1
\lowercase{\endgroup
\def~{%
#4
\ifnum\mathgroup=\m@ne
\expandafter\@firstofone
\else
\expandafter\@gobble
\fi
{%
\let\fix@sub\@empty%
\let\fix@sup\@empty%
\def\fix@kernsub{#2mu}%
\def\fix@kernsup{#3mu}%
\fix@test%
}%
}
}
}

\def\fix@test{%
\@ifnextchar_{\fix@catch@sub}{%
\@ifnextchar^{\fix@catch@sup}{\fix@fini}}}
\def\fix@catch@sub_#1{%
\expandafter\def\expandafter\fix@sub\expandafter{\fix@sub#1}\fix@test}
\def\fix@catch@sup^#1{%
\expandafter\def\expandafter\fix@sup\expandafter{\fix@sup#1}\fix@test}
\def\fix@fini{%
\ifx\fix@sub\@empty\else_{\mkern\fix@kernsub\fix@sub}\fi%
\ifx\fix@sup\@empty\else^{\mkern\fix@kernsup\fix@sup}\fi}

\fixkerning{f}{-2}{0}{\math@f}
\makeatother


Notice the reversal of the argument sign with respect to your implementation. Compared to nonactive characters, things like $f_\text{x}$ do not work anymore because the function collects only the \text` token but not its argument.