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
.
Ok, I think I've found the answer. My thanks go to Gilu, whose info led me to the following solution. Here is the MWE (a little expanded to better see how it works).
\documentclass[openany]{book}
\usepackage{imakeidx}
\makeindex[name=one,title=Index One, intoc, options= -s one.ist]
\makeindex[name=four,title=Index Four, intoc, options= -s four.ist]
\makeindex[name=six,title=Index Six, intoc, options= -s six.ist]
\usepackage[hangindent=0pt,subindent=0pt,subsubindent=0pt]{idxlayout}
\begin{document}
Some text.
\index[one]{Acts of the Avocados!2:2}
\index[one]{Acts of the Avocados!5:5}
\index[one]{Acts of the Avocados!3:3}
\index[one]{Acts of the Avocados!5:5}
\index[one]{Acts of the Avocados!6:6}
\index[one]{Acts of the Avocados!7:7}
\index[one]{Acts of the Avocados!8:8}
\index[one]{Romaines!3:3}
\index[one]{Romaines!4:4}
\index[one]{Romaines!5:5}
\index[four]{Aristotle!Metaphysalis!205c}
\index[four]{Aristotle!Metaphysalis!306d}
\index[four]{Plato!Tomatoes!407e}
\index[four]{Cicero!Lettuce!115}
\index[six]{Bananerges}
\index[six]{Appleadorus}
\index[six]{Plato}
\index[six]{Plato!\textit{Potatoes}!144a}
\index[six]{Plato!\textit{Potatoes}!166d}
\printindex[one]
\printindex[four]
\idxlayout{itemlayout=abshang}
\printindex[six]
\end{document}
Things that have changed:
1) I added idxlayout to make life easy when it comes to turning off indents within the indices without having to mess around in the class file, as suggested by Gilu, 2) I set up the .ist files correctly for what I want to achieve and 3) I added a line of idxlayout code to re-apply indents for the subject index, which comes last.
Now, here are the new .ist files, followed by the .ind files they produce in case anyone else has to customize their index in a similar way. I used the page cited in my question to find the "keys" to controlling different aspects of the index formatting in the .ist files (index style files). This is the link: https://www.sharelatex.com/learn/Indices#/Parameters_for_the_.5Cmakeindex_command.
I messed around with the .ist files until they produced an .ind file that read like working code, so if anyone has to format an index in the same way, that would be my number one tip from this experience: mess around with your .ist files until the .ind files they make when you run (xe)latex look like latex code that should work. Sometimes that means opening curly brackets under one key and closing them under another key.
Final thing: Always make sure your text editor doesn't convert straight quotes (") into curly quotes in your .ist files when you're not looking. It will screw things up.
one.ist:
item_0 "\\indexspace \\vspace{-12pt} \n \\textit{\\item "
item_x1 " } \n \\subitem "
delim_0 " \\hfill "
delim_1 " \\hfill "
delim_2 " \\hfill "
one.ind (although it's set off like code here, this is just the contents of the file; setting it up as code in the forum post editor makes it easier to read):
\begin{theindex}
\textit{\item Acts of the Avocados }
\subitem 2:2 \hfill 1
\subitem 3:3 \hfill 1
\subitem 5:5 \hfill 1
\subitem 6:6 \hfill 1
\subitem 7:7 \hfill 1
\subitem 8:8 \hfill 1
\indexspace
\textit{\item Romaines }
\subitem 3:3 \hfill 1
\subitem 4:4 \hfill 1
\subitem 5:5 \hfill 1
\end{theindex}
four.ist: (\no indent was added because without it there was a space moving the \item in)
item_0 " \\indexspace \n \\item \\noindent \\vspace{10.5pt}"
item_x1 " \n \\subitem \\textit{"
item_x2 " \n } \\subitem "
delim_0 " \\hfill "
delim_1 " \\hfill "
delim_2 " \\hfill "
four.ind:
\begin{theindex}
\item \noindent \vspace{10.5pt}Aristotle
\subitem \textit{Metaphysalis
} \subitem 205c \hfill 1
\subsubitem 306d \hfill 1
\indexspace
\item \noindent \vspace{10.5pt}Cicero
\subitem \textit{Lettuce
} \subitem 115 \hfill 1
\indexspace
\item \noindent \vspace{10.5pt}Plato
\subitem \textit{Tomatoes
} \subitem 407e \hfill 1
\end{theindex}
six.ist:
delim_0 " \\hfill "
delim_1 " \\hfill "
delim_2 " \\hfill "
six.ind:
\begin{theindex}
\item Appleadorus \hfill 1
\indexspace
\item Bananerges \hfill 1
\indexspace
\item Plato \hfill 1
\subitem \textit{Potatoes}
\subsubitem 144a \hfill 1
\subsubitem 166d \hfill 1
\end{theindex}
I'll wait a few days before accepting my own post as the answer since someone may have a more elegant solution.
Best Answer
Short Answer
xindy
is far more flexible thanmakeindex
. Unlikemakeindex
,xindy
supports UTF8, can sort according to different language rules and can support enumeration systems outside of the European and Roman numbering systems. The UTF8 support works best withxindy -I xindy
rather than withtexindy
(xindy -I latex
).Long Answer
The xindy FAQ provides a useful summary of the things
xindy
can do that can't be done withmakeindex
. Here's an abridged form of that summary:In addition to the above, another thing that you can do with
xindy
but not withmakeindex
is to have arbitrary sub-levels. Withmakeindex
you're restricted to primary (level 0), first sub-level and second sub-level entries.The only advantages of
makeindex
overxindy
that I can think of are:makeindex
should be installed with all TeX installations. A TeX installation that doesn't havemakeindex
is most likely extremely old. However,xindy
is only included in TeX Live so MikTeX users will need to install it separately.xindy
is a Perl script and so you must have the Perl interpreter installed on your computer. This is a stumbling block for some Windows users. Unix-like systems tend to have Perl preinstalled.makeindex
usually works with restricted\write18
but last time I tried callingxindy
with a restricted\write18
it was disabled. I expect it will eventually be added to the list of allowed applications. (I can't see any reason why it shouldn't be allowed.)Sorting and collating. Both read a file that contains a set of terms with an associated location (or cross-reference). The terms are sorted according to the designated alphabet (the English alphabet for
makeindex
, or the chosen alphabet forxindy
). The term may have a corresponding key that should be used for the actual sort comparison. Multiple occurrences of each term are then merged into a single entry with a sorted location list. Consecutive numbering in the location list may be compacted into a number range. This information is then written to another file, which can be input by an application such astex
orlatex
. (The output markup can be changed via a style file or module, which means that althoughmakeindex
andxindy
are often used with TeX/LaTeX, they can be used with other systems as well.)The syntax of the
.ist
format is much simpler than the.xdy
format, but this is because it's more restrictive.makeindex
style format (.ist
)This is just a list of ⟨specifier⟩ ⟨attribute⟩ pairs. The specifiers are divided into two groups: the input specifiers and the output specifiers.
The input specifiers tell
makeindex
how the input is formatted. Consider the following document:On the first LaTeX run, a file with the extension
.idx
is created and at the end of the run contains:This is the default format for
makeindex
but can be explicitly set in a.ist
file using:There are some other input specifiers as well. (See Index Preparation and Processing.) These specifiers enable
makeindex
to correctly parse the input file.The output specifiers tell
makeindex
how to format the output. If you runmakeindex
on the above example, the resulting.ind
file will look like:This uses the default output specifiers, which include:
This
.ind
file can now be input by LaTeX (via\printindex
). The resulting index looks like:If I wanted, say, to have headings at the start of each letter group, I can create a file called, say,
test.ist
that contains:Now I need to run
makeindex
with-s test.ist
which will now write the following to the.ind
file:The next LaTeX run now produces the index:
The reason why the entry "The Rise and Fall of the Duck Empire" is listed in the "R" category rather than the "T" category is because I set the sort key for that entry to "Rise and Fall of Duck Empire".
xindy
style format (.xdy
)Unlike
makeindex
,xindy
has modules, which can load other modules, so you can build on existing styles. In addition,xindy
has an--input-markup
(-I
) command line switch that is used to indicate the input markup. There are three supported markup settings:latex
,omega
andxindy
.xindy -I latex
Using
texindy
is equivalent to callingxindy
with-I latex
and with the modules that enablexindy
to parse files written using the defaultmakeindex
input specifiers. So, for example, the above.idx
file created by LaTeX can be processed directly bytexindy
. If the file is called, say,test.idx
thentexindy test.idx
will create an.ind
file that contains:This is similar to the
.ind
file created bymakeindex
except that it uses\lettergroup
to markup the category headings. If this command isn't already defined, it will be defined via\providecommand
at the start of the.ind
file. If you want to change the way the heading is formatted, you just need to define\lettergroup
before\printindex
. This makes it simpler than themakeindex
example shown above that needed a custom.ist
file to make the headings appear.Writing a
xindy
module is quite complicated and too long to discuss in this (already very long) answer, but thexindy
FAQ gives an introduction. However, there are a number of modules supplied byxindy
that cover common requirements, in particular the language modules. The modules are in subdirectories of TEXMF/xindy/modules/
where TEXMF is the base of the TEXMF tree. The language modules are in TEXMF/xindy/modules/lang/
and are identified via the-L
command line option.Suppose my
.idx
file now looks like:makeindex
creates the following.ind
file:Here
makeindex
has positioned "ænder" after "zebra". This may not look too bad at first glance if that's the correct position for your language, but now try adding headings by creating an.ist
file that contains:Running
makeindex
with this style results in:The UTF8 characters have become mangled as
makeindex
has only grabbed the first octet of æ for the heading. This has ruined the file encoding.In theory, if I want to use
texindy
instead, I need to specify the language using the-L
switch (in this case-L danish
) and the encoding using the-C
switch (in this case-C utf8
). Unfortunately this results in the error:and no
.ind
file is produced.The error goes away if I use
-M lang/danish/utf8
. This results in the.ind
file containing:which has put "ænder" in the "A" letter group (which is incorrect for the Danish alphabet, see the comment below).
Getting the
.idx
file into the format shown above is somewhat harder. The following XeLaTeX document works fine:The equivalent LaTeX document:
produces:
which confuses
texindy
.xindy -I xindy
With the
xindy
input markup, the.idx
file has entries in the format:where
sort
is the text used by the comparison function when sorting,term
is how the entry should be typeset in the.ind
file,location
is the associated location (page number) for this entry andattribute
is the associated attribute. This is the format used by theglossaries
package when used with thexindy
package option.The differences between the syntax used by
makeindex
andxindy
can be illustrated by examining the files created using theglossaries
package.Consider the following LaTeX document:
This is analogous to the earlier
makeidx
example. By default, this document assumes thatmakeindex
will be used. This creates the.idx
file containing:This uses
\glossaryentry
instead of\indexentry
and the encap character is?
instead of@
, soglossaries
creates amakeindex
.ist
file that contains:If, on the other hand, you added the
xindy
package option when you loadglossaries
:The
.idx
file now looks like:The extended Latin characters, such as å haven't been expanded as they were in the earlier
makeidx
example since, by default,glossaries
"sanitizes" the sort key. (The reason for the braces around æ is discussed in the UTF8 section of themfirstuc
manual.)This time, instead of creating an accompanying
.ist
file,glossaries
now creates axindy
.xdy
file that is considerable larger, and is too large to reproduce here without exceeding the maximum length of a StackExchange answer. However, if you try the above example yourself, you'll be able to see the syntactic differences.Running the Perl script
makeglossaries test
(where the example file is calledtest.tex
) is equivalent to runningxindy
as:Although
-L danish -C utf8
has been used, this now doesn't produce the earlier error withtexindy
asxindy
is no longer trying to inputtex/inputenc/utf8.xdy
. The index now looks like:Again, switching to XeLaTeX makes the document simpler: