# Prevent incorrect expansion of \! in index

I recently upgraded from texlive-2019 to texlive-2020, and my index command broke.

The relevant code is:

\newcommand{\BasisChange}[2]{[#2\!\leftarrow\!#1]}

A change of basis matrix\index{$\BasisChange{\mathcal A}{\mathcal B}$}.


In texlive-2019, this would produce an entry in my .ind file of

  \item {$[\mathcal B\tmspace -\thinmuskip {.1667em}\leftarrow \tmspace -\thinmuskip {.1667em}\mathcal A]$},
161


whereas in texlive-2020, it produces

  \item $[\mathcal B\ \subitem \leftarrow \ \subsubitem \mathcal A]$, 161


It seems that the \! is being interpreted as the start of a subitem.

Is there a way I can get the old behaviour back or "protect" my math command so \! isn't misinterpreted?

• Clearly it shouldn't behave that way, but my comment is about something else. When using a math expression as an index term, you really should consider providing a sort field. The index sort is really dumb -- with makeindex, plain ascii -- so you want some control over where this entry gets placed. – barbara beeton Jan 17 at 3:22

What's happening here is that the macro gets expanded when its contents are written to the .idx file you get an entry of

\indexentry{$\mathcal B\!\leftarrow\!\mathcal A$}


(There are other issues with how you've defined things. Try doing \BasisChange{A}{\mathcal B} for example.)

The exclamation marks get interpretted as being subitems. I think that just doing the basics of changing your index command to

\index{B-A@\BasisChange{A}{B}}

will fix the problem as makeindex shouldn't be parsing for subentries past the @ if I remember correctly.

Edit: Digging a bit deeper this won't work. You could try

\index{B-A@{A}{B}|BasisChange}


but I've not checked that. End edit

Putting \protect before \BasisChange should also work and if you have a lot of these in your document, you could use \DeclareRobustCommand (actually, probably \DeclareRobustCommand* would be even better) in place of \newcommand so you get the \protection automatically.

As for why this is broke with the update, I did a cursory search through the git history and it looks like it might be connected with changes regarding robustness that were part of the 2019 patches to LaTeX, but I didn't see anything obvious.