summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/seealso/seealso.dtx
blob: f3b49e6c3e8e7c22412cc2eef931e01467e9d0e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
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