2

I'm using the \sindex[]{} command from the splitxdx package to create index entries. To control sorting I'm using the @ symbol, for example \sindex[...]{1@One}.

To make things a bit more configurable, I define a custom command: \newcommand{\sortedOne}{1@One}.

The problem is when I insert this command into \sindex's argument, I get the literal text 1@One showing up. For example, the code \sindex[myindex]{\sortedOne!This fails.} produces the first of the following entries:

enter image description here

Is there an easy way to avoid this? I would prefer a method where I don't have to manually type out something like \expandafter each time I use \sindex.

As an interesting side note, it does work correctly if I wrap the \sindex command in a \comma@parse command from the kvsetkeys package: \comma@parse{\sortedOne!This works with comma parse}{\sindex[myindex]}.

Here's my MWE that produced the output above:

\documentclass[12pt]{book}

\usepackage[split]{splitidx}\makeindex
    \newindex{myindex}
\usepackage{lipsum}
\usepackage{kvsetkeys}
%\usepackage{hyperref}
%\newcommand{\mainindexentry}[1]{\textbf{\hyperpage{#1}}}
\newcommand{\sortedOne}{1@One}

\begin{document}

\lipsum[1]

\sindex[myindex]{1@One!This works fine}
\sindex[myindex]{\sortedOne!This fails.}
\sindex[myindex]{Even subentries fail!\sortedOne}
\makeatletter
\comma@parse{\sortedOne!This works with comma parse}{\sindex[myindex]}
\makeatother

\printindex[myindex]

\end{document}
1
  • the problem is, output to an .idx file is literal -- nothing is expanded. so \sortedOne is what goes into the .idx file for your second and third examples, and of course it doesn't sort with 1@One, since the index sort is basically a dumb ascii sort of whatever is in the .idx file. unfortunately, i can't suggest how to make that approach work as you want it to. probably someone else can. Sep 22, 2014 at 18:37

1 Answer 1

2

Usually index commands do not expand their argument and read its contents verbatim. That also prevents, that macros are expanded. By reading the argument before the index command sees it, the verbatim changes are without effect, because the tokens are already formed, see the definition of \Sindex:

\documentclass[12pt]{book}

\usepackage[split]{splitidx}\makeindex
    \newindex{myindex}
\usepackage{lipsum}
%\usepackage{kvsetkeys}
%\usepackage{hyperref}
%\newcommand{\mainindexentry}[1]{\textbf{\hyperpage{#1}}}
\newcommand{\sortedOne}{1@One}

\newcommand*{\myindex}{\sindex[myindex]}
\newcommand*{\smyindex}[1]{\sindex[myindex]{#1}}
\newcommand*{\Sindex}[2][]{\sindex[{#1}]{#2}}

\begin{document}

\lipsum[1]

\sindex[myindex]{1@One!This works fine}
\expandafter\myindex\expandafter{\sortedOne!This also works.}
\smyindex{Even subentries work!\sortedOne}
\Sindex[myindex]{\sortedOne!\sortedOne}

\printindex[myindex]

\end{document}

Result

Of course, commands that should not expand should be protected by \string:

\Sindex[myindex]{...\string\fragilecmd...}

or several tokens can be protected by \detokenize:

\Sindex[myindex]{...\detokenize{...}...}

Also the methods (with/without expansion) should not mixed to prevent duplicate index entries due to expanded/unexpanded index entries. Depending on the method, the number of spaces after a command can vary:

\sindex[myindex]{\textbf{...}}
\Sindex[myindex]{\string\textbf{...}}
\Sindex[myindex]{\protect\textbf{...}}
\Sindex[myindex]{\textbf{...}}

Result in .idx file:

\indexentry{\textbf{...}}{1}
\indexentry{\textbf{...}}{1}
\indexentry{\textbf {...}}{1}
\indexentry{\textbf  {...}}{1}

The two latter forms can be merged by makeindex' option -c, which merges consecutive spaces, but an entry without space remains different from an entry with space.

1
  • Wonderful notes about extra spaces. Thank you.
    – BMS
    Sep 22, 2014 at 21:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .