If you look in index.idx
, which is what LaTeX writes out for later being processed by MakeIndex, you find
\indexentry{{$\DOTSB \bigcup@ \slimits@ $}}{1}
\indexentry{{$<$}}{1}
What happens? When \index
is found at the outer level, it enters a “semiverbatim” mode, so \index{$\bigcup$}
would write
\indexentry{$\bigcup$}{1}
In particular, what's passed to the eventual \write
operation is the string of characters \bigcup
, not a command.
In your case, instead, the tokens $\bigcup$
have already been formed and the “semiverbatim” mode can do nothing. And TeX will perform macro expansion during \write
.
Solution:
\documentclass[a4paper,openany,12pt]{amsbook}
\usepackage{imakeidx}
\makeindex[name = index, title = Special Index, columns = 3]
\newcommand{\khm}[1]{#1\index[index]{\unexpanded{\unexpanded{#1}}}}
\begin{document}
\khm{$\bigcup$} \khm{$<$}
\printindex[index]
\end{document}
You need two \unexpanded
, because TeX would try expansion twice.
The contents of the .idx
file is now
\indexentry{$\bigcup $}{1}
\indexentry{$<$}{1}
and the .ind
file will be
\begin{theindex}
\item $<$, 1
\item $\bigcup $, 1
\end{theindex}
Regarding \exists!
, you have to take into account that !
is a special character for MakeIndex and has to be quoted. You might go with
\newcommand{\khm}[1]{%
\begingroup\mathcode`"="8000\relax
\begingroup\lccode`~=`"\lowercase{\endgroup\let~}\relax
#1\endgroup\index[index]{\unexpanded{\unexpanded{#1}}}}
so that
\khm{$\exists"!$}
would work as expected. But for this unique case it's much easier and robust to do
$\exists!$\index[index]{$\exists"!$}