\documentclass[UTF8]{ctexart} \usepackage{etoolbox} \setmainfont[Ligatures=TeX]{CMU Serif} \setsansfont[Ligatures=TeX]{CMU Sans Serif} \setmonofont[Mapping=]{CMU Typewriter Text} \setCJKmainfont[BoldFont=FandolSong Bold,ItalicFont=FandolKai]{FandolSong} \newfontfamily\libertine{Linux Libertine O} \usepackage{pifont} \newcommand\gooditem{\item[\ding{51}]} \newcommand\baditem{\item[\ding{55}]} \usepackage[a4paper,centering,margin=1.2in]{geometry} \ctexset{section/format=\bfseries\Large} \usepackage[numbers,square,sort&compress]{natbib} \renewcommand\bibname{参考文档} \bibliographystyle{plainnat} \usepackage{tocbibind} \usepackage{ragged2e} \usepackage{booktabs} \usepackage{longtable} \usepackage{tabu} \usepackage{caption} \captionsetup[table]{font=small,position=top,skip=1ex} \usepackage{xcolor} \usepackage{makeidx} \makeindex % 索引项示例 \newenvironment{idxexample} {\newcommand{\sindex}{% \end{tabular}% & \begin{tabular}[t]{@{}l@{}}} \newcommand{\sitem}{\hspace*{20pt}} \newcommand{\ssitem}{\hspace*{30pt}} \begin{quote} \begin{tabular}{@{}l @{\quad{\color{gray}\vrule width .25em}\quad} l @{}} \begin{tabular}[t]{@{}l@{}}} { \end{tabular} \end{tabular} \end{quote}} \usepackage{fancyvrb} \fvset{formatcom=\xeCJKVerbAddon} \usepackage{shortvrb} \AtBeginDocument{ \MakeShortVerb\| \MakeShortVerb\" } \makeatletter \appto\@sanitize{% \@makeother\|% \@makeother\"} \def\useangles{% \@makeother\{% \@makeother\}% \catcode`\<=1% \catcode`\>=2} \def\restoreangles{% \@makeother\<% \@makeother\>% \catcode`\{=1% \catcode`\}=2} \let\org@wrindex\@wrindex \let\rawindex\index \patchcmd\rawindex{\@wrindex}{\org@wrindex} {} {\GenericWarning {\space\space\space\space} {hyperref index patch failed.}} \makeatother \usepackage{hyperref} \hypersetup{bookmarksnumbered,pdfstartview=FitH} \def\tableautorefname{表} \usepackage{xspace} \newcommand*\pkg[1]{\textsf{#1}\index{#1@\textsf{#1}}} \newcommand*\zhm{\pkg{zhmakeindex}\xspace} \newrobustcmd*\meta[1]{$\langle\textnormal{\itshape#1}\rangle$} \newcommand*\optional[1]{\textnormal{[}#1\textnormal{]}} \def\defchar#1{\begingroup\lccode`~=`#1\lowercase{\endgroup\def~}} \newenvironment{syntax}{% \quote\ttfamily \catcode`<\active \defchar<##1>{\meta{##1}} \catcode`[\active \defchar[##1]{\optional{##1}} }{\endquote} \newcommand*\optindex[1]{\index{选项!\texttt{#1}}} \newcommand*\optitem[1][]{\optindex{#1}\item[#1]} \newrobustcmd*\textkw[1]{\texttt{\scantokens{\catcode`\_=12 #1\endinput}}} \newcommand*\kwindex[1]{\index{#1@\textkw{#1}}} \newcommand*\kw[1]{\kwindex{#1}\textkw{#1}} \newcommand*\sort[1]{% \index{选项!\texttt{-z}!#1@\textkw{#1}}% \textkw{#1}} \newcommand\email{\nolinkurl} \InputIfFileExists{zhm-version}{}{% \def\zhmVersion{???}% \def\zhmRevision{???}} \title{\zhm\thanks{版本 \zhmVersion-\zhmRevision} 中文索引处理程序} \author{刘海洋} \date{2018 年 4 月 11 日} \begin{document} \maketitle \section{命令行} \index{命令行} \begin{syntax} \halign{#&#\hfil\cr zhmakeindex &[-c] [-i] [-o~] [-q] [-r] [-s~] [-t~]\cr &[-enc~] [-senc~] [-strict] [-z~]\cr &[ ...]\cr } \end{syntax} \section{简介} \zhm 是一个通用的中文多级索引处理程序,它从一个或多个输入文件读入索引项,将其 内容按指定的方式分组、排序,然后按格式将整理好的索引输出到文件。索引项可以有 3 个级别(0, 1, 2)的嵌套。\zhm 主要用于 \LaTeX{} 索引的处理,其功能和用法与 \pkg{makeindex}\cite{Chen1991} 相似,并支持中文的分组与排序。 \index{.idx@\verb+.idx+} \index{.ind@\verb+.ind+} 输入与输出文件的格式由一个格式文件确定。默认的输入/输出是 ".idx"/".ind" 格式 的,即 \LaTeX{} 格式的索引文件。 如果没有显式指定,第一个输入文件(\meta{idx0})的主文件名将用于确定输出和日志 文件的主文件名。对每个输入文件名 \meta{idx0}, \meta{idx1}, \ldots, \zhm 会首先 查找这个名字的文件;如果找不到且文件名没有后缀,则加上 ".idx" 后缀查找此文件; 如果还找不到文件,\zhm 则会中止。 \optindex{-s} \index{.mst@\verb+.mst+} 如果只有一个输入文件,并且没有显式用 "-s" 选项指定格式文件,\zhm 会使用后缀为 ".mst" 的默认格式文件(如果存在的话)。 关于如何使用 \pkg{makeindex} 在 \LaTeX{} 文档中处理索引,可以参考陈丕宏较早的 文档 \cite{Chen:1988:IPP},或 Lamport 的文档 \cite{Lamport1987}。\zhm 的在 \LaTeX 中的使用方法与 \pkg{makeindex} 基本一致。 \section{选项说明} \index{选项|(} \subsection{与 \pkg{makeindex} 相同的选项} \label{subsec:oldoption} \begin{description} \optitem[-c] 压缩索引项排序项前后的空格。默认情况下,排序项中的空格会被保留。 \optitem[-i] 从标准输入流("stdin")读入索引项。如果使用了该选项,并且没有使用 "-o" 选项,则排序后的索引将输出到标准输出流("stdout")。 \optitem[-o~\meta{ind}] 设置输出索引文件为 \meta{ind}。如果没有指定该选项,默认 的输出文件名是第一个输入文件 \meta{idx0} 的主文件名加上 ".ind" 的扩展名。 \index{.ind@\verb+.ind+} \optitem[-q] 静默模式,不向标准错误流("stderr")显示信息。默认情况下处理过程与 错误信息会同时在 "stderr" 与日志文件中输出。 \optitem[-r] 禁止隐式页码区间构造,要求页码区间必须使用显式区间符号生成。见 第~\ref{sec:idxsyntax} 节的说明。默认情况下,三个或三个以上连续的页码会自 动合并为一个页码区间(如 1--5)。 \optitem[-s~\meta{sty}] 设置 \meta{sty} 为格式文件。没有默认值。如果没有后 缀,会加上 ".ist" 后缀。\zhm 会首先在当前目录查找格式文件,如果找不到则调 用 \TeX{} 发行版的 \pkg{kpathsea} 库在 TEXMF 树中查找。 \index{.ist@\verb+.ist+} \optitem[-t~\meta{log}] 设置 \meta{log} 为日志文件。默认情况下,会使用第一个输 入文件 \meta{idx0} 的主文件名加上 ".ilg" 后缀作为日志文件。 \index{.ilg@\verb+.ilg+} \end{description} \subsection{\zhm 独有的选项} \label{subsec:newoption} \begin{description} \optitem[-enc~\meta{enc}] 设置输入输出文件的编码为 \meta{enc}。可选的编码包括 "UTF-8", "UTF-16", "GB18030", "GBK" 和 "Big5",不区分大小写。默认使用 UTF-8 编码。 \index{编码!UTF-8} \index{编码!UTF-16} \index{编码!GB18030} \index{编码!GBK} \index{编码!Big5} \optitem[-senc~\meta{senc}] 设置读入格式文件的编码为 \meta{senc}。可选的编码与 "-enc" 选项相同。默认使用 UTF-8 编码。 \optitem[-strict] 严格区分不同嵌入命令的页码。默认情况下,在页码区间处理时,会 将如果页码左区间的嵌入命令与右区间不匹配,会以左区间为准(部分 \LaTeX{} 文 档会生成右区间命令缺失的索引项);而如果使用 "-strict" 选项,则要求左右区 间的命令类型必须严格匹配。 \index{分组}\index{排序} \optitem[-z~\meta{sort}] 设置中文分组与排序方式为 \meta{sort}。可选的中文分 组排序方式包括 \sort{pinyin}/\sort{reading}, \sort{bihua}/\sort{stroke}, \sort{bushou}/\sort{radical}。默认值为 \sort{pinyin},即中文按拼音分组排 序。有关分组与排序的详细说明见第~\ref{sec:sort} 节。 \end{description} \subsection{未实现的选项} \label{subsec:unsupportedoption} \optindex{-g} \optindex{-l} \optindex{-p} \optindex{-L} \optindex{-T} \zhm 没有实现 \pkg{makeindex} 的 "-g", "-l", "-p", "-L", "-T" 选项。其中,选项 "-p" 依赖对 \TeX{} 编译的日志文件的解析,可能在未来版本实现;另外几个语言相关 的排序选项("-g" 德文,"-T" 泰文,"-L" 做系统 locale 选择,"-l" 有关西文单词排 序)对中文索引意义较小,不在 \zhm 中实现。 \index{选项|)} \section{索引项输入语法} \label{sec:idxsyntax} \zhm 输入索引项的语法与 \pkg{makeindex} 相同。下面以默认的格式输入设置(即在 \LaTeX{} 中使用)为例对索引项输入语法进行说明。 索引项文件是一个由多条索引项组成的文本文件,每行一条索引项,允许有空行,但索引 项不得跨行。 一个简单的索引项及其输出如 \begin{idxexample} "\indexentry{简介}{15}" \\ \sindex 简介, 15 \end{idxexample} 其语法为: \begin{syntax} "\indexentry{"<条目>"}{"<页码>"}" \end{syntax} 在 \LaTeX{} 中,"\indexentry" 项是在编译过程中自动生成的,实际生成上面例子的 \LaTeX{} 代码并不包括页码问题,只是在文档 15 页的源文件处输入 "\index{简介}" 即可得到这样的效果。关于 \pkg{makeindex} 在 \LaTeX{} 中的使用可以参考文档 \cite{Lamport1987,Chen:1988:IPP}。 \useangles \index<"{@\verb+"{+> \index<"}@\verb+"}+> \restoreangles "\indexentry" 是在索引输入文件中表示索引项的关键字。可以使用 \kw{keyword} 输入 格式进行修改(\autoref{tab:oldinputstyle})。左右花括号是界定 \meta{条目} 与 \meta{页码} 的标记,可以使用 \kw{arg_open}, \kw{arg_close} 输入格式修改 (\autoref{tab:oldinputstyle})。 \index{页码} \meta{页码} 是一个数字,可以使用阿拉伯数字、大小写罗马数字、大小写拉丁字母共 5 种格式。 \index{-@\verb+-+} 此外,与 \pkg{makeindex} 类似 \cite{Rodgers1991},\zhm 还支持多级页码。可以使 用 "-" 划分不同级别的复合页码。页码分隔符可由 \kw{page_compositor} 输入格式修 改,见 \autoref{tab:oldinputstyle}。例如: \begin{idxexample} "\indexentry{方程}{5-ii-2}" \\ "\indexentry{方程}{5-ii-1}" \\ "\indexentry{方程}{3-v-9}" \sindex 方程, 3-v-9, 5-ii-1, 5-ii-2 \end{idxexample} \meta{条目} 是 \zhm 需要处理的正文内容。最简单的条目就是一个普通的词条串,但也 可以有复杂的格式。 \index{"@@\verb+"@+} 如果对条目排序使用的串与用来输出条目的 \LaTeX{} 代码不一样,则可以把这两部分用 符号 "@" 分开,前面是排序的键,后面是输出的值。例如: \begin{idxexample} "\indexentry{Gamma 射线@$\Gamma$ 射线}{2}" \\ "\indexentry{粗体@\textbf{粗体}}{3}" \sindex \textbf{粗体}, 3 \\ $\Gamma$ 射线, 2 \end{idxexample} 分隔符 "@" 可通过修改格式文件的 \kw{actual} 项配置 (\autoref{tab:oldinputstyle})。 \index{"!@\verb+"!+} 索引项的条目可以分成至多三级,不同级别之间用符号 "!" 分开。例如 \begin{idxexample} "\indexentry{方程!解}{1}" \\ "\indexentry{方程!代数方程!线性方程}{2}" \\ "\indexentry{方程!代数方程!二次方程}{3}" \sindex 方程 \\ \sitem 代数方程 \\ \ssitem 二次方程, 3 \\ \ssitem 线性方程, 2 \\ \sitem 解, 1 \end{idxexample} 每一级别内部都可以分别指定排序的键与输出值,例如: \begin{idxexample} "\indexentry{射线!Gamma 射线@$\Gamma$ 射线}{8}" \\ "\indexentry{射线!X 射线}{9}" \sindex 射线 \\ \sitem $\Gamma$ 射线, 8 \\ \sitem X 射线, 9 \end{idxexample} 即分隔符 "!" 的优先级低于 "@"。分隔符 "!" 可通过修改格式文件的 \kw{level} 项配 置(\autoref{tab:oldinputstyle})。 \rawindex{"|@\verb+"|+|hyperpage} 索引项条目中也可以在最后指定页码的输出格式,用分隔符 "|" 与前面分开(用 \autoref{tab:oldinputstyle} 中的 \kw{encap} 项配置)。页码的输出格式由一个带单 个页码参数的 \TeX{} 命令决定,在输入索引项时这一特殊命令的反斜线 "\" 和左右花 括号被忽略,输出时会自动加上(用\autoref{tab:oldoutputstyle} 中的 \kw{encap_prefix}, \kw{encap_infix}, \kw{encap_suffix} 项配置)。例如: \begin{idxexample} "\indexentry{字体|emph}{2}" \sindex 字体, \emph{2} \end{idxexample} 它输出的代码实际上是 \begin{verbatim} 字体, \emph{2} \end{verbatim} \rawindex{"|@\verb+"|+|hyperpage} \index{"(@\verb+"(+} \index{")@\verb+")+} 除了指定页码输出格式的特殊命令,还可以指定页码范围,在分隔符 "|" 后、特殊命令 名前(如果有的话),使用开定界符 "(" 和闭定界符 ")",分别表示页码范围的起始和 结束。例如: \begin{idxexample} "\indexentry{方程|(}{5}" \\ "\indexentry{方程|)}{9}" \\ "\indexentry{函数!二次函数|(emph}{11}" \\ "\indexentry{函数!二次函数|)emph}{15}" \sindex 方程, 5--9 \\ 函数 \\ \sitem 二次函数, \emph{11--15} \end{idxexample} 页码范围的开闭定界符可由\autoref{tab:oldoutputstyle} 中的 \kw{range_open} 与 \kw{range_close} 项配置。 \index{""@\verb+""+} \index{转义符} 由于在索引条目中,"{", "}", "(", ")", "!", "@", "|" 等多种符号都有特殊意义,因 此引入引号 |"| 作为索引条目的转义符,引号及紧跟引号的字符都作为普通的单个后一 字符看待,不作为索引条目的特殊语法符号。例如: \begin{idxexample} |\indexentry{Aha"!}{1}| \\ \verb/\indexentry{绝对值 $"|x"|$}{2}/ \sindex Aha!, 1 \\ 绝对值 $\vert x\vert$, 2 \end{idxexample} 引号字符 |"| 可以由\autoref{tab:oldinputstyle} 中的 \kw{quote} 项配置。 \index{"\@\verb+"\+} \index{转义符} 使用转义符有一个例外,就是在反斜线后的引号 |\"| 被解释为普通 \TeX{} 命令 |\"|,这是因为 |\"| 经常被用于输入 G\"odel(|G\"odel|)这样的文字。注意这一例 外会影响 "\|" 等符号组合的输入。例如: \begin{idxexample} |\indexentry{G\"odel}{5}| \\ \verb/\indexentry{命令 \verb+"\"|+}{9}/ \sindex G\"odel, 5 \\ 命令 \verb+\|+, 9 \end{idxexample} 转义符 "\" 可以由\autoref{tab:oldinputstyle} 中的 \kw{escape} 项配置。 \section{格式文件} \label{sec:ist} \zhm 的格式文件与标准 \pkg{makeindex} 语法完全相同,内容也基本上相同,同时增加 了少量控制中文分组输出的格式。可以在 \zhm 中使用标准 \pkg{makeindex} 的格式文 件。 格式文件指明了 ".idx" 输入文件和最终输入文件的格式。该文件在当前工作目录或在 TEXMF 树中由 \pkg{kpathsea} 库查找。一个格式文件由一组 \meta{关键字} \meta{属 性} 的列表组成。\meta{关键字} 分为输出和输出两类。\meta{关键字} \meta{属性} 对 儿不要求以任何顺序出现。 \index{%@\verb+%+} \index{注释} 以字符 \verb"%" 开头的行是注释。 \index{字符串} \index{""@\verb+""+} \index{`@\verb+`+} \meta{属性} 可以有不同的类型,字符串是以任意双引号 |"| 或反引号 |`| 界定的串, \index{字符} \index{'@\verb+'+} 字符是以单引号 |'| 界定的单个字符,数字是一个整数。 \index{转义符} \index{"\@\verb+"\+} 其中,双引号和单引号界定的串和字符,可以使用反斜线 "\" 符号作为转义符,以得到 特殊字符或引号本身;而反引号界定的串是 \zhm 特有的功能,它不使用转义符。格式文 件中没有指定的项目会使用其默认值。 \subsection{与 \pkg{makeindex} 兼容的格式} \autoref{tab:oldinputstyle} 与\autoref{tab:oldoutputstyle} 的格式是在 \pkg{makeindex} 中有定义,同时也在 \zhm 中有支持的输入、输出格式。\zhm 的这部 分格式选项与 \pkg{makeindex} 意义相同,完全兼容。 \begin{longtabu*} to \linewidth{lll>{\RaggedRight}X} \caption{与 \pkg{makeindex} 兼容的输入格式}\label{tab:oldinputstyle} \\ \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \endfirsthead \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \endhead \bottomrule \endfoot \kw{keyword} & 字符串 & |"\\indexentry"| & 索引关键字 \\ \kw{arg_open} & 字符 & |'{'| & 参数的开定界符 \\ \kw{arg_close} & 字符 & |'}'| & 参数的闭定界符 \\ \kw{range_open} & 字符 & |'('| & 页码范围的开定界符 \\ \kw{range_close} & 字符 & |')'| & 页码范围的闭定界符 \\ \kw{level} & 字符 & |'!'| & 索引项层次分隔符 \\ \kw{actual} & 字符 & |'@'| & (区别于排序项的)实际输出项标志符 \\ \kw{encap} & 字符 & "'|'" & 页码和特殊命令指示符 \\ \kw{quote} & 字符 & |'"'| & 引号(转义符) \\ \kw{escape} & 字符 & |'\\'| & 转义 |quote| 的符号,在它后面的引号不作转义符 解释 \\ \kw{page_compositor} & 字符串 & |"-"| & 复合页码分隔符 \\ \end{longtabu*} \useangles\index<"{@\verb+"{+>\restoreangles \useangles\index<"}@\verb+"}+>\restoreangles \index{"(@\verb+"(+} \index{")@\verb+")+} \index{"!@\verb+"!+} \index{"@@\verb+"@+} \rawindex{"|@\verb+"|+|hyperpage} \index{""@\verb+""+} \index{"\@\verb+"\+} \index{-@\verb+-+} \begin{longtabu*} to \linewidth{lll>{\RaggedRight}X} \caption{与 \pkg{makeindex} 兼容的输出格式}\label{tab:oldoutputstyle} \\ \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \endfirsthead \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \endhead \bottomrule \endfoot \kw{preamble} & 字符串 & |"\\begin{theindex}\n"| & 索引导言代码\\ \kw{postamble} & 字符串 & |"\n\n\\end{theindex}\n"| & 索引末尾代码\\ \kw{group_skip} & 字符串 & |"\n\n \\indexspace\n"| & 组间垂直间距\\ \kw{headings_flag} & 数字 & |0| & 控制显示分组名标题的旗标\\ \kw{heading_prefix} & 字符串 & |""| & 分组名标题的前缀\\ \kw{heading_suffix} & 字符串 & |""| & 分组名标题的后缀\\ \kw{symhead_positive} & 字符串 & |"Symbols"| & 当旗标 |headings_flag| 为正数时,符号的标题\\ \kw{symhead_negative} & 字符串 & |"symbols"| & 当旗标 |headings_flag| 为负数时,符号的标题\\ \kw{numhead_positive} & 字符串 & |"Numbers"| & 当旗标 |headings_flag| 为正数时,数字的标题\\ \kw{numhead_negative} & 字符串 & |"numbers"| & 当旗标 |headings_flag| 为负数时,数字的标题\\ \kw{item_0} & 字符串 & |"\n \\item "| & 第 0 级条目间分隔\\ \kw{item_1} & 字符串 & |"\n \\subitem "| & 第 1 级条目间分隔\\ \kw{item_2} & 字符串 & |"\n \\subsubitem "| & 第 2 级条目间分隔\\ \kw{item_01} & 字符串 & |"\n \\subitem "| & 第 0/1 级条目间分隔\\ \kw{item_x1} & 字符串 & |"\n \\subitem "| & 第 0/1 级条目间分隔,其中第 0 级无页码\\ \kw{item_12} & 字符串 & |"\n \\subsubitem "| & 第 1/2 级条目间分隔\\ \kw{item_x2} & 字符串 & |"\n \\subsubitem "| & 第 1/2 级条目间分隔,其中第 1 级无页码\\ \kw{delim_0} & 字符串 & |", "| & 第 0 级条目与页码分隔\\ \kw{delim_1} & 字符串 & |", "| & 第 1 级条目与页码分隔\\ \kw{delim_2} & 字符串 & |", "| & 第 2 级条目与页码分隔\\ \kw{delim_n} & 字符串 & |", "| & 多个页码的分隔\\ \kw{delim_r} & 字符串 & |"--"| & 页码范围符号\\ \kw{delim_t} & 字符串 & |""| & 将插入到在页码列表末尾。如果页码列表为空,此项无 效果。 \\ \kw{encap_prefix} & 字符串 & |"\\"| & 页码特殊指令前缀\\ \kw{encap_infix} & 字符串 & |"{"| & 页码特殊指令中缀\\ \kw{encap_suffix} & 字符串 & |"}"| & 页码特殊指令后缀\\ \kw{page_precedence} & 字符串 & |"rnaRA"| & 不同类型页码的次序,默认值表示小写 罗马、阿拉伯数字、小写字母、大写罗马、大写字母\\ \kw{suffix_2p} & 字符串 & |""| & 在 2 页的页码范围中代替 |delim_r| 和第二个页码\\ \kw{suffix_3p} & 字符串 & |""| & 在 3 页的页码范围中代替 |delim_r| 和后面的页码\\ \kw{suffix_mp} & 字符串 & |""| & 在更多页的页码范围中代替 |delim_r| 和后面的页码\\ \end{longtabu*} \subsection{\zhm 特有的格式} \zhm 定义了新的输入格式(\autoref{tab:newinputstyle}),以支持索引输入的行 注释。 \begin{table}[htbp] \caption{\zhm 特有的输入格式}\label{tab:newinputstyle} \begin{tabu*} to \linewidth{lll>{\RaggedRight}X} \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \kw{comment} & 字符 & \texttt{'\textpercent'} & 行注释的开始符 \\ \bottomrule \end{tabu*} \index{%@\verb+%+} \index{注释} \end{table} \zhm 定义了一些新的输出格式(\autoref{tab:newoutputstyle}),用来控制按笔画数或 部首分组时,分组名的输出格式。 \begin{table}[htbp] \caption{\zhm 特有的输出格式}\label{tab:newoutputstyle} \begin{tabu*} to \linewidth{lll>{\RaggedRight}X} \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \kw{stroke_prefix} & 字符串 & |""| & 笔画数前缀 \\ \kw{stroke_suffix} & 字符串 & |" 画"| & 笔画数后缀 \\ \kw{radical_prefix} & 字符串 & |""| & 部首前缀 \\ \kw{radical_suffix} & 字符串 & |"部"| & 部首后缀 \\ \kw{radical_simplified_flag} & 数字 & 1 & 是否输出简化部首的标志 \\ \kw{radical_simplified_prefix} & 字符串 & |"("| & 简化部首前缀 \\ \kw{radical_simplified_suffix} & 字符串 & |")"| & 简化部首后缀 \\ \bottomrule \end{tabu*} \end{table} \subsection{未实现的 \pkg{makeindex} 格式} \autoref{tab:unsupportedoutputstyle} 中给出的是在标准的 \pkg{makeindex} 中定 义,但在 \zhm 中没有实现对应功能的格式。格式文件中如果出现这些格式,\zhm 将会 忽略它们。 \begin{table}[htbp] \caption{未实现的输出格式}\label{tab:unsupportedoutputstyle} \begin{tabu*} to \linewidth{lll>{\RaggedRight}X} \toprule 关键字 & 类型 & 默认值 & 意义 \\ \midrule \kw{setpage_prefix} & 字符串 & |"\n \\setcounter{page}{"| & 页码设置前缀\\ \kw{setpage_suffix} & 字符串 & |"}\n"| & 页码设置后缀\\ \kw{line_max} & 数字 & |72| & 最大行长度,超出长度会自动折行\\ \kw{indent_space} & 字符串 & |"\t\t"| & 自动折行的缩进\\ \kw{indent_length} & 数字 & |16| & |indent_space| 的长度\\ \bottomrule \end{tabu*} \end{table} \subsection{格式文件示例} 合法的 \pkg{makeindex} 格式文件都是合法的 \zhm 格式文件。\LaTeXe{} 的 \pkg{doc} 包附带的 \path{gind.ist} 和 \path{gglo.ist} 就是两个实际的例子。此 外,\pkg{makeindex} 手册页 \cite{Rodgers1991} 也给出了几个有用的例子。 下面是本文档使用的格式文件,注意其中反引号格式的串是 \zhm 特有的: \VerbatimInput[numbers=left]{zhmakeindex.mst} \section{排序细节} \label{sec:sort} \subsection{索引项分组} \optindex{-z} \zhm 与 \pkg{makeindex} 类似,主要是按第一级索引项的排序项的首个字符分组的。对 最普通的场景,西文是按单词的首字母分组,中文则根据 "-z" 选项 (\ref{subsec:newoption}~节)的不同,选择对应的分组,数字和其他符号单独分组。 \zhm 的前 28 个分组是固定的,分别是符号、数字,以及 A--Z 的 26 个拉丁字母。按 笔画排序时,后面是按总笔画数分组的汉字,共 64 组;按部首笔画排序时,后面是按康 熙字典部首分组的汉字,共 214 组。详细情况见\autoref{tab:group}。 \begin{table}[htbp] \caption{\zhm 支持的分组方式}\label{tab:group} \begin{tabu} to \linewidth{lll@{\qquad}>{\RaggedRight}X} \toprule "-z" 选项 & 别名 & 前 28 个分组 & 后面的分组 \\ \midrule \sort{pinyin} & \sort{reading} & 符号、数字、A, \ldots, Z & (无)\\ \sort{bihua} & \sort{stroke} & 符号、数字、A, \ldots, Z & 1 画、2 画、……、64 画(共 64 组) \\ \sort{bushou} & \sort{radical} & 符号、数字、A, \ldots, Z & 一部、丨部、……、龠部(共 214 组) \\ \bottomrule \end{tabu} \end{table} \zhm 主要是面向中文排版的索引处理,因此对于西文条目,只对没有重音等符号的拉丁 字母能进行正确的分组,对带重音符号的拉丁字母(如 é, ç)、非拉丁字母(如 Σ, Δ, Ж, Я 等)等则会一律按符号分组。 \index{数字} 如果索引项的第一级排序项全部由数字组成,则该项会被分入数字分组;但如果条目的首 个字符是数字,后面还有其他字符,则条目会被计入符号分组。除了阿拉伯数字,\zhm 还将其他 Unicode 数字符号(如罗马数字“{\libertine Ⅳ}”、带圈数字“{\libertine ⑧}”)也当作数字处理,但汉字 数码“〇”被看作汉字处理。 \index{〇} 当索引项第一级排序项的首个字符不是拉丁字母或汉字,排序项本身也不是纯数字时,则 此索引项就会计入符号分组。 当输出格式变量 \kw{headings_flag} 非零时(参见\autoref{tab:oldoutputstyle}), 将输出分组名称。\kw{headings_flag} 是正数时,以大写字母显示分组名 称;\kw{headings_flag} 是负数时,以小写字母显示分组名称。 当使用汉字特有的分组时,分组名称可以使用格式文件定制(参见% \autoref{tab:newoutputstyle})。按笔画分组时,分组名为 \begin{syntax} \kwindex{stroke_prefix} \kwindex{stroke_suffix} <笔画数> \end{syntax} 按康熙字典部首分组时,如果变量 \kw{radical_simplified_flag} 非零(默认情况), 则分组名由原康熙字典部首与简化字部首组合而成: \begin{syntax} \kwindex{radical_prefix} \kwindex{radical_suffix} \kwindex{radical_simplified_prefix} \kwindex{radical_simplified_suffix} <部首>\\ \hspace*{2em}<简化字部首> \end{syntax} 如果变量 \kw{radical_simplified_flag} 是零,则分组名没有简化字部首: \begin{syntax} \kwindex{radical_prefix} \kwindex{radical_suffix} <部首> \end{syntax} \subsection{索引项排序} 大体上,\zhm 逐字符按字典序对索引项的排序项进行排序,汉字与其他 Unicode 字符一 样,按单个字符比较。排序时使用的字符串比较有一些特殊规则: \begin{itemize} \item 如果字符串只包含阿拉伯数字,则首先按数字大小比较,数字相等时再按字典序 比较。 \item 以符号开头的字符串总是先于排在以数字开头的串(即使符号的 Unicode 码在 数字之后),而这又先于纯数字的排序项和以字母开头的串。 \item 在比较两个字符串时,\zhm 首先忽略字母大小写进行比较,如果此时结果相 等,再按区分大小写进行比较,将大写字母排在小写字母之前。 \end{itemize} \optindex{-l} \pkg{makeindex} 有一个 "-l" 选项忽略条目中的空格,按所有非空白符比较所有条目 (\ref{subsec:unsupportedoption}~节)。\zhm 未提供此功能。 \optindex{-z} 按 "-z" 选项(\ref{subsec:newoption}~节)的不同,汉字可以使用不同的排序方式, 如\autoref{tab:sort} 所示。 \begin{table}[htbp] \caption{\zhm 支持的中文排序方式}\label{tab:sort} \begin{tabu} to \linewidth{ll>{\RaggedRight}X} \toprule "-z" 选项 & 别名 & 意义 \\ \midrule \sort{pinyin} & \sort{reading} & 汉字按常用读音的拼音排序。 \\ \sort{bihua} & \sort{stroke} & 汉字按笔画数和笔顺排序。 \\ \sort{bushou} & \sort{radical} & 汉字按康熙字典部首和除部首笔画数排序。 \\ \bottomrule \end{tabu} \end{table} 使用读音排序时,没有读音数据的字符(包括生僻字)一律排在有读音的字符之前,汉字 按其最常用读音比较,读音相同汉字的按 Unicode 编码排序。使用笔画数和笔顺排序 时,笔画数小的排在前面,笔画数相同的,按横、竖、撇、点(捺)、折的顺序逐笔画比 较,仍然相同的按 Unicode 编码排序;生僻汉字没有笔顺信息的,排在同笔画数有笔顺 的字后面。使用部首和除部首笔画数排序时,部首按康熙字典 214 部首顺序排列,部首 和笔画数相同的按 Unicode 编码排序。 \subsection{页码排序与合并} \label{subsec:pagemerge} 内容完全相同而页码不同的索引项,会在排序时合并为一项。同一索引项的所有页码会按 前后次序排序、去重,并按要求合并为页码区间。 \index{数字} \index{页码} \zhm 能识别不同类型的页码格式,包括阿拉伯数字(1, 2, 3, \ldots)、大小写罗马数 字(I, II, III, \ldots)、大小写拉丁字母(a, b, c, \ldots)。不同类型的页码按 照 \kw{page_precedence} 变量的设置(\autoref{tab:oldoutputstyle})区分前后次序。 默认情况下,不同类型的页码次序是 "rnaRA",即小写罗马数字的页码排在最前,然后依 次是阿拉伯数字、小写拉丁字母、大写罗马数字、大写拉丁字母的页码。 目前,页码的类型判别比较粗糙,仅以页码的第一个字符判断类型。当页码以字母 "i", "v", "x", "l", "c", "d", "m" 起始时,即被识别为罗马数字,其他字母被识别为拉丁 字母页码。 \zhm 支持页码区间,在索引项中显式指定区间,如对输入 \begin{verbatim} \indexentry{foo|(}{5} \indexentry{foo|)}{10} \end{verbatim} 则 "foo" 项会输出页码 5--10。连续的区间、区间内的零散页码会被合并为一个大的区 间,如对输入 \begin{verbatim} \indexentry{foo|(}{5} \indexentry{foo}{6} \indexentry{foo|)}{10} \indexentry{foo|(}{11} \indexentry{foo|)}{13} \end{verbatim} 则 "foo" 项会输出页码 5--13。 \optindex{-r} 如果没有使用 "-r" 选项(\ref{subsec:oldoption}~节),零散的页码也会与区间一起 合并,3 页或以上连续的页码也会被合并为区间。例如输入 \begin{verbatim} \indexentry{foo}{i} \indexentry{foo}{ii} \indexentry{foo}{iii} \indexentry{foo|(}{5} \indexentry{foo|)}{7} \indexentry{foo}{8} \end{verbatim} 则 "foo" 项会输出页码 i--iii, 5--8。使用 "-r" 选项将禁止这种自动合并。 在排序合并页码时,\zhm 会区分不同数字类型的页码;如果页码还有特殊命令修饰,则 还会区分不同的修饰命令。例如输入 \begin{verbatim} \indexentry{foo}{1} \indexentry{foo|textit}{5} \indexentry{foo}{3} \indexentry{foo|textit}{7} \end{verbatim} 则 "foo" 项会分别以不同格式输出页码 1, 3, \textit{5}, \textit{7}。 在页码区间中如果出现不同类型的特殊命令修饰,则按不同的页码格式分别输出。但是, 为了适应部分 \LaTeX{} 代码不精确的页码输出,如果页码区间头与页码区间尾使用的特 殊命令不同,仍把它们看做相同的格式,按页码区间头的格式输出。例如输入 \begin{verbatim} \indexentry{foo|(textit}{1} \indexentry{foo|textbf}{5} \indexentry{foo|textit}{2} \indexentry{foo|)}{4} \end{verbatim} 则 "foo" 项会把页码 1, 2, 4 都归入区间 1--4,输出页码 \textit{1--4}, \textbf{5}。这也是 \pkg{makeindex} 默认效果。如果使用了 "-strict" 选项 (\ref{subsec:newoption}~节),则不再允许页码区间有不同的特殊命令修饰,而要求 格式严格匹配。"-strict" 选项适合用于不同格式页码区间相互交错的复杂的页码格式, 例如输入 \begin{verbatim} \indexentry{foo|(textit}{1} \indexentry{foo|(textbf}{5} \indexentry{foo|)textit}{8} \indexentry{foo|)textbf}{9} \end{verbatim} 则 "foo" 项会输出页码 \textbf{5--9}, \textit{1--8}。但如果不使用 "-strict" 选 项,或者使用 \pkg{makeindex},则无法正确识别这类页码区间。 \section{与 \pkg{makeindex} 的比较} \begin{itemize} \gooditem \zhm 支持 Unicode,所有字符按 Unicode 字符而非字节流处理。同时支持 输入输出文件、格式文件使用不同的中文编码(\ref{subsec:newoption}~节)。 \gooditem \zhm 支持中文特有的分组与排序方式(第~\ref{sec:sort} 节)。 \gooditem \zhm 与 \pkg{makeindex} 的页码合并算法不同 (\ref{subsec:pagemerge}~节),在页码区间有嵌套和交错,前后分界的格式不统一 时,\zhm 与 \pkg{makeindex} 可能会产生不完全相同的效果。如果使用 "-strict" 选项,\zhm 会使用更复杂的页码区间合并算法,能正确处理不同格式多层嵌套和互相 交错的页码区间,也能识别输入不正确的前后区间分界,而 \pkg{makeindex} 将给出 错误的结果。 \gooditem \zhm 的格式文件支持使用反引号界定的串,在其中禁用转义符 (第~\ref{sec:ist} 节)。 \gooditem \zhm 对输入的索引文件支持单个注释符开始的行注释。 \baditem \zhm 暂不支持 "-p" 选项自动获取 \TeX{} 编译日志文件中的页码,然后输出对 应的页码设置语句(\ref{subsec:unsupportedoption}~节、 \autoref{tab:unsupportedoutputstyle})。 \baditem \zhm 不支持 "-g", "-l", "-L", "-T" 等与中文索引无关的语言选项。 \baditem \zhm 不支持输出折行(\autoref{tab:unsupportedoutputstyle})。 \end{itemize} \section{已知问题} \index{多音字} 汉字按拼音分组排序时,多音字可能会被分到错误的分组或排在错误的位置。例如,“长 度”的“长”有 zhǎng 与 cháng 两个常用读音,由于读音 zhǎng 的使用频率比 cháng 略高一点,“长”字就会按 zhǎng 的读音分到 Z 组,排序也较为靠后。目前 \zhm 缺少一种通用的方式控制多音字按拼音分组与排序,只能暂时使用同音字处理此问 题。另外,部分汉字因为旧字形等问题,笔画数和笔顺也可能有多种选择,造成分组的分 歧。 \section{版权与许可} \index{版权}\index{许可} 版权所有:2014, 2015, 2016, 2018 年,刘海洋 \email{leoliu.pku@gmail.com} \index{LPPL} 本作品可在《the \LaTeX{} Project Public License》1.3 或更高版本的条件下发布与 修改。最新版本的 LPPL 许可证可以在 \begin{quote} \url{http://www.latex-project.org/lppl.txt} \end{quote} 下载;该许可证同时也包含在所有最新的 \LaTeX{} 发行版中。 本作品目前处于 LPPL 维护状态“maintained”。 当前维护者是刘海洋。 \index{源文件} 本作品包括 \zhm 的程序及文档,由如下源文件: \begin{verbatim} build-dist.cmd input.go install.cmd main.go MENIFEST numberedreader.go output.go pagenumber.go radical_collator.go reading_collator.go README sorter.go stroke_collator.go style.go style_test.go VERSION doc/make.cmd doc/zhmakeindex.bib doc/zhmakeindex.mst doc/zhmakeindex.tex examples/compositepage.idx examples/gb2312.idx examples/mixedpage.idx examples/numbers.idx examples/rangeencap.idx examples/suffix.ist examples/symorder.idx examples/zh.ist kpathsea/dynamic_other.go kpathsea/dynamic_windows_386.go kpathsea/kpathsea.go CJK/make-table.cmd CJK/maketables.go CJK/radicalstrokes.go CJK/strokes.go CJK/readings.go \end{verbatim} 以及编译源文件得到的二进制文件 \path{zhmakeindex.exe} 或 \path{zhmakeindex}、 PDF 文档 \path{zhmakeindex.pdf} 组成。 \index{Unicode} 大部分汉字数据来自 Unicode 项目(\url{http://www.unicode.org/})。 \index{海峰五笔} 部分字形数据来自海峰五笔项目(\url{http://okuc.net/sunwb/}): \begin{verbatim} maketables/sunwb_strokeorder.txt \end{verbatim} \bibliography{zhmakeindex} \printindex \end{document} vim:tw=78