% \iffalse meta-comment % % Copyright (C) 2014, 2017 by Leo Liu % --------------------------------------------------------------------------- % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Leo Liu. % % This work consists of the files seealso.dtx and seealso.ins % and the derived filebase seealso.sty. % % \fi % % \iffalse %<*driver> \ProvidesFile{seealso.dtx} % %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{seealso} %<*package> [2017/03/23 v1.2 makeidx's see and seealso with page number support.] % % %<*driver> \documentclass{ltxdoc} \usepackage[a4paper,left=2in,right=1in,top=1in,bottom=1in]{geometry} \newcommand\pkg[1]{\textsf{#1}} \usepackage[UTF8,hyperref]{ctex} \makeatletter \renewcommand\glossary@prologue{% \section*{版本历史} \markboth{版本历史}{版本历史}} \renewcommand\index@prologue{% \section*{Index / 代码索引} \markboth{Index / 代码索引}{Index / 代码索引} 斜体的数字表示对应项说明所在的页码。下划线的数字表示定义所在的代码行号;而直 立体的数字表示对应项使用时所在的行号。} \def\option{\begingroup \catcode`\\12 \MakePrivateLetters \option@} \let\endoption\endtrivlist \long\def\option@#1{\endgroup \topsep\MacroTopsep \trivlist \edef\saved@macroname{\string#1}% \def\makelabel##1{\llap{##1}}% \if@inlabel \let\@tempa\@empty \count@\macro@cnt \loop \ifnum\count@>\z@ \edef\@tempa{\@tempa\hbox{\strut}}\advance\count@\m@ne \repeat \edef\makelabel##1{\llap{\vtop to\baselineskip {\@tempa\hbox{##1}\vss}}}% \advance \macro@cnt \@ne \else \macro@cnt\@ne \fi \edef\@tempa{\noexpand\item[% \noexpand\PrintEnvName {\string#1}]}% \@tempa \global\advance\c@CodelineNo\@ne \SpecialMainOptionIndex{#1}\nobreak \global\advance\c@CodelineNo\m@ne \ignorespaces} \def\SpecialMainOptionIndex#1{\@bsphack \special@index{% #1\actualchar {\string\ttfamily\space#1} (option)% \encapchar main}% \@esphack} \def\SpecialOptionIndex#1{\@bsphack \begingroup \HD@target \let\HDorg@encapchar\encapchar \edef\encapchar usage{% \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage}}% \index{#1\actualchar{\protect\ttfamily#1} (option)\encapchar usage}% \index{options:\levelchar#1\actualchar{\protect\ttfamily#1}\encapchar usage}% \endgroup \@esphack} \def\DescribeOption{\leavevmode\@bsphack\begingroup\MakePrivateLetters \Describe@Option} \def\Describe@Option#1{\endgroup \marginpar{\raggedleft\PrintDescribeEnv{#1}}% \SpecialOptionIndex{#1}\@esphack\ignorespaces} \def\stylemeaning#1{\texttt{% \expandafter\expandafter\expandafter\strip@prefix \expandafter\meaning\csname seealso@#1\endcsname}} \renewcommand\author[2][]{% \ifstrempty{#1}{}{% \hypersetup{pdfauthor=#1}}% \def\@author{#2}} \renewcommand\title[2][]{% \ifstrempty{#1}{}{% \hypersetup{pdftitle=#1}}% \def\@title{#2}} \makeatother \usepackage{seealso} \usepackage{fancyvrb} \fvset{gobble=2} \usepackage{hypdoc} \hypersetup{pdfstartview=FitH} \AtBeginDocument{\MakeShortVerb\|} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{seealso.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{279} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v0.1}{2014/04/04}{初始版本。} % \changes{v1.0}{2014/04/05}{功能较完备的版本。} % % \DoNotIndex{\newcommand,\newenvironment,\^,\~,\@for,\@ifnextchar, % \@let@token,\@onlypreamble, \active, \AtBeginDocument,\begingroup,\catcode, % \csdef,\cslet,\cslet,\csuse, \DeclareBoolOption,\def,\define@key,\do, % \docsvlist, \dolistloop,\edef,\else, \emph,\empty,\endgroup,\expandafter, % \fi, \forcsvlist, \forlistcsloop, \forlistloop, \futurelet,\global, % \ifcsdef, \ifcsempty,\ifinlist,\ifinlistcs, \ifstrempty,\ifundef,\ifx, % \ignorespaces, \kvsetkeys,\lccode,\let, \listadd,\listbreak, \listcsgadd, % \lowercase,\newif, \next, \noexpand,\ProcessKeyvalOptions, \RequirePackage, % \reserved@a, \SetupKeyvalOptions,\space,\unexpanded,\unless} % % \GetFileInfo{seealso.dtx} % \title[The seealso Package (\fileversion)] % {\hypertarget{English}{The \pkg{seealso} Package (\fileversion)} % \makebox[0pt][l]{\hspace{3cm}\large % \hyperlink{Chinese}{$\Rightarrow$ \textsf{中文版}}}} % \author[Liú Hǎiyáng (Leo Liu) ] % {Liú Hǎiyáng (Leo Liu) \\ \nolinkurl{leoliu.pku@gmail.com}} % \date{\filedate} % % \maketitle % % \section{Introduction} % % When preparing index, the macros |\see| and |\seealso| defined by \LaTeXe's % standard package \pkg{makeidx} are handy to use. They are used as special % page format command, to present cross reference of index entry. For example, % if we use % \begin{Verbatim} % \index{math|see{mathematics}} % \end{Verbatim} % to reference the index entry ``mathematics'', we will get % \begin{quote} % math, \emph{see} mathematics % \end{quote} % in the output index. % % However, |\see| and |\seealso| commands in \LaTeXe{} cannot produce page % numbers. Moreover, if we use multiple |\see| or |\seealso|'s for one entry, % there will be multiple reference targets produced. Therefore we may get % this unexpected output: % \begin{quote} % math, \emph{see} mathematics, \emph{see} mathematics, \emph{see} mathematics % \end{quote} % if we have used \verb=\index{math|see{mathematics}}= at 3 different places % in the document. % % The \pkg{seealso} package solve the problem. If we use % \begin{Verbatim} % \usepackage{seealso} % \end{Verbatim} % all cross references of index entry will produce page numbers, and the % reference targets, which we call \emph{see list}, will be merged. The % previous example will produce an output like this: % \begin{quote} % math, \seepage{mathematics}{2}, \seepage{mathematics}{4}, \seepage{mathematics}{5} % \end{quote} % % \section{Reference} % % \subsection{Package Loading} % % The basic usage of the package is to simply load the package % \begin{Verbatim} % \usepackage{seealso} % \end{Verbatim} % then |\see| and |\seealso| commands will be redefined to support page number % output and reference target merging. % % The \pkg{seealso} package should be loaded after \pkg{makeidx}, % \pkg{imakeidx}, etc. Or the redefinition of |\see| and |\seealso| may be % broken. % % \subsection{Package Options} % % \DescribeOption{override} % |override| is a boolean option, with a default value |true|. When it is set % the original |\see| and |\seealso| will be overridden. However, when it is % set to be |false|, say % \begin{Verbatim} % \usepackage[override=false]{seealso} % \end{Verbatim} % then |\see| and |\seealso| will not be overridden, and |\seepage| and % |\seealsopage| should be used for page number output. % % \DescribeOption{activecr} % |activecr| is a boolean option, with a default value |true|. When it is set, % the see list will be output at the end of an index entry line (in a |.ind| % file). If we set |activecr=false|, however, the see list will not be output % automatically, one should use |\SeealsoPrintList| manually at the end of the % index entry instead. Usually |\SeealsoPrintList| is added via |delim_t| % style of Makeindex. % % \subsection{The \cs{see} and \cs{seealso} Commands} % % \DescribeMacro{\seepage} % \DescribeMacro{\seealsopage} % |\seepage| and |\seealsopage| provide the main functions of this package. % They provide the same faculty of cross reference, but output page numbers % and prevent redundancy. For example, suppose that there are % \begin{Verbatim} % \index{foo|seepage{bar}} % \end{Verbatim} % in page 1, 2, and 3, we will have a |.ind| file as below: % \begin{Verbatim} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{bar}{3} % \end{Verbatim} % And the output of the index will be: % \begin{quote} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{bar}{3} % \end{quote} % % It is possible to use different references for one index entry. For example % we can use % \begin{Verbatim} % \index{foo|seepage{bar}} % \end{Verbatim} % and % \begin{Verbatim} % \index{foo|seepage{foobaz}} % \end{Verbatim} % several times, the generated |.ind| file may be: % \begin{Verbatim} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{foobaz}{3} % \end{Verbatim} % And the output of the index will be: % \begin{quote} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{foobaz}{3} % \end{quote} % % \DescribeMacro{\seenopage} % \DescribeMacro{\seealsonopage} % The macros |\seenopage| and |\seealsonopage| save the original definitions % of |\see| and |\seealso| before loading \pkg{seealso}, which do not produce % page numbers. % % \DescribeMacro{\see} % \DescribeMacro{\seealso} % When option |override| is |true|, which is the default, |\see| and % |\seealso| works just as |\seepage| and |\seealsopage|. % % \DescribeMacro{\SeealsoPrintList} % |\seepage| and |\seealsopage| will collect the see lists, which will be % output at the end of the line under default |activecr| option. However, when % |activecr| is set to be |false|, the see lists won't be output at the end of % source line where |\seepage| and |\seealsopage| are. In the latter case, we % can add |\SeealsoPrintList| manually at the end of line to output the see % lists. Usually we can set |delim_t| variable in the style file of Makeindex, % for example: % \begin{Verbatim} % % example.ist % delim_t "\\SeealsoPrintList" % \end{Verbatim} % Then a |\SeealsoPrintList| will be appended at the end of every non-empty % index entry, and the see lists will be output properly. % % \DescribeMacro{\DeclareSeealsoMacro} % |\DeclareSeealsoMacro| can be used to define a new macro like |\see| and % |\seealso|. The syntax is % \begin{quote} % |\DeclareSeealsoMacro\|\meta{macro}|{|\meta{seelist}|}{|\meta{name}|}| % \end{quote} % where |\|\meta{macro} is the macro name, \meta{seelist} is the new see list, % and \meta{name} is the name of the see list to be output (like |\seename|). % Using |\DeclareSeealsoMacro|, two macros will be defined, the one is % |\|\meta{macro}, the other is |\|\meta{macro}|name|. If there has no % |\|\meta{macro}|name| predefined, it is defined to be \meta{name}, or the % definition remains unchanged. % % For example, |\seepage| and |\seealsopage| are defined like this: % \begin{Verbatim} % \DeclareSeealsoMacro\seepage{see}{see} % \DeclareSeealsoMacro\seealsopage{also}{see also} % \end{Verbatim} % The definitions above also provide the default value of |\seename| and % |\alsoname| to be |see| and |see also|, respectively. % % \subsection{Output Styles} % % \DescribeMacro{\seealsosetup} % The macro |\seealsosetup| is used to configure the output style of see % lists. The syntax is: % \begin{quote} % |\seealsosetup[|\meta{seelists}|]{|\meta{kv-options}|}| % \end{quote} % where \meta{seelists} is a comma separated list, each item of which is a see % list to be setup. \meta{seelists} can also be omitted or set to be empty, % which means we are setting up the default output style of all kind of see % lists. \meta{kv-options} is the options in key-value syntax. % % All possible output styles are summarized in table~\ref{tab:outstyleen}. % \begin{table}[htbp] % \centering % \begin{tabular}{lp{4cm}ll} % \hline % Key & Meaning & Argument & Default Value \\ % \hline % |name| & The name of see list to be output, e.g. |\seename| & none % & (invalid) \\ % |listsep| & The separator before a see list & none % & \stylemeaning{listsep} \\ % |itemsep| & The separator between see list items & none % & \stylemeaning{itemsep} \\ % |nameformat| & Output format of the see list name & |#1| % & \stylemeaning{nameformat} \\ % |itemformat| & Output format of the see list items & |#1| % & \stylemeaning{itemformat} \\ % |pageformat| & Output format of the page numbers & |#1| % & \stylemeaning{pageformat} \\ % \hline % \end{tabular} % \caption{Output styles used by \cs{seealsosetup}}\label{tab:outstyleen} % \end{table} % % For example, if we want to set all page numbers produced by |\seealsopage| % to be italic, we can use: % \begin{Verbatim} % \seealsosetup[also]{pageformat=\textit{#1}} % \end{Verbatim} % % Besides the output styles, |\seealsosetup| accepts |enditem| and |enditem+| % options, which is a list of token that determines whether to output the see % list at the end of line, if |activecr| option is true. The default value of % the list includes some common macros in |theindex| environment: % |\indexspace|, |\item|, |\subitem|, |\subsubitem|, and |\end|. For example, % if we have a special index which supports 4th level item |\subsubsubitem| % and a special space |\myindexspace|, we can use % \begin{Verbatim} % \seealsosetup{enditem+={\subsubsubitem,\myindexspace}} % \end{Verbatim} % to add the new macros to the list. % % \DescribeMacro{\SeealsoGobble} % |\SeealsoGobble| takes a character \meta{c} as argument. It checks the % following character, gobble it and ignore spaces if it is \meta{c}, or do % nothing if it is not \meta{c}. This macro is useful in |pageformat| style % to prevent outputting the page numbers, like this: % \begin{Verbatim} % \seealsosetup[see,also]{pageformat=\SeealsoGobble{,}} % \end{Verbatim} % % % \section{Known Issues} % % Here are some known problems and their solutions: % \begin{itemize} % \item % Since the output format of page numbers of |\seepage|, |\seealsopage| is the % same as normal page numbers, it may be ambiguous if we use normal |\index| % and \verb=\index{...|seepage}= simultaneously. Usually we should avoid using % different style of |\index| with or without |\seepage| and |\seealsopage|. % If it is impossible, we can set special page number format to identify them, % or we can use |\SeealsoGobble| to disable page numbers. % \end{itemize} % % % \clearpage % \title{\hypertarget{Chinese}{\pkg{seealso} 宏包 (\fileversion)} % \makebox[0pt][l]{\hspace{3cm}\large % \hyperlink{English}{$\Rightarrow$ \textsf{English Version}}}} % \author{刘海洋 \\ \nolinkurl{leoliu.pku@gmail.com}} % \date{\filedate} % % \maketitle % % \section{简介} % % 在索引生成时,\LaTeXe{} 的标准宏包 \pkg{makeidx} 定义了 |\see| 与 |\seealso| % 两个宏,它们通常是在 |\index| 中作为一种特殊的页码格式使用,表示索引项的引 % 用。例如使用 % \begin{Verbatim} % \index{math|see{mathematics}} % \end{Verbatim} % 会使索引项 math 引用到 mathematics。生成类似 % \begin{quote} % math, \emph{see} mathematics % \end{quote} % 的索引条目。 % % 不过,\LaTeXe{} 的 |\see| 与 |\seealso| 命令并不会为交叉引用的索引项输出页 % 码。更严重的问题是,如果对一个索引项使用了多次交叉引用,则会多次输出相同的目 % 标引用。因此可能出现这样的尴尬效果: % \begin{quote} % math, \emph{see} mathematics, \emph{see} mathematics, \emph{see} mathematics % \end{quote} % 其中可能在三个不同的地方使用了 \verb=\index{math|see{mathematics}}=。 % % \pkg{seealso} 宏包即为解决这种问题而编写。只要使用了 % \begin{Verbatim} % \usepackage{seealso} % \end{Verbatim} % 则交叉引用的索引项会同时显示页码,同时多个交叉引用的目标(我们称为\emph{参见 % 列表})会合并显示。前面的例子就可能会输出: % \begin{quote} % math, \seepage{mathematics}{2}, \seepage{mathematics}{4}, \seepage{mathematics}{5} % \end{quote} % 这样的格式。 % % \section{参考手册} % % \subsection{宏包载入} % % 基本的用法就是直接使用 % \begin{Verbatim} % \usepackage{seealso} % \end{Verbatim} % 这样 |\see| 和 |\seealso| 命令就会被重定义为支持输出页码和合并目标的格式。 % % 注意 \pkg{seealso} 宏包的载入应该晚于 \pkg{makeidx}、\pkg{imakeidx} 等定义 % |\see|、|\seealso| 的宏包,否则其功能将会失效。 % % \subsection{宏包选项} % % \DescribeOption{override} % |override| 是布尔型选项,默认为 |true|。表示覆盖已有的 |\see| 与 |\seealso| % 定义。如果设置 % \begin{Verbatim} % \usepackage[override=false]{seealso} % \end{Verbatim} % 则不对 |\see| 与 |\seealso| 覆盖,要使用 |\seepage| 和 % |\seealsopage| 命令调用相应的功能。 % % \DescribeOption{activecr} % |activecr| 是布尔型选项,默认为 |true|。表示打开在(|.ind| 文件中)索引项行 % 末自动输出所有参见列表的功能。如果设置 |activecr=false|,则必须手工(通常通 % 过设置 Makeindex 的 |delim_t| 格式)在索引项末加上 |\SeealsoPrintList| 输出 % 参见列表。 % % \subsection{\cs{see} 与 \cs{seealso} 命令} % % \DescribeMacro{\seepage} % \DescribeMacro{\seealsopage} % |\seepage| 与 |\seealsopage| 提供了宏包的主要功能,它们与原始的 % |\see|、|\seealso| 命令类似提供索引项的交叉引用功能,但同时会输出页码,并避 % 免重复输出交叉引用。例如,在文档中第 1, 2, 3 页分别多次使用 % \begin{Verbatim} % \index{foo|seepage{bar}} % \end{Verbatim} % 则在 |.ind| 文件中会生成: % \begin{Verbatim} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{bar}{3} % \end{Verbatim} % 而输出的结果将会是: % \begin{quote} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{bar}{3} % \end{quote} % % 同一个词可以有不同的参见引用项目,例如在不同的位置几次使用 % \begin{Verbatim} % \index{foo|seepage{bar}} % \end{Verbatim} % 和 % \begin{Verbatim} % \index{foo|seepage{foobaz}} % \end{Verbatim} % 则 |.ind| 文件中可能生成: % \begin{Verbatim} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{foobaz}{3} % \end{Verbatim} % 于是将得到输出结果 % \begin{quote} % foo, \seepage{bar}{1}, \seepage{bar}{2}, \seepage{foobaz}{3} % \end{quote} % % \DescribeMacro{\seenopage} % \DescribeMacro{\seealsonopage} % |\seenopage| 与 |\seealsonopage| 这两个宏则保存了在调用 \pkg{seealso} 宏包之 % 前,|\see| 与 |\seealso| 的原始定义,它们不会输出页码。 % % \DescribeMacro{\see} % \DescribeMacro{\seealso} % 在默认的 |override| 选项下,|\see| 与 |\seealso| 的功能与 % |\seepage|、|\seealsopage| 相同。 % % \DescribeMacro{\SeealsoPrintList} % |\seepage| 和 |\seealsopage| 会收集参见列表,在默认的 |activecr| 选项为 % |ture| 时会在行末自动输出。但如果 |activecr| 选项设置为 |false|,则 % |\seepage| 与 |\seealsopage| 所在行结束后不会自动输出参见列表。此时,可以手 % 工在此行最后加上 |\SeealsoPrintList| 宏,输出参见列表。通常可以在 Makeindex % 的格式文件中,输出格式选项 |delim_t| 里面加上 |\SeealsoPrintList| 宏,如: % \begin{Verbatim} % % example.ist % delim_t "\\SeealsoPrintList" % \end{Verbatim} % 这样,每个非空索引项输出的最后都会加上 |\SeealsoPrintList|,按需要输出参见列 % 表。 % % \DescribeMacro{\DeclareSeealsoMacro} % |\DeclareSeealsoMacro| 命令用于生成新的类似 |\see| 与 |\seealso| 的宏。其语 % 法为: % \begin{quote} % |\DeclareSeealsoMacro\|\meta{macro}|{|\meta{seelist}|}{|\meta{name}|}| % \end{quote} % 其中 |\|\meta{macro} 是新的宏名称,\meta{seelist} 是新的参见列表 % 名,\meta{name} 是输出参见列表时的名称。使用该命令会生成两个宏,一个是 % |\|\meta{macro},一个是对应的名称 |\|\meta{macro}|name|。 % |\|\meta{macro}|name| 如果事先没有定义,则定义其值为 \meta{name},否则保持不 % 变。 % % 例如,|\seepage| 和 |\seealsopage| 就是这样定义的: % \begin{Verbatim} % \DeclareSeealsoMacro\seepage{see}{see} % \DeclareSeealsoMacro\seealsopage{also}{see also} % \end{Verbatim} % 上述命令同时定义了 |\seename| 的备选值为 |see|,以及 |\alsoname| 的备选值为 % |see also|。 % % \subsection{格式设置} % % \DescribeMacro{\seealsosetup} % |\seealsosetup| 命令用于设置参见列表的输出格式。其语法为: % \begin{quote} % |\seealsosetup[|\meta{seelists}|]{|\meta{kv-options}|}| % \end{quote} % 其中,可选参数 \meta{seelists} 是一个逗号分隔的列表,每一项表示要设置其格式 % 的参见列表,如果不设置 \meta{seelists} 或设为空,则设置默认的输出格式。而选 % 项 \meta{kv-options} 则是输出格式项。 % % 可用的输出格式见表~\ref{tab:outstylezh}。 % \begin{table}[htbp] % \centering % \begin{tabular}{llll} % \hline % 选项 & 意义 & 参数 & 默认值 \\ % \hline % |name| & 输出参见列表的名称 & 无 & (不可用) \\ % |listsep| & 参见列表前的分隔符 & 无 & \stylemeaning{listsep} \\ % |itemsep| & 参见列表项间的分隔符 & 无 & \stylemeaning{itemsep} \\ % |nameformat| & 输出参见名“see also”的格式 & |#1| & \stylemeaning{nameformat} \\ % |itemformat| & 参见列表项的格式 & |#1| & \stylemeaning{itemformat} \\ % |pageformat| & 页码格式 & |#1| & \stylemeaning{pageformat} \\ % \hline % \end{tabular} % \def\tablename{表} % \caption{\cs{seealsosetup} 使用的输出格式}\label{tab:outstylezh} % \end{table} % % 例如,如果要让所有 |\seealsopage| 命令生成的页码以斜体显示,就可以使用 % \begin{Verbatim} % \seealsosetup[also]{pageformat=\textit{#1}} % \end{Verbatim} % % 除了输出格式,|\seealsosetup| 还接受 |enditem| 和 |enditem+| 选项,用于设置 % \pkg{seealso} 宏包在 |activecr| 选项设置时,进入行尾之后遇到什么记号时决定输 % 出参见列表。通常情况下并不需要设置该选项,|enditem| 选项的默认值已经包括了在 % 标准的 |theindex| 环境中会出现的一些宏:|\indexspace|、|\item|、|\subitem|、 % |\subsubitem|、|\end|。使用 |enditem+| 选项则可以向列表中增加新的记号。例 % 如,如果某种特殊的索引支持 4 级项 |\subsubsubitem| 和特殊的间隔 % |\myindexspace|,就可以使用 % \begin{Verbatim} % \seealsosetup{enditem+={\subsubsubitem,\myindexspace}} % \end{Verbatim} % 向列表中添加新的记号。 % % \DescribeMacro{\SeealsoGobble} % |\SeealsoGobble| 宏接受一个字符作为参数,它检查后面是否有此字符,如果是则吞 % 掉此字符及后面的空格,否则什么都不做。在 |pageformat| 选项中使用这个宏可以用 % 来禁止显示参见项的页码,像下面这样: % \begin{Verbatim} % \seealsosetup[see,also]{pageformat=\SeealsoGobble{,}} % \end{Verbatim} % % \section{已知问题} % % 以下是一些已知的问题和解决方案: % \begin{itemize} % \item % 由于 |\seepage|, |\seealsopage| 的页码显示形式与普通页码相同,所以可能会造成 % 页码重叠的情况。最好尽量避免交叉引用的项目有多种形式的索引。如果不能避免,为 % 解决此问题,可以设置特别的页码输出格式以示区分,或者借用 |\SeealsoGobble| 设 % 置不输出页码。 % \end{itemize} % % \StopEventually{} % % \clearpage % \section{Implementation / 代码实现} % % \iffalse %<*package> % \fi % % \subsection{准备工作} % % 引入相关编程工具。 % % \pkg{etoolbox} 是基本宏工具。原有的 \cs{ifinlist} 和 \cs{ifinlistcs} 不能用 % 于带花括号的文字的查找,会限制我们的使用。为此按 \pkg{etoolbox} 手册的建议, % 补充了 \cs{seealso@ifstrinlist} 和 \cs{seealso@ifstrinlistcs} 两个宏来在列表 % 中搜索字符串。它们会比 \cs{ifinlist} 与 \cs{ifinlistcs} 性能略差一点。 % \changes{v1.2}{2017/03/23}{允许 \cs{see} 等命令参数中带花括号。} % \begin{macrocode} \RequirePackage{etoolbox} % {}{}{}{} \long\def\seealso@ifinlist@#1#2#3#4{% \def\next{#4}% \def\do##1{% \ifstrequal{##1}{#2} {\def\next{#3}\listbreak} {}}% \dolistloop{#1}% \next} % {}{}{}{} \protected\long\def\seealso@ifinlist#1#2{% \seealso@ifinlist@{#2}{#1}} % {}{}{}{} \protected\long\def\seealso@ifinlistcs#1#2{% \expandafter\seealso@ifinlist@\csname #2\endcsname{#1}} % \end{macrocode} % % \pkg{kvoptions} 用于处理宏包选项。 % \begin{macrocode} \RequirePackage{kvoptions} \SetupKeyvalOptions{ family=seealso@opt, prefix=seealso@, setkeys=\kvsetkeys} % \end{macrocode} % % 声明宏包选项。 % % \begin{option}{override} % \changes{v1.0}{2014/04/05}{新增选项。} % 重定义 |\see| 与 |\seealso| 为有页码的形式。默认打开。 % \begin{macrocode} \DeclareBoolOption[true]{override} % \end{macrocode} % \end{option} % % \begin{option}{activecr} % \changes{v1.0}{2014/04/05}{新增选项。} % 使用换行符作为输出 |\see| 等命令的指令。默认打开。 % \begin{macrocode} \DeclareBoolOption[true]{activecr} % \end{macrocode} % \end{option} % % 执行选项。 % \begin{macrocode} \ProcessKeyvalOptions* % \end{macrocode} % % \begin{macro}{\seealso@charlet} % 参数 |#1| 是一个字符或 |\| 加字符的形式,|\seealso@charlet| 将此字符看做活动 % 字符的宏,使用 |\let| 与后面的内容赋值,但本身不改变字符的 catcode。 % \begin{macrocode} \def\seealso@charlet#1{% \begingroup\lccode`\~=`#1\lowercase{\endgroup\let~}} % \end{macrocode} % \end{macro} % % \subsection{参见列表及其实现} % % \begin{macro}{\seealso@macrolist} % 列表记录所有独立的类似 |\seepage| 的宏。默认只有 |see| 和 |also| 两组,对应 % 命令 |\seepage| 和 |\seealsopage|。 % \begin{macrocode} \let\seealso@macrolist\empty % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@clearlist} % 清空参见列表,如 |\seealso@see@list|、|\seealso@also@list|。 % \begin{macrocode} \def\seealso@clearlist#1{% \global\cslet{seealso@#1@list}\empty} \AtBeginDocument{\forlistloop\seealso@clearlist\seealso@macrolist} % \end{macrocode} % \end{macro} % % \begin{macro}{\SeealsoPrintList} % 输出参见列表,如 |\seealso@see@list|、|\seealso@also@list|。 % \begin{macrocode} \newcommand\SeealsoPrintList{% \forlistloop\seealso@printlist\seealso@macrolist \forlistloop\seealso@clearlist\seealso@macrolist} % \end{macrocode} % \end{macro} % % \begin{macro}{\ifseealso@gobblefirstlistsep} % 测试是否忽略第一个列表分隔符(因为前面使用了 |\SeealsoGobble|)。 % \begin{macrocode} \newif\ifseealso@gobblefirstlistsep % \end{macrocode} % \end{macro} % % \begin{macro}{\ifseealso@firstitem} % 测试是否是在输出参见列表的第一项。 % \begin{macrocode} \newif\ifseealso@firstitem % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@printlist} % 输出参见列表 |#1|。如果列表为空则无操作。 % \begin{macrocode} \def\seealso@printlist#1{% \ifcsempty{seealso@#1@list} {} {\ifseealso@gobblefirstlistsep \seealso@gobblefirstlistsepfalse \else \csuse{seealso@#1@listsep}% \fi \csuse{seealso@#1@nameformat}{\csuse{#1name}}% \seealso@firstitemtrue \forlistcsloop{\seealso@listitem{#1}}{seealso@#1@list}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@listitem} % 输出参见列表的一项。如果不是第一项,同时输出分隔符。 % \begin{macrocode} \def\seealso@listitem#1#2{% \ifseealso@firstitem \seealso@firstitemfalse \else \csuse{seealso@#1@itemsep}% \fi \csuse{seealso@#1@itemformat}{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\DeclareSeealsoMacro} % \changes{v1.0}{2014/04/05}{新增以定义新的参见命令。} % 定义一个新的带页码的参见命令。|#1| 是命令名,|#2| 是该命令使用的参见列 % 表,|#3| 是列表输出时使用的名字。 % \begin{macrocode} \newcommand\DeclareSeealsoMacro[3]{% % \end{macrocode} % 首先定义参见命令 |#1| 本身。 % \begin{macrocode} \newcommand#1[2]{% \seealso@setactivecr \seealso@ifinlistcs{##1}{seealso@#2@list} {} {\listcsgadd{seealso@#2@list}{##1}}% \csuse{seealso@#2@pageformat}{##2}}% % \end{macrocode} % 将参见命令加入列表。 % \begin{macrocode} \listadd\seealso@macrolist{#2}% % \end{macrocode} % 定义 |name| 选项,用来设置 |\|\meta{macro}|name|。如 |\seename| 和 % |\alsoname|。 % \begin{macrocode} \define@key{seealso@#2}{name}{% \csdef{#2name}{##1}}% % \end{macrocode} % 如果事先没有定义,则定义 |\|\meta{macro}|name| 为 |#3|。 % \begin{macrocode} \ifcsdef{#2name} {} {\kvsetkeys{seealso@#2}{name=#3}}% % \end{macrocode} % 定义无参选项。 % \begin{macrocode} \def\do##1{% \define@key{seealso@#2}{##1}{% \csdef{seealso@#2@##1}{####1}}% \kvsetkeys{seealso@#2}{##1=\csuse{seealso@##1}}}% \docsvlist{listsep,itemsep}% % \end{macrocode} % 定义有一个参数的选项。 % \begin{macrocode} \def\do##1{% \define@key{seealso@#2}{##1}{% \csdef{seealso@#2@##1}########1{####1}}% \kvsetkeys{seealso@#2}{##1=\csuse{seealso@##1}{####1}}}% \docsvlist{nameformat,itemformat,pageformat}} \@onlypreamble{\DeclareSeealsoMacro} % \end{macrocode} % \end{macro} % % \begin{macro}{\ifseealso@iscractive} % 判断当前换行符是否已经被激活。 % \begin{macrocode} \newif\ifseealso@iscractive % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@setactivecr} % |activecr| 选项为真时,设置换行符为 |\seealso@cr| 并激活。 % \begin{macrocode} \def\seealso@setactivecr{% \ifseealso@activecr \unless\ifseealso@iscractive \catcode`\^^M=\active \seealso@charlet\^^M\seealso@cr \seealso@iscractivetrue \fi \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@cr} % \changes{v1.1}{2014/04/07}{处理折行问题。} % 是在 |activecr| 选项下,换行符的定义。它检测后面的记号是否在 % |\seealso@enditemlist| 中,以判断是否处于折行状态,决定是否输出列表。 % \begin{macrocode} \def\seealso@cr{% \futurelet\next\seealso@cr@aux} % \end{macrocode} % |\seealso@cr@aux| 是实际完成判断折行与输出的辅助过程。如果折行,则补全折行造 % 成的空白;否则取消激活换行符为宏,并输出参见列表。 % \begin{macrocode} \def\seealso@cr@aux{% \seealso@testwrap \ifseealso@wrap \space \else \catcode`\^^M=5 \seealso@iscractivefalse \SeealsoPrintList \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\ifseealso@wrap} % 判断当前是否在折行的行尾。 % \begin{macrocode} \newif\ifseealso@wrap % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@testwrap} % 检查由 |\seealso@cr| 获取的下一记号 |\next| 是否在列表 % |\seealso@enditemlist| 中,确定当前是否在折行行尾。 % \begin{macrocode} \def\seealso@testwrap{% \seealso@wraptrue \forlistloop\seealso@testwrap@aux\seealso@enditemlist} \def\seealso@testwrap@aux#1{% \ifx#1\next \seealso@wrapfalse \expandafter\listbreak \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@enditemlist} % 表示索引项结束的记号列表。用于判断是否处于折行状态。 % \begin{macrocode} \let\seealso@enditemlist\empty % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@enditemlistadd} % 向结束记号列表中增加一项。 % \begin{macrocode} \def\seealso@enditemlistadd#1{% \seealso@ifinlist{#1}\seealso@enditemlist {} {\listadd\seealso@enditemlist{#1}}} % \end{macrocode} % \end{macro} % 下面定义结束记号列表的在 |seealso| 族下的键 |enditem| 与 |enditem+|,允许用 % 户自定义此列表。这里要求列表总包含 |\seealso@cr|。 % \begin{macrocode} \define@key{seealso}{enditem}{% \let\seealso@enditemlist\empty \listadd\seealso@enditemlist{\seealso@cr}% \forcsvlist\seealso@enditemlistadd{#1}} \define@key{seealso}{enditem+}{% \forcsvlist\seealso@enditemlistadd{#1}} % \end{macrocode} % 结束记号列表的默认值,除了 |\seealso@cr| 外,还包括通常在 |theindex| 等环境 % 中出现的其他一些宏。 % \begin{macrocode} \kvsetkeys{seealso}{% enditem={\indexspace,\item,\subitem,\subsubitem,\end}} % \end{macrocode} % % 下面定义参见列表的默认输出格式。以下宏给出的都是全局的默认值,可以单独修改每 % 一项的输出格式。 % \begin{macro}{\seealso@listsep} % 参见列表之前的分隔符。 % \begin{macrocode} \def\seealso@listsep{,\space} % \end{macrocode} % \end{macro} % \begin{macro}{\seealso@itemsep} % 参见列表项之间的分隔符。 % \begin{macrocode} \def\seealso@itemsep{,\space} % \end{macrocode} % \end{macro} % \begin{macro}{\seealso@nameformat} % 参见名“see also”的输出格式。 % \begin{macrocode} \def\seealso@nameformat#1{\emph{#1}\space} % \end{macrocode} % \end{macro} % \begin{macro}{\seealso@itemformat} % 参见列表项的输出格式。 % \begin{macrocode} \def\seealso@itemformat#1{#1} % \end{macrocode} % \end{macro} % \begin{macro}{\seealso@pageformat} % 参见页码的输出格式。 % \begin{macrocode} \def\seealso@pageformat#1{#1} % \end{macrocode} % \end{macro} % % \begin{macro}{\seealso@define@key} % \begin{macro}{\seealso@define@keyarg} % 定义 |seealso| 族的键,用于设置输出格式。 % \begin{macrocode} \def\seealso@define@key#1{% \define@key{seealso}{#1}{% \csdef{seealso@#1}{##1}}} \def\seealso@define@keyarg#1{% \define@key{seealso}{#1}{% \csdef{seealso@#1}####1{##1}}} % \end{macrocode} % \end{macro} % \end{macro} % 为每个输出格式定义键。 % \begin{macrocode} \forcsvlist\seealso@define@key{listsep,itemsep} \forcsvlist\seealso@define@keyarg{nameformat,itemformat,pageformat} % \end{macrocode} % % \begin{macro}{\SeealsoGobble} % \changes{v1.0}{2014/04/06}{支持吞掉分隔符的页码格式,即不显示页码。} % \changes{v1.1}{2014/04/07}{处理 \pkg{hyperref} 兼容性。} % \changes{v1.1}{2014/04/09}{不再要求设置 \texttt{listsep} 为空。} % 检查后面的字符是否 |#1|,如果是则吞掉分隔符 |#1| 及后面的空格。这个宏可用于 % 设置 |pageformat| 格式,吞掉一个类似 |,\space| 类型的分隔符。 % % 这里检查是否定义了 \pkg{hyperref} 的 |\hyperindexformat|(表示打开了索引的超 % 链接功能),如果有 |\hyperindexformat|,则需要调整参数次序以解决 % |\hyperindexformat| 与 |\see| 等命令嵌套的问题。 % \begin{macrocode} \AtBeginDocument{% \ifundef\hyperindexformat{% \let\SeealsoGobble\seealso@gobble }{% \def\SeealsoGobble#1{\seealso@swap{\seealso@gobble{#1}}}% \def\seealso@swap#1#2#3#4{#2#3#4#1}% }} % \end{macrocode} % \end{macro} % \begin{macro}{\seealso@gobble} % 实际的 |\SeealsoGobble| 命令,检查后面的字符是否 |#1|,如果是则吞掉分隔符 % |#1| 及后面的空格。 % \begin{macrocode} \def\seealso@gobble#1{% \@ifnextchar#1% {\seealso@gobbleignorespaces} % \end{macrocode} % 如果 |\SeealsoGobble| 后面即将输出,即为换行符或 |\SeealsoPrintList|,则决定 % 后面不再输出第一个参见列表的 |listsep|。 % \begin{macrocode} {\ifseealso@activecr \ifx\@let@token\seealso@cr \seealso@gobblefirstlistseptrue \fi \else \ifx\@let@token\SeealsoPrintList \seealso@gobblefirstlistseptrue \fi \fi}} % \end{macrocode} % \end{macro} % \begin{macro}{\seealso@gobbleignorespaces} % \changes{v1.1}{2014/04/08}{正确处理 \cs{SeealsoGobble} 在自动折行下的行为。} % 吞掉分隔符参数 |#1|(通常是一个逗号)并忽略后面的空格。 % % 为了处理折行时会遇到的换行符宏 |\seealso@cr|,在发现后面的参数是 % |\seealso@cr| 时就递归调用自身把 |\seealso@cr| 也清除掉。此时就好像直接把两 % 行连接起来,不再调用 |\seealso@cr| 的复杂判断流程。 % \begin{macrocode} \def\seealso@gobbleignorespaces#1{% \@ifnextchar\seealso@cr{\seealso@gobbleignorespaces}{\ignorespaces}} % \end{macrocode} % \end{macro} % % \subsection{定义用户接口} % % \begin{macro}{\seealsosetup} % \changes{v1.0}{2014/04/05}{新增格式设置。} % \changes{v1.1}{2014/04/09}{正确处理有参数的格式。} % 设置输出格式。可选参数是一个逗号列表:如果可选参数为空,用 |#2| 设置默认的输 % 出格式;否则对可选参数的每一项,设置参数 |#2| 的格式。为了避免因嵌套定义造 % 成使用时参数不得不使用双重 |##|,这里作了特别的展开处理。 % \begin{macrocode} \newcommand\seealsosetup[2][]{% \ifstrempty{#1}{% \kvsetkeys{seealso}{#2}% }{% \edef\do##1{% \noexpand\kvsetkeys{seealso@##1}{\unexpanded{#2}}}% \docsvlist{#1}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\seenopage} % \begin{macro}{\seealsonopage} % 保存旧的 |\see| 与 |\seealso| 命令定义,使用 |override| 选项时可临时使用旧的 % 定义。 % \begin{macrocode} \let\seenopage\see \let\seealsonopage\seealso % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seepage} % \begin{macro}{\seealsopage} % 带页码输出的 |\seepage| 与 |\seealsopage|。使用 |override| 选项时可直接使用 % |\see| 与 |\seealso| 代替 |\seepage| 与 |\seealsopage|。 % % 如果之前没有定义,这里会同时定义 |\seename| 和 |\alsoname|,与 \pkg{makeidx} % 初始值一致。 % \begin{macrocode} \DeclareSeealsoMacro\seepage{see}{see} \DeclareSeealsoMacro\seealsopage{also}{see also} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\see} % \begin{macro}{\seealso} % 使用 |override| 时,重定义 |\see| 与 |\seealso|。 % \begin{macrocode} \ifseealso@override \def\see{\seepage} \def\seealso{\seealsopage} \fi % \end{macrocode} % \end{macro} % \end{macro} % % \iffalse % % \fi % % \Finale \endinput