Der Index am Ende eines Buches – die Liste der Begriffe mit den Seiten, auf denen sie vorkommen – wird von LaTeX nicht selbst erstellt. LaTeXs Aufgabe endet damit, die im Text gesetzten \index{…}-Marken einzusammeln und als rohe Liste namens .idx auszuschreiben. Diese Liste zu sortieren und zu einem Index zu formen, erledigt ein eigenes Programm, makeindex. Die Arbeitsteilung hat eine Vorgeschichte: Die Dokumentation von makeindex nennt Leslie Lamport, den Autor von LaTeX, als jemanden, der wesentlich zu ihrem Entwurf beigetragen hat. Diese Seite führt vom Paket makeidx und der Deklaration \makeindex über die Eintragssyntax (! für Untereinträge, @ für Sortierschlüssel) und die Bauschritte bis zur Antwort darauf, warum „Ångström“ hinter „Zulu“ einsortiert wird.
Die vier Bausteine eines Index – warum makeidx nur acht Zeilen hat
Ein Index braucht vier Bausteine: \usepackage{makeidx} und \makeindex in der Präambel, ein \index{Begriff} überall dort, wo ein Begriff auftaucht, und \printindex an der Stelle, an der die Liste gesetzt werden soll. Überraschend ist, dass zwei davon – \makeindex und \index – bereits im LaTeX-Kern (latex.ltx) stecken. Das Paket makeidx steuert \printindex sowie \see und \seealso für Querverweise bei; das sind tatsächlich etwa acht Zeilen Code. Der Entwurf verrät damit etwas: Die schwere Arbeit des Indexierens sollte von Anfang an außerhalb von LaTeX stattfinden.
\usepackage{makeidx}– stellt\printindexsowie\see/\seealsobereit (Präambel).\makeindex– die Deklaration, die\jobname.idxöffnet und\indexin die tatsächlich schreibende Fassung umdefiniert (nur in der Präambel). Im Terminal erscheintWriting index file mydoc.idx.\index{Begriff}– die Marke an der Stelle, an der ein Begriff vorkommt. Sie gibt nichts aus; festgehalten wird allein die Seitenzahl dieser Stelle.\printindex– der Befehl, der den fertigen Index setzt. Er läuft auf das Einlesen der.ind-Datei hinaus und steht üblicherweise am Dokumentende.
Es lohnt zu betonen, dass \index eine unsichtbare Marke ist. Das Wort selbst wird weiterhin im Text geschrieben, das \index{…} folgt unmittelbar darauf: random numbers\index{random numbers} are used. Und es gibt eine Falle, auf die es ankommt: Fehlt \makeindex in der Präambel, verschluckt \index sein Argument und tut nichts – genau so lautet die Voreinstellung im Kern. Es erscheint weder Fehler noch Warnung, nur der Index bleibt leer. Wenn Dutzende \index-Aufrufe überhaupt nichts hervorbringen, ist zuerst diese eine fehlende Zeile verdächtig.
\documentclass{article}
\usepackage{makeidx}
\makeindex % without this line, \index does nothing
\begin{document}
METAFONT\index{METAFONT} draws the shapes,
TeX\index{TeX} sets the type.
We cover random numbers\index{random numbers|textbf} here,
and touch on groups\index{group} and rings\index{ring}.
The treatment of algorithms\index{algorithm|(} starts here ...
% ... several pages later ...
... and the treatment of algorithms\index{algorithm|)} ends here.
\printindex
\end{document}Einträge schreiben: die vier Zeichen !, @, | und das Anführungszeichen
Das Argument von \index besitzt eine eigene kleine Syntax, die auf vier Sonderzeichen beruht. Festhalten sollte man: Diese vier werden von makeindex ausgewertet, nicht von LaTeX. Für LaTeX ist das Argument bloß eine Zeichenkette, die unverändert in die .idx-Datei fließt. Ein Syntaxfehler zieht deshalb beim Satz keinerlei Beschwerde nach sich; er zeigt sich erst beim Lauf von makeindex als Warnung im Protokoll .ilg.
Untereinträge über !. Das Ausrufezeichen trennt die Ebenen: \index{animals!cats} stellt „cats“ unter den Haupteintrag „animals“. Wiederholtes ! verschachtelt weiter, bis zu drei Ebenen (0, 1 und 2) – die konstruktive Obergrenze von makeindex. Sortierschlüssel über @. In der Form sortkey@display trennt er die zum Ordnen verwendete Zeichenkette von der tatsächlich gedruckten: \index{alpha@$\alpha$} druckt α im Index, sortiert es aber dort ein, wo „alpha“ hingehört. Bei Symbolen und Formeln, deren Glyphen zu Unsinn sortieren, ist das keine Kür.
Die Formatierung der Seitenzahl übernimmt |. Nach dem senkrechten Strich folgt der Name eines Befehls mit einem Argument (ohne führenden Backslash), und genau diese Seitenzahl wird damit gesetzt. \index{cat|textbf} ist die klassische Art, die Seite mit der Definition fett zu setzen; |textit oder ein eigener Befehl gehen ebenso. Seitenbereiche über |( und |). Erstreckt sich ein Thema über mehrere Seiten, öffnet \index{recursion|(} und schließt \index{recursion|)} einen Bereich wie 12--15. Zu beachten: makeindex fasst drei oder mehr aufeinanderfolgende Seiten von sich aus zu einem Bereich zusammen; abschalten lässt sich das mit der Option -r.
Querverweise stehen ebenfalls hinter |. \index{dog|see{pets}} gibt statt einer Seitenzahl „dog, see pets“ aus, |seealso{…} liefert „see also“. Beide rufen die von makeidx definierten Befehle \see und \seealso auf; die ausgegebenen Wörter lassen sich daher über \seename (Standard „see“) und \alsoname (Standard „see also“) in andere Sprachen bringen. Schließlich maskiert das Anführungszeichen: Um !, @, | oder das Anführungszeichen selbst als gewöhnliches Zeichen in einen Eintrag zu bekommen, stellt man ihm ein Anführungszeichen voran – \index{C"!} ergibt den Eintrag „C!“. Genau hier scheitern Indizes zu C und C++ üblicherweise.
| Zeichen | Aufgabe | Beispiel |
|---|---|---|
! | Untereintrag, bis zu drei Ebenen | \index{animals!cats} |
@ | Sortierschlüssel: trennt Ordnung von Ausgabe | \index{alpha@$\alpha$} |
|( |) | Seitenbereich öffnen und schließen | \index{recursion|(} … \index{recursion|)} |
|cmd | Diese Seitenzahl mit einem Befehl setzen (fett, …) | \index{cat|textbf} |
|see |seealso | Statt einer Seitenzahl auf einen anderen Eintrag verweisen | \index{dog|see{pets}} |
" | Das folgende Sonderzeichen wörtlich nehmen | \index{C"!} ergibt „C!“ |
makeindex ausführen: von .idx nach .ind – und No file mydoc.ind.
Ein Index wird nicht in einem Lauf fertig. Wie bei bibtex handelt es sich um drei Stufen mit einem externen Programm in der Mitte. Zuerst sammelt LaTeX die \index-Aufrufe in mydoc.idx – eine schlichte Datei aus Zeilen der Form \indexentry{Begriff}{Seite}, die sich öffnen und lesen lässt. Dann sortiert makeindex sie zu einem satzfähigen mydoc.ind. Ein weiterer LaTeX-Lauf lässt schließlich \printindex die Datei mydoc.ind einlesen, und der Index erscheint im Dokument. Ein Protokoll des Sortierens bleibt in mydoc.ilg zurück – dorthin schaut man, wenn die Syntax eines Eintrags falsch war.
pdflatex mydoc # writes mydoc.idx ("Writing index file mydoc.idx")
makeindex mydoc # mydoc.idx -> mydoc.ind, log in mydoc.ilg
pdflatex mydoc # \printindex reads mydoc.ind
# -s picks a style file, -o names the output, -t names the log
makeindex -s style.ist -o mydoc.ind -t mydoc.ilg mydoc.idxVergisst man den mittleren Schritt, fällt das Symptom erstaunlich leise aus: kein Fehler, keine Warnung, nur diese eine Zeile im Log – No file mydoc.ind.. Der Grund liegt im Mechanismus selbst, denn \printindex läuft auf einen Aufruf von \@input@ hinaus, der die Datei einliest, sofern sie existiert, und andernfalls genau diese Zeile ausgibt. Wegen dieser Stille kann ein Dokument tadellos aussehen, obwohl der gesamte Index fehlt. In der Praxis erledigt latexmk den Umlauf allerdings selbsttätig: Es ruft makeindex auf, sobald sich .idx ändert, und startet LaTeX so oft wie nötig – die drei Schritte von Hand tippt man also immer seltener.
Warum „Ångström“ hinter „Zulu“ landet: wie makeindex sortiert
Sortiert wird von makeindex nicht das sichtbare Wort, sondern der Sortierschlüssel – und ohne @ ist der Schlüssel schlicht der Eintragstext. Die Standardordnung ist dokumentiert: Symbole, dann Zahlen, dann Buchstaben, wobei Buchstaben zunächst ohne Rücksicht auf Groß- und Kleinschreibung verglichen werden und Großbuchstaben nur bei sonst identischer Schreibung vorangehen. Als Entwurf für das Englische ist das völlig ausreichend. Das Problem ist der Umfang von „Buchstaben“: Für makeindex sind das nur das englische Alphabet und die Ziffern. Übergibt man Ångström und émile unverändert an makeindex 2.17 aus TeX Live 2024, landen sie nicht unter A und E, sondern ganz am Ende des Index, hinter Zulu.
# entries written with no sort key at all:
# +plus 9nine apple sea lion seal Zulu Angstrom emile
# (the last two really spelled Ångström and émile)
makeindex mydoc # default: word ordering
+plus / 9nine / apple / sea lion / seal / Zulu / Ångström / émile
makeindex -l mydoc # letter ordering: blanks do not count
+plus / 9nine / apple / seal / sea lion / Zulu / Ångström / émile
# the fix is an ASCII sort key, not an accented one:
# \index{Angstrom@Ångström} files under A
# \index{emile@émile} files under EDaraus folgt zweierlei. Erstens: Akzentuierte Wörter bekommen einen ASCII-Sortierschlüssel. \index{Angstrom@Ångström} druckt weiterhin Ångström, sortiert es aber unter A ein. Ein verbreitetes Missverständnis ist, \index{Ångström@Ångström} würde etwas ändern – tut es nicht, denn die Schlüsselseite bleibt nicht-ASCII. Zweitens bietet makeindex eine Wahl der Ordnung. Voreingestellt ist die Wortordnung, in der ein Leerzeichen vor jedem Buchstaben steht, sodass „sea lion“ vor „seal“ erscheint. Mit -l gilt die Buchstabenordnung, in der Leerzeichen gar nicht zählen und „seal“ vorangeht. Für ein wörterbuchartiges Verzeichnis nimmt man -l, für Telefonbuchstil die Voreinstellung. Fürs Deutsche gibt es zudem -g nach DIN 5007.
Enthält ein Dokument so viele Akzente, dass handgeschriebene Sortierschlüssel unrealistisch werden, ist es schneller, das Sortierprogramm selbst zu wechseln. xindy – von LaTeX aus über texindy erreichbar – ist um mehrsprachige Kollation herum gebaut und wird mit TeX Live ausgeliefert. Dasselbe Ångström an texindy -L english -C utf8 übergeben, und es steht ganz ohne Sortierschlüssel korrekt zwischen abacus und zebra, also unter A. Je umfangreicher der Index, desto günstiger ist der Wechsel des Kollators gegenüber dem Tippen von Schlüsseln.
Japanische Indizes: mendex und upmendex
Die Überlegung des vorigen Abschnitts gilt unverändert für Japanisch und Chinesisch, und das Symptom fällt schlimmer aus. Übergibt man \index{群}, \index{環} und \index{体} an makeindex, erscheinen sie in Zeichencode-Reihenfolge, ohne eine einzige Warnung – eine Ordnung, die mit der Lesung der Wörter nichts zu tun hat. Da nichts fehlschlägt, kann ein Index, der nach der Silbenordnung laufen sollte, in gar keiner Ordnung enden. Die Antwort lautet hier wie schon bei hyperref: das eigens gebaute Werkzeug einsetzen – mendex für pLaTeX, upmendex für upLaTeX und LuaLaTeX. Beide sind makeindex-kompatibel; es genügt, das bislang getippte Wort zu ersetzen.
Gewonnen wird die Sortierung nach Lesung. Zur makeindex-Zeit musste jedem Eintrag die Lesung als Lesung@Anzeige mitgegeben und Trübungszeichen von Hand normalisiert werden. upmendex nutzt die Kollation von ICU (International Components for Unicode), um Kana korrekt zu ordnen, und nimmt damit einen Großteil dieser Arbeit ab. Darüber hinaus registriert eine mit -d übergebene Wörterbuchdatei Lesungen gebündelt, sodass Einträge die @-Lesung häufig ganz auslassen können. Als Faustregel: mendex bei pLaTeX, upmendex bei upLaTeX und LuaLaTeX; Lesungen über @ funktionieren in beiden.
uplatex mydoc # writes mydoc.idx
upmendex -s style.ist mydoc # kana sorted via ICU -> mydoc.ind
uplatex mydoc # \printindex reads mydoc.ind
# readings can still be given by hand with @, in either program:
# \index{さくいん@索引}
# \index{Knuth@クヌース}Das Aussehen des Index ändern: die .ist-Stildatei
Das Aussehen eines Index bestimmt eine Stildatei (.ist), die mit -s übergeben wird, etwa makeindex -s style.ist mydoc. Ihr Format ist schlicht: eine Liste von Parameter Wert-Paaren, Zeichenketten in doppelten Anführungszeichen, % leitet einen Kommentar bis zum Zeilenende ein. Was dort steht, weist makeindex an, nicht LaTeX, und legt den Inhalt der .ind-Datei unmittelbar fest. Stile für mendex und upmendex sind aufwärtskompatibel zu makeindex, eine vorhandene .ist lässt sich also unverändert weiterverwenden.
headings_flag– ungleich null gesetzt, wird bei jedem Gruppenwechsel eine Gruppenüberschrift eingefügt (der Buchstabe A, B, … oder die Symbolgruppe); Standard 0.heading_prefix/heading_suffix– die Zeichenketten vor und nach dieser Überschrift.symhead_positive– die Überschrift der Symbolgruppe, wennheadings_flagpositiv ist (Standard "Symbols").delim_0/delim_1/delim_2– das Trennzeichen zwischen einem Eintrag der jeweiligen Ebene und seinen Seitenzahlen (Standard jeweils ", "); hier steht auch ein Punktführer.item_0/item_1/item_x1– die Zeichenketten zwischen Einträgen und zwischen Ebenen (Zeilenumbrüche, Einzüge).preamble/postamble– der Code am Anfang und Ende der.ind-Datei (standardmäßig\begin{theindex}und\end{theindex}).group_skip– der Abstand an einer Gruppengrenze (standardmäßig\indexspace).
% group headings in bold, and a dotted leader before the page number
headings_flag 1
heading_prefix "{\\bfseries "
heading_suffix "}\\nopagebreak\n"
delim_0 "\\dotfill "Der moderne Weg: imakeidx und mehrere Indizes
imakeidx tritt an die Stelle von makeidx und bringt zwei gewichtige Vorteile. Erstens ruft es das Indexprogramm während des Kompilierens selbsttätig auf, sodass sich ein Index fast wie das Inhaltsverzeichnis verhält. Zweitens unterstützt es mehrere Indizes in einem Dokument – etwa ein Sach- und ein Namenregister. Konfiguriert wird über Optionen an \makeindex: name= unterscheidet einen Index, title= setzt dessen Überschrift, intoc nimmt ihn ins Inhaltsverzeichnis auf, program= wählt das Sortierprogramm (makeindex, xindy, texindy oder mendex / upmendex fürs Japanische) und options= reicht Argumente wie -s style.ist durch. Pro Index ein \makeindex, im Text die Zuordnung über \index[name]{…}, die Ausgabe über \printindex[name].
Der automatische Aufruf beruht auf Shell Escape, und genau das hängt von der Umgebung ab. In der Standardkonfiguration von TeX Live 2024 steht makeindex auf der Positivliste des eingeschränkten Shell Escape, sodass imakeidx den Index auch ohne -shell-escape erzeugt (mit kpsewhich -var-value shell_escape_commands lässt sich die eigene Liste einsehen). xindy, texindy, mendex und upmendex stehen nicht darauf und brauchen daher -shell-escape. Wo Shell Escape gänzlich untersagt ist – manche Einreichungssysteme, strenge CI –, entfällt der automatische Aufruf; dann greift man auf den dreistufigen Ablauf mit eigenem makeindex-Aufruf zurück oder überlässt die Sache latexmk.
\documentclass{article}
\usepackage{imakeidx}
% two indexes, built during the compilation
\makeindex[name=subject, title=Subject index, intoc]
\makeindex[name=people, title=Index of names, intoc,
options={-s style.ist}]
\begin{document}
Groups\index[subject]{group} matter here.
Knuth\index[people]{Knuth, Donald} wrote TeX.
\printindex[subject]
\printindex[people]
\end{document}
% makeindex runs under restricted shell escape:
% pdflatex mydoc
% xindy / mendex / upmendex need the full permission:
% lualatex -shell-escape mydoc