25

I'm using xindy to generate indexes for a manual that gets translated into multiple languages. Unfortunately, hyperref and xindy don't like to play nicely together. I found some older mailing list threads that suggest that fixing this in xindy would require too much effort.

My question is: how can I get xindy and hyperref to play nicely together. What is the best workaround for this incompatibility?

An example document will demonstrate the problem:

\documentclass{article}

\usepackage{lipsum}
\usepackage{makeidx}
\usepackage{hyperref}

\makeindex

\begin{document}

\index{single}
\index{range|(}
\lipsum
\index{range|)}

\printindex

\end{document}

I compile this document (named x.tex) using xelatex and xindy:

xelatex x
xindy -C utf8 -M texindy -L english x.idx
xelatex x
xelatex x

Page numbers that are part of a range are missing from the index:

Missing page range numbers

The xindy output makes a few complaints:

WARNING: Found no :close-range matching an already opened one!
         Location-reference is 1 in keyword (range).
         Maybe I lost some of the regular location-references.

WARNING: Found a :close-range in the index that wasn't opened before!
         Location-reference is 2 in keyword (range)
         I'll continue and ignore this.

These errors make sense when we look at the x.idx file:

\indexentry{single|hyperpage}{1}
\indexentry{range|(hyperpage}{1}
\indexentry{range|)}{2}

The hyperpage command isn't used in the close-range entry.

In order of preference, here are my desired outcomes:

  1. xindy and hyperref work perfectly together and generate indexes with hyperlinked page numbers without any external processing.
  2. xindy and hyperref can generate indexes with hyperlinked page numbers with the aid of an external script to pre- or post-process the index files before/after passing them through xindy. (I'm not currently using any special formatting for page numbers if that simplifies things.)
  3. xindy can be pacified by removing hyperlinks from the page numbers (with or without the use of an external script).

Alternatively, is there a different indexing program that can work with UTF-8-encoded files, hyperref, and knows to collate various languages?

5
  • @Stephen: That perl script failed to run for me. It initially complained about an unmatched ( in the regex. I escaped the ( with backslashes, but then it just made a message of the .idx file.
    – godbyk
    Nov 4, 2012 at 19:57
  • @Stephen: That only adjusts the second line of the .idx file shown above. xindy reports the following: WARNING: unknown cross-reference-class hyperindexformat'! (ignored)' and the pagae range still doesn't appear in the index.
    – godbyk
    Nov 5, 2012 at 20:22
  • OK, another experiment (Lacking the knowledge I'm doing trial and error here, sorry): What happens when you remove the hyperpage from \indexentry{range|(hyperpage}{1}?
    – Stephen
    Nov 6, 2012 at 20:45
  • Then I get “range, 1, 2” in the index (as opposed to the expected “range, 1–2”. But at least xindy doesn't balk.
    – godbyk
    Nov 6, 2012 at 21:06
  • No hyperlinks, just the page numbers.
    – godbyk
    Nov 6, 2012 at 21:27

3 Answers 3

15

Simple ranges

In hyperref 2012/11/06 v6.83m the encapsulating command will be repeated, if it is not explicitly given for the closing range entry. Then both Makeindex and xindy should be happy in case of simple ranges:

\index{...|(}
\index{...|)}

The .idx file will contain hyperpage in both cases.

Formatting commands

From the manual page of xindy:

For raw index entries in LaTeX syntax, \index{aaa|bbb} is interpreted differently. For MakeIndex bbb is markup that is output as a LaTeX tag for this page number. For xindy, this is a location attribute, an abstract identifier that will be later associated with markup that should be output for that attribute.

For straight-forward usage, when bbb is textbf or similar, we supply location attribute definitions that mimic MakeIndex's behaviour.

For more complex usage, when bbb is not an identifier, no such compatibility definitions exist and may also not been created with current xindy. In particular, this means that by default the LaTeX package hyperref will create raw index files that cannot be processed with xindy. This is not a bug, this is the unfortunate result of an intented incompatibility. It is currently not possible to get both hyperref's index links and use xindy.

A similar situation is reported to exist for the memoir LaTeX class.

Programmers who know Common Lisp and Lex and want to work on a remedy should please contact the author.

Ad 3.

Easy, hyperref index redefinitions are suppressed by

\usepackage[hyperindex=false]{hyperref}

Maybe there is a way to insert \hyperpage for linked page numbers in xindy.

Minimal page range

Xindy make page ranges starting with three consecutive page numbers. This can changed by setting :min-page-range to 1 (default is 2). The following file mypagerange.xdy also includes page-ranges.xdy that contains the definition of the range separator:

; File mypagerange.xdy
(require "page-ranges.xdy")
(define-location-class "arabic-page-numbers"
                       ("arabic-numbers") :min-range-length 1)

Then xindy is called with option -M mypagerange.xdy.

3
  • thanks for the hyperref update! It looks like it pacifies xindy for the most part. The only remaining problem is that xindy shows the “range” entry as “range, 1, 2” instead of “range, 1–2” (despite my specifying -M page-ranges.xdy to xindy). xindy lodges no complains against the new index file. Any ideas there?
    – godbyk
    Nov 15, 2012 at 4:42
  • The mypagerange.xdy script worked perfectly. Thanks, Heiko!
    – godbyk
    Nov 21, 2012 at 7:30
  • \hyperpage for linked page numbers can be inserted with (markup-locref :open "\hyperpage{" :close "}).
    – michal.h21
    Jan 23, 2013 at 22:16
7

Here's the solution that worked for me (based on Heiko's and michal's replies).

\documentclass{article}

\usepackage{lipsum}
\usepackage[xindy]{imakeidx}
\usepackage[hyperindex=false]{hyperref}
\def\xindyopt{-M indexstyle}
\makeindex[options=\xindyopt]

\begin{filecontents*}{indexstyle.xdy}
(require "page-ranges.xdy")
(define-location-class "arabic-page-numbers"
                       ("arabic-numbers") :min-range-length 1)
(markup-locref :open "\hyperpage{" :close "}")
\end{filecontents*}

\begin{document}

\index{single}
\index{range|(}
\lipsum
\index{range|)}

\printindex

\end{document}
2
  • Does this solution reveal anything new?
    – user31729
    Aug 25, 2014 at 20:44
  • 2
    It corrects a syntax error in michal's answer and simply puts everything together for struggling texnicians like me that are trying to compile their first index.
    – emav
    Aug 26, 2014 at 7:48
1

Ad 2)

perl -pi -e 's/\|\)/\|hyperpage\)/g' myfile.idx

after the first latex call, before the xindy call.

1
  • Sorry to necro this question, but six years later, this bug still hasn't been fixed. Your perl script works correctly in isolation, but I can't manage to add it to my build chain in TexStudio. I've tried putting it at every point in the compilation process, and I added it to the texindy command, all to no avail. Any ideas? May 16, 2021 at 14:03

You must log in to answer this question.

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