An index — the alphabetised list of terms and page numbers at the back of a book — is built for you by LaTeX, as long as you mark the terms in the text. Three pieces do it: declare \makeindex in the preamble, drop \index{…} at each point you want indexed, and call \printindex where the list should appear. The catch is that the sorting is done not by LaTeX itself but by a separate program, makeindex (mendex / upmendex for Japanese) — so, like bibtex, it needs an extra pass. This page walks from the opening declarations through entry syntax (! subentries, @ sort keys, | page encapsulation), the build process, Japanese sorting, style tuning, and the modern imakeidx package.
The four pieces of an index
The standard indexing commands come from the **makeidx package. Load it in the preamble and then declare \makeindex**; from that point LaTeX writes your index entries out to a separate file (.idx). All that remains is to mark the terms and say where the list should print.
\usepackage{makeidx}** — loads the indexing commands (preamble).\makeindex** — the declaration that turns index collection on (preamble). Without it,\indexis silently ignored.\index{entry}** — the mark you place in the body where a term appears. Nothing is printed there; only the current page number is recorded.\printindex** — the command that actually typesets the finished index, usually placed at the end of the document.
The key idea is that \index is an invisible marker. You still write the word in the body yourself and add \index{…} right after it (random numbers\index{random numbers} are used). The page number of the spot you marked is what gets recorded for that entry.
Writing index entries
The argument of \index has its own little syntax for subentries, sort keys, page ranges, page-number formatting, and cross-references. These rely on four special characters interpreted by makeindex (not by LaTeX): !, @, |, and ".
**Subentries (!).** An exclamation point separates levels. \index{animals!cats} makes a main entry “animals” with a subentry “cats” under it. Repeating ! nests up to three levels deep (deeper still with the mendex / upmendex family).
**Sort key (@).** Written sortkey@display, this separates the string used for sorting from the string actually printed. It is essential for symbols and math, which do not sort by their glyph. \index{alpha@$\alpha$} prints α in the index but files it under “alpha.” In Japanese it supplies the reading of kanji (\index{さくいん@索引}).
**Page ranges (|( … |)).** When a topic spans several pages, mark the start with |( and the end with |) to get a range like 12–15. Open with \index{recursion|(} and close it later with \index{recursion|)}.
**Page-number encapsulation (|). Put a vertical bar followed by the name of a one-argument command**, and that page number alone is formatted with it. \index{cat|textbf} makes the page where the term is defined bold; \index{group|textit} makes it italic. Your own command names work too.
**Cross-references (|see / |seealso).** Again after a bar, you can emit a pointer to another entry instead of a page number. \index{dog|see{pets}} yields “dog, *see* pets”; |seealso{…} gives “*see also*.”
**Printing the special characters literally (").** To put !, @, |, or " into an entry as ordinary characters, precede each with a double quote. For example \index{C"!} makes the entry “C!”.
| Symbol | Role | Example |
|---|---|---|
! | Subentry (nesting) | \index{animals!cats} |
@ | Sort key (controls ordering) | \index{alpha@$\alpha$} |
|( |) | Open / close a page range | \index{recursion|(} … \index{recursion|)} |
|cmd | Format the page number (bold, etc.) | \index{cat|textbf} |
|see | “see” cross-reference | \index{dog|see{pets}} |
" | Print the next special char literally | \index{C"!} |
The build process (running makeindex)
An index is not finished in a single compile. Like bibtex, it is a three-stage process with a separate program in the middle. First, running LaTeX collects the \index calls into a raw file, file.idx. Next, the **makeindex** program sorts and formats that into file.ind (a typesettable index). Finally, running LaTeX once more lets \printindex read file.ind so the index appears in the document. A processing log is left in file.ilg.
\documentclass{article}
\usepackage{makeidx}
\makeindex
\begin{document}
METAFONT\index{METAFONT} は字形を、TeX\index{TeX} は組版を担う。
ここでは乱数\index{乱数|textbf} の生成を扱い、
群\index{group@群} と環\index{ring@環} にも触れる。
アルゴリズム\index{algorithm|(} の説明はここから始まり…
% (数ページ後)
…アルゴリズム\index{algorithm|)} の説明はここで終わる。
\printindex
\end{document}From the command line you run it like this. -s selects a style file, -o names the output, and -t names the log (omit them and only the extension changes).
pdflatex mydoc # writes mydoc.idx
makeindex mydoc # mydoc.idx -> mydoc.ind (log in mydoc.ilg)
pdflatex mydoc # \printindex reads mydoc.indThe whole sequence is **handled automatically by latexmk**: it calls makeindex whenever the .idx changes and re-runs LaTeX the right number of times, so you need not invoke the three steps by hand.
Japanese indexes (mendex / upmendex)
Because makeindex assumes Western alphabetical order, Japanese indexes use **mendex (with pLaTeX) or upmendex** (with upLaTeX / LuaLaTeX, Unicode-aware). Both are makeindex-compatible — you simply call them where you would have called makeindex.
uplatex mydoc # writes mydoc.idx
upmendex -s style.ist mydoc # sorts kana correctly -> mydoc.ind
uplatex mydoc # \printindex reads mydoc.indThe big win is kana sorting. With makeindex, ordering entries in Japanese syllabary order meant giving each one a hiragana/katakana reading as reading@display and normalising voiced marks by hand. upmendex sorts kana correctly and automatically using ICU (International Components for Unicode), removing much of that labour. Supplying a dictionary file with -d registers readings for kanji words in bulk, so you can often skip the @ readings entirely.
Rule of thumb: mendex for pLaTeX, upmendex for upLaTeX / LuaLaTeX. Supplying readings via @ works in both (\index{さくいん@索引}).
Changing the index style (.ist)
The look of the index is controlled by a **style file (.ist)**, passed with -s as in makeindex -s style.ist file. It is just a list of <parameter> <value> pairs — strings in double quotes, % starts a comment (mendex / upmendex styles are upward-compatible with makeindex).
headings_flag— set nonzero to insert a group heading** (the leading letter, e.g.A,B… or kana groups) before each new group.lethead_prefix/lethead_suffix** — strings placed before and after that heading.delim_0/delim_1/delim_2— the delimiter** between an entry (at each level) and its page number (e.g.", "or a dotted leader).item_0/item_1** — strings inserted between entries and between levels (line breaks, indentation).preamble/postamble** — code emitted before and after the whole index.
For nothing more than group headings, a small .ist like this is enough.
% style.ist
headings_flag 1
heading_prefix "{\\bfseries "
heading_suffix "}\\nopagebreak\n"
delim_0 "\\dotfill "The modern way: imakeidx
imakeidx extends makeidx and brings two big advantages. First, it runs makeindex automatically** during compilation: launch LaTeX with -shell-escape (permission to run external programs) and the index is built much like the table of contents, with no manual pass. Second, it supports multiple indexes in one document (e.g. a name index and a subject index).
You configure it by passing options to \makeindex. name= distinguishes an index, title= sets its heading, intoc lists it in the table of contents, program= chooses the sorting program (makeindex / xindy / texindy, or mendex / upmendex for Japanese), and options= passes arguments such as -s style.ist. Write several \makeindex calls for several indexes, then route entries with \index[name]{…} and print with \printindex[name].
\documentclass{article}
\usepackage{imakeidx}
% two indexes; built automatically with -shell-escape
\makeindex[name=subject, title=事項索引, intoc, program=upmendex]
\makeindex[name=people, title=人名索引, intoc, program=upmendex,
options={-s style.ist}]
\begin{document}
群\index[subject]{group@群} は重要だ。
クヌース\index[people]{Knuth@クヌース} が TeX を作った。
\printindex[subject]
\printindex[people]
\end{document}# auto-build: makeindex/upmendex is invoked for you
lualatex -shell-escape mydoc
lualatex -shell-escape mydoc # second pass resolves page numbersOnly xindy requires the *full* shell-escape, but auto-building at all needs -shell-escape. If you prefer, you can still call makeindex / mendex externally with imakeidx too. Where -shell-escape cannot be enabled (some web services, strict CI), the auto-build is unavailable — fall back to a manual pass or let latexmk handle it.