3

I'm a long time LaTeX user, and over the years this forum has been extremely useful. I have always found an answer here, except this time.

I'm trying to create a newcommand to define some math symbols. The command defines a macro, and that macro uses \index{} when the symbol is used. It works most of the time. However, there is some math notation that generate extra @ characters, which it is not appreciated by makeindex.

I know this question is similar (but different) to question 254977, but I have been unable to adapt that solution to this situation.

This is a sample test.tex file:

% arara: pdflatex: { synctex: on } 
% arara: makeindex 
% arara: pdflatex: { synctex: on } 
\documentclass{article}
\usepackage{amsmath,amssymb,mathrsfs,makeidx}
\makeindex

\newcommand{\MKMathSymbol}[4]{%
    \expandafter\newcommand\csname #1\endcsname{\ensuremath{#2}\index{#4!#3@\ensuremath{#2}}}
        %%% More stuff in here (glossaries, etc.)
}

\MKMathSymbol{TestOne}{\widehat{\varphi}}{phi}{Type A}
\MKMathSymbol{TestTwo}{\widehat{\mathscr{A}}}{A}{Type A}
\MKMathSymbol{TestThree}{\widehat{d_C}}{dCw}{Type B}
\MKMathSymbol{TestFour}{{\prod}}{P}{Type B}

\begin{document}
Outside math mode (\TestOne, \TestTwo, \TestThree, \TestFour). 
\clearpage 
Inside math mode  ($\TestOne$, $\TestTwo$, $\TestThree$, $\TestFour$). 
\clearpage 
Inside macro: (\emph{\TestOne, \TestTwo, \TestThree, \TestFour}).

Let now print the index:
\printindex
\end{document}

The output of makeindex (test.ilg file) contains the following:

This is makeindex, version 2.15 [MiKTeX 2.9.6100 64-bit] (kpathsea + Thai support).
Scanning input file test.idx...
!! Input index error (file = test.idx, line = 1):
   -- Extra `@' at position 36 of first argument.
 . . .
 . . .
done (0 entries accepted, 12 rejected).
Nothing written in test.ind.
Transcript written in test.ilg.

And the file text.idx will contain entries like these:

\indexentry{Type A!phi@\ensuremath  {\setbox \z@ \hbox {\frozen@everymath \@emptytoks \mathsurround \z@ $\textstyle \varphi $}\mathaccent "0362{\varphi }}}{1}
\indexentry{Type A!A@\ensuremath  {\setbox \z@ \hbox {\frozen@everymath \@emptytoks \mathsurround \z@ $\textstyle \mathscr  {A}$}\mathaccent "0362{\mathscr  {A}}}}{1}
\indexentry{Type B!dCw@\ensuremath  {\setbox \z@ \hbox {\frozen@everymath \@emptytoks \mathsurround \z@ $\textstyle d_C$}\mathaccent "0362{d_C}}}{1}
\indexentry{Type B!P@\ensuremath  {{\DOTSB \prod@ \slimits@ }}}{1}

The generated pdf file does not print the index, because test.ind is empty. So, the question is how do I make this work? I have tried several approaches, but none of them seems to work.

MaMike
  • 33
  • Both solutions below (David Carlisle's use of \protect, and egreg's use of \unexpanded) work fine. I used egreg solution, because it goes in a single definition, and I don't need to be careful every time I add a new math symbol. Thanks you both for your elegant solutions. – MaMike Nov 10 '16 at 08:27

2 Answers2

2

Use \unexpanded:

\documentclass{article}
\usepackage{amsmath,amssymb,mathrsfs,makeidx}
\makeindex

\newcommand{\MKMathSymbol}[4]{%
  \expandafter\newcommand\csname #1\endcsname{%
    \ensuremath{#2}\index{#4!#3@\unexpanded{\unexpanded{\ensuremath{#2}}}}%
    %%% More stuff in here (glossaries, etc.)
  }%
}

\MKMathSymbol{TestOne}{\widehat{\varphi}}{phi}{Type A}
\MKMathSymbol{TestTwo}{\widehat{\mathscr{A}}}{A}{Type A}
\MKMathSymbol{TestThree}{\widehat{d_C}}{dCw}{Type B}
\MKMathSymbol{TestFour}{\prod}{P}{Type B}

\begin{document}
Outside math mode (\TestOne, \TestTwo, \TestThree, \TestFour). 
\clearpage 
Inside math mode  ($\TestOne$, $\TestTwo$, $\TestThree$, $\TestFour$). 
\clearpage 
Inside macro: (\emph{\TestOne, \TestTwo, \TestThree, \TestFour}).

Let now print the index:
\printindex
\end{document}

Here's the contents of the .idx file

\indexentry{Type A!phi@\ensuremath {\widehat {\varphi }}}{1}
\indexentry{Type A!A@\ensuremath {\widehat {\mathscr {A}}}}{1}
\indexentry{Type B!dCw@\ensuremath {\widehat {d_C}}}{1}
\indexentry{Type B!P@\ensuremath {\prod }}{1}
\indexentry{Type A!phi@\ensuremath {\widehat {\varphi }}}{2}
\indexentry{Type A!A@\ensuremath {\widehat {\mathscr {A}}}}{2}
\indexentry{Type B!dCw@\ensuremath {\widehat {d_C}}}{2}
\indexentry{Type B!P@\ensuremath {\prod }}{2}
\indexentry{Type A!phi@\ensuremath {\widehat {\varphi }}}{3}
\indexentry{Type A!A@\ensuremath {\widehat {\mathscr {A}}}}{3}
\indexentry{Type B!dCw@\ensuremath {\widehat {d_C}}}{3}
\indexentry{Type B!P@\ensuremath {\prod }}{3}
egreg
  • 1,121,712
1

You are seeing the internal expansion of the commands "fragile command in a moving argument" in the terminology of the latex book. use

\MKMathSymbol{TestOne}{\protect\widehat{\varphi}}{phi}{Type A}
\MKMathSymbol{TestTwo}{\protect\widehat{\mathscr{A}}}{A}{Type A}
\MKMathSymbol{TestThree}{\protect\widehat{d_C}}{dCw}{Type B}
\MKMathSymbol{TestFour}{{\protect\prod}}{P}{Type B}

The index is then

\indexentry{Type A!phi@\ensuremath  {\widehat {\varphi }}}{1}
\indexentry{Type A!A@\ensuremath  {\widehat {\mathscr  {A}}}}{1}
\indexentry{Type B!dCw@\ensuremath  {\widehat {d_C}}}{1}
\indexentry{Type B!P@\ensuremath  {{\prod }}}{1}
\indexentry{Type A!phi@\ensuremath  {\widehat {\varphi }}}{2}
\indexentry{Type A!A@\ensuremath  {\widehat {\mathscr  {A}}}}{2}
\indexentry{Type B!dCw@\ensuremath  {\widehat {d_C}}}{2}
\indexentry{Type B!P@\ensuremath  {{\prod }}}{2}
\indexentry{Type A!phi@\ensuremath  {\widehat {\varphi }}}{3}
\indexentry{Type A!A@\ensuremath  {\widehat {\mathscr  {A}}}}{3}
\indexentry{Type B!dCw@\ensuremath  {\widehat {d_C}}}{3}
\indexentry{Type B!P@\ensuremath  {{\prod }}}{3}
David Carlisle
  • 757,742