索引,也就是书末按字母或假名顺序列出的术语和页码,只要在正文中标记术语,LaTeX 就能为你生成。关键有三步:在导言区声明 \makeindex,在需要编入索引的位置放置 \index{…},并在要输出列表的位置调用 \printindex。需要注意的是,排序不是由 LaTeX 本身完成,而是由 独立程序 makeindex(日文使用 mendex / upmendex) 负责,所以像 bibtex 一样需要额外一次处理。本页会依次介绍起始声明、条目语法(! 副条目、@ 排序键、| 页码封装)、构建流程、日文排序、样式调整,以及现代的 imakeidx 包。
索引的四个组成部分
标准索引命令由 makeidx 包提供。在导言区加载它,然后声明 \makeindex;从此以后,LaTeX 会把索引条目写入一个单独文件(.idx)。接下来只需要在正文中标记术语,并指定列表的输出位置。
\usepackage{makeidx}— 加载索引命令(导言区)。\makeindex— 开启索引收集的声明(导言区)。没有它,\index会被静默忽略。\index{entry}— 在正文中术语出现的位置放置的标记。那里不会打印任何内容,只记录当前页码。\printindex— 实际排版完成后索引的命令,通常放在文档末尾。
关键思想是,\index 是一个 不可见标记。词语本身仍要由你写在正文里,并在后面紧接 \index{…}(random numbers\index{random numbers} are used)。被标记位置的页码会记录到该条目下。
编写索引条目
\index 的参数有一套专用小语法,用来表示副条目、排序键、页码范围、页码格式和交叉引用。这些依赖四个由 makeindex(不是 LaTeX)解释的 特殊字符:!、@、| 和 "。
副条目(!)。 感叹号用来分隔层级。\index{animals!cats} 会创建主条目 “animals”,并在其下创建副条目 “cats”。重复 ! 最多可嵌套三层(mendex / upmendex 系列还能更深)。
排序键(@)。 写作 sortkey@display,可以 把用于排序的字符串与实际打印的字符串分开。符号和数学内容不会按字形自然排序,因此这点很关键。\index{alpha@$\alpha$} 会在索引中打印 α,但把它排在 “alpha” 的位置。日文中它用来给汉字提供 读音(\index{さくいん@索引})。
页码范围(|( … |))。 当某个主题跨越多页时,在开始位置标记 |(,在结束位置标记 |),即可得到类似 12–15 的范围。用 \index{recursion|(} 开始,之后用 \index{recursion|)} 关闭。
页码封装(|)。 在竖线后写上 接受一个参数的命令名,就只对该页码应用这个格式。\index{cat|textbf} 会把术语定义所在页码设为 粗体;\index{group|textit} 会设为斜体。自定义命令名也可以使用。
交叉引用(|see / |seealso)。 同样在竖线之后,可以输出指向另一个条目的提示,而不是页码。\index{dog|see{pets}} 会得到 “dog, *see* pets”;|seealso{…} 则表示 “*see also*”。
按字面打印特殊字符(")。 如果想把 !、@、| 或 " 作为普通字符放入条目,就在它前面加一个双引号。例如 \index{C"!} 会创建条目 “C!”。
| 符号 | 作用 | 示例 |
|---|---|---|
! | 副条目(嵌套) | \index{animals!cats} |
@ | 排序键(控制顺序) | \index{alpha@$\alpha$} |
|( |) | 打开/关闭页码范围 | \index{recursion|(} … \index{recursion|)} |
|cmd | 设置页码格式(粗体等) | \index{cat|textbf} |
|see | “see” 交叉引用 | \index{dog|see{pets}} |
" | 按字面打印下一个特殊字符 | \index{C"!} |
构建流程(运行 makeindex)
索引不会在一次编译中完成。和 bibtex 一样,它是中间夹着独立程序的三阶段流程。 首先运行 LaTeX,会把 \index 调用收集到原始文件 file.idx。接着 makeindex 程序把它排序并格式化成 file.ind(可排版的索引)。最后再运行一次 LaTeX,让 \printindex 读取 file.ind,索引就会出现在文档中。处理日志会留在 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}从命令行可以这样运行。-s 选择样式文件,-o 指定输出名,-t 指定日志名(省略时只替换扩展名)。
pdflatex mydoc # writes mydoc.idx
makeindex mydoc # mydoc.idx -> mydoc.ind (log in mydoc.ilg)
pdflatex mydoc # \printindex reads mydoc.ind整个流程可以由 latexmk 自动处理:当 .idx 更新时它会调用 makeindex,并按需要重新运行 LaTeX,因此无需手动敲三步。
日文索引(mendex / upmendex)
由于 makeindex 假定西文的字母顺序,日文索引使用 mendex(pLaTeX 系)或 upmendex(upLaTeX / LuaLaTeX 系,支持 Unicode)。两者都兼容 makeindex;只需在原本调用 makeindex 的位置调用它们。
uplatex mydoc # writes mydoc.idx
upmendex -s style.ist mydoc # sorts kana correctly -> mydoc.ind
uplatex mydoc # \printindex reads mydoc.ind最大的好处是 假名排序。使用 makeindex 时,要按五十音顺序排列条目,就必须为每个条目以 reading@display 的形式给出平假名/片假名读音,并手动统一浊点等。upmendex 使用 ICU (International Components for Unicode) 自动正确地排序假名,大大减少这项工作。再用 -d 提供 词典文件,就能批量登记汉字词读音,很多时候甚至可以完全省去 @ 读音。
经验法则:pLaTeX 用 mendex,upLaTeX / LuaLaTeX 用 upmendex。通过 @ 提供读音的方法在两者中都有效(\index{さくいん@索引})。
更改索引样式(.ist)
索引的外观由 样式文件(.ist) 控制,并像 makeindex -s style.ist file 这样通过 -s 传入。文件内容只是 <parameter> <value> 对的列表;字符串放在双引号中,% 之后是注释(mendex / upmendex 的样式与 makeindex 向上兼容)。
headings_flag— 设为非零时,在每个新组之前插入 组标题(开头字母,如A、B…,或假名组)。lethead_prefix/lethead_suffix— 放在该标题前后的字符串。delim_0/delim_1/delim_2— 条目(各层级)与页码之间的 分隔符(例如", "或点线引导)。item_0/item_1— 插入到条目之间和层级之间的字符串(换行、缩进)。preamble/postamble— 在整个索引前后输出的代码。
如果只是整理组标题的外观,像下面这样的小 .ist 就足够了。
% style.ist
headings_flag 1
heading_prefix "{\\bfseries "
heading_suffix "}\\nopagebreak\n"
delim_0 "\\dotfill "现代做法:imakeidx
imakeidx 是对 makeidx 的扩展,有两个重要优点。第一,它会在编译时 自动运行 makeindex:用 -shell-escape(允许执行外部命令)启动 LaTeX,索引就会像目录一样生成,无需手动处理。第二,它支持在一个文档中使用 多个索引(例如人名索引和主题索引)。
通过给 \makeindex 传递选项来配置它。name= 用来区分索引,title= 设置标题,intoc 将其列入目录,program= 选择排序程序(makeindex / xindy / texindy,日文可用 mendex / upmendex),options= 传递诸如 -s style.ist 的参数。写多个 \makeindex 就会得到多个索引,然后用 \index[name]{…} 分流条目,并用 \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 numbers只有使用 xindy 时才需要 *完整* shell-escape,但自动构建本身都需要 -shell-escape。如果愿意,使用 imakeidx 时仍然可以像传统方式那样从外部调用 makeindex / mendex。在无法启用 -shell-escape 的环境(某些 Web 服务、严格 CI)中,自动构建不可用;请退回手动处理或交给 latexmk。