summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/seealso
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/seealso
Initial commit
Diffstat (limited to 'macros/latex/contrib/seealso')
-rw-r--r--macros/latex/contrib/seealso/README11
-rw-r--r--macros/latex/contrib/seealso/seealso.dtx1084
-rw-r--r--macros/latex/contrib/seealso/seealso.ins58
-rw-r--r--macros/latex/contrib/seealso/seealso.pdfbin0 -> 254867 bytes
4 files changed, 1153 insertions, 0 deletions
diff --git a/macros/latex/contrib/seealso/README b/macros/latex/contrib/seealso/README
new file mode 100644
index 0000000000..70da5b9c81
--- /dev/null
+++ b/macros/latex/contrib/seealso/README
@@ -0,0 +1,11 @@
+The seealso package
+
+Copyright (C) 2014, 2017 by Leo Liu <leoliu.pku@gmail.com>
+
+The package amends the \see and \seealso macros that are used in building
+indexes with makeindex, to deal with repetitions, and to ensure page numbers
+are present in the actual index entries.
+
+This work is released under the LPPL v1.3c or later.
+
+The project is hosted on https://github.com/leo-liu/tex-pkg
diff --git a/macros/latex/contrib/seealso/seealso.dtx b/macros/latex/contrib/seealso/seealso.dtx
new file mode 100644
index 0000000000..f3b49e6c3e
--- /dev/null
+++ b/macros/latex/contrib/seealso/seealso.dtx
@@ -0,0 +1,1084 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2014, 2017 by Leo Liu <leoliu.pku@gmail.com>
+% ---------------------------------------------------------------------------
+% 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}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{seealso}
+%<*package>
+ [2017/03/23 v1.2 makeidx's see and seealso with page number support.]
+%</package>
+%
+%<*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}
+%</driver>
+% \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) <leoliu.pku@gmail.com>]
+% {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}
+% {<listmacro>}{<string>}{<true>}{<false>}
+\long\def\seealso@ifinlist@#1#2#3#4{%
+ \def\next{#4}%
+ \def\do##1{%
+ \ifstrequal{##1}{#2}
+ {\def\next{#3}\listbreak}
+ {}}%
+ \dolistloop{#1}%
+ \next}
+% {<string>}{<listmacro>}{<true>}{<false>}
+\protected\long\def\seealso@ifinlist#1#2{%
+ \seealso@ifinlist@{#2}{#1}}
+% {<string>}{<listcsname>}{<true>}{<false>}
+\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
+%</package>
+% \fi
+%
+% \Finale
+\endinput
diff --git a/macros/latex/contrib/seealso/seealso.ins b/macros/latex/contrib/seealso/seealso.ins
new file mode 100644
index 0000000000..2524e5a3e6
--- /dev/null
+++ b/macros/latex/contrib/seealso/seealso.ins
@@ -0,0 +1,58 @@
+%% Copyright (C) 2014, 2017 by Leo Liu <leoliu.pku@gmail.com>
+%% --------------------------------------------------------------------------
+%% 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.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/seealso}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2014, 2017 by Leo Liu <leoliu.pku@gmail.com>
+--------------------------------------------------------------------------
+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.
+
+\endpreamble
+
+\askforoverwritefalse
+\generate{\file{seealso.sty}{\from{seealso.dtx}{package}}}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* seealso.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file seealso.dtx *}
+\Msg{* through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile
diff --git a/macros/latex/contrib/seealso/seealso.pdf b/macros/latex/contrib/seealso/seealso.pdf
new file mode 100644
index 0000000000..d4cd87fb1d
--- /dev/null
+++ b/macros/latex/contrib/seealso/seealso.pdf
Binary files differ