2

(Note: This is somewhat related similar post, but the issue is quite different.)

I'm trying to make an index entry using \index that has a bolded page number, all while the hyperref package is loaded. Normally when hyperref sees a manually-inserted |textbf in an index entry it will do something clever like modify or remove the usual |hyperpage insertion. That's fine. No problem.

The trouble lies when I try to first parse argument of \index using the macro \comma@parse from the kvsetkeys package, as shown here:

%with hyperref is loaded, this produces a bad .idx entry
\comma@parse{But this fails on makeindex|textbf}{\index{\comma@entry}\@gobble}

The code above produces the following entry in the .idx file:

\indexentry{But this fails on makeindex|textbf|hyperpage}{1}

As you can see, there are two | symbols in the entry, causing the makeindex to reject it. hyperref should have caught this.

  • If I disable hyperref, everything works fine.
  • If I don't use the \comma@parse macro, everything works fine.
  • The same thing happens if instead of |textbf I do |see etc.

It's as if using \comma@parse doesn't allow hyperref to do its job.

Is there a way I can get the .idx entry to be well-formed while keeping hyperref loaded?

Here's the MWE I'm using:

\documentclass[12pt]{book}

\usepackage{makeidx}\makeindex
\usepackage{lipsum}
\usepackage{kvsetkeys}
\usepackage{hyperref}

\begin{document}

\lipsum[1]

\index{1@This works fine|textbf}
\makeatletter
    \comma@parse{2@So does this}{\index{\comma@entry}\@gobble}
    \comma@parse{3@But this fails on makeindex|textbf}{\index{\comma@entry}\@gobble}
\makeatother

\printindex

\end{document}

And here's the .idx file that is created after typesetting:

\indexentry{This works fine|hyperindexformat{\textbf}}{1}
\indexentry{So does this|hyperpage}{1}
\indexentry{But this fails on makeindex|textbf|hyperpage}{1}
5

The | is hidden by macro \comma@entry. Therefore hyperref does not see it, when it appends |hyperpage for hyper-linked page numbers in the index. \expandafter helps:

\documentclass[12pt]{book}

\usepackage{makeidx}\makeindex
\usepackage{lipsum}
\usepackage{kvsetkeys}
\usepackage{hyperref}

\begin{document}

\lipsum[1]

\index{This works fine|textbf}%
\makeatletter
    \comma@parse{So does this}{\index{\comma@entry}\@gobble}%
    \comma@parse{This also works|textbf}{%
      \expandafter\index\expandafter{\comma@entry}\@gobble 
    }%
\makeatother

\printindex

\end{document}

Or much easier, \index is already used as command that takes an entry, thus it can be directly used as comma list processor:

\documentclass[12pt]{book}

\usepackage{makeidx}\makeindex
\usepackage{lipsum}
\usepackage{kvsetkeys}
\usepackage{hyperref}

\begin{document}

\lipsum[1]

\index{This works fine|textbf}%
\makeatletter
    \comma@parse{So does this}\index
    \comma@parse{This also works|textbf}\index
\makeatother

\printindex

\end{document}

Result

Package splitidx

The trick of the previous example also works for commands with additional argument, if they precede the argument, which gets the list entry:

\comma@parse{my, comma, list}{\sindex[...]}

A macro \idxboldpage can be defined to get hyperlinked bold page numbers, as \sindex of package splitidx is not automatically supported by hyperref:

\newcommand*{\idxboldpage}[1]{%
  \textbf{\hyperpage{#1}}%
}

Then \index{...|idxboldpage} is used instead of \index{...|textbf}.

Full example:

\documentclass[12pt]{book}

\usepackage[makeindex]{splitidx}
\newindex[Author index]{authidx}
\newcommand*{\idxboldpage}[1]{%
  \textbf{\hyperpage{#1}}%
}

\usepackage{lipsum}
\usepackage{kvsetkeys}
\usepackage{hyperref}

\begin{document}

\lipsum[1]

\index{This works fine|textbf}%
\makeatletter
    \comma@parse{So does this}{\sindex[authidx]}
    \comma@parse{This also works|idxboldpage}{\sindex[authidx]}
\makeatother

\printindex[authidx]

\end{document}
  • My mouth dropped when I saw that second solution. Thank you. I think I still have some more learning to understand why you can put \index like that without an explicit {} argument. FYI modified index entries with 1@ etc. – BMS Sep 17 '14 at 19:48
  • Is there a similar solution for using \sindex[]{} from the splitidx package? Neither works; I'm using \sindex[] where I would put \index. Should I post that as a separate question? – BMS Sep 17 '14 at 19:58
  • @BMS It's the way \comma@parse works. It has two interfaces. In the first example \comma@entry is defined and can be used by the comma list processor. Also the comma list processor gets the entry in curly braces as argument. Therefore \index as comma list processor sees the entry as argument. – Heiko Oberdiek Sep 17 '14 at 19:58
  • 2
    @BMS The important issue is that | is not hidden in a macro, when hyperref's index macros are used. – Heiko Oberdiek Sep 17 '14 at 20:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.