summaryrefslogtreecommitdiff
path: root/macros/texsis/index/index.tex
blob: d9985e29528890a4e0364389339fbaf73b38341b (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
%% file: index.tex - creating an index - TeXsis 2.19
% @(#) $Id: index.tex,v 18.1 2003/01/20 17:08:21 myers Exp $
%======================================================================*
%  index.tex  --  Macros for creating an index using MakeIndex
%
%  Use \index{key} or \idx{word} to make an entry in the index file
%  [\idx{word} is more or less the same as ``word\index{word}''].
%  At the end of the job the file \jobname.idx is the raw index file, 
%  ready to be fed into the MakeIndex program to create the index.  
%  The MakeIndex output file \jobname.ind is then fed back through TeX with
%  the output formatting macros below to print the final formatted index.
%
%  To process the index file with MakeIndex the command is simply
%
%       makeindex  jobname.idx
%
%  You can leave off the .idx extension for the raw file and makeindex
%  will assume it.  This will produce the processed index file, called
%  \jobname.ind.  To print the index you can either include it in 
%  another pass of the full document with ``\input \jobname.ind'' or
%  print it separately by adding ``\input index'' to the begining of the 
%  \jobname.ind file and running it through TeX.
%
%  If you set \markindextrue then indexed words selected with \idx
%  will appear in the printed output inside a ruled box.  This is
%  useful for draft copies when you are putting together the index,
%  but obviously you do not want to use it in a final copy.
%  The box does not interfere with or change the line spacing.
%
%  These macros are completely compatible with Plain TeX, although
%  they can also be used with TeXsis (some of the macros used below
%  are a part of TeXsis). Note however that these macros support output 
%  from MakeIndex in it's default LaTeX mode.  You don't need a separate
%  style file for MakeIndex!
%
%  For more information about how to make full use of MakeIndex read
%  the man page for makeindex(1) and/or the paper ``Index Preparation 
%  and Processing'' by Pehong Chen and Michale A. Harrison, 
%  Software: Practice and Experience, Vol 19, No. 9, Sep. 1988, pp. 897-915  
%  (a copy is available at ftp://ftp.texsis.org/texsis/index/index.tex )
%
%  It is possible to make more than one index by creating a few extra
%  macros based on the ones below.  See the documentation at the end
%  of this file for details.
%
%======================================================================*
% (C) Copyright 1992, 1999, 2000 by Eric Myers and Frank Paige.
% This file is a part of TeXsis.  Distribution and/or modifications
% are allowed under the terms of the LaTeX Project Public License (LPPL).
% See the file COPYING or ftp://ftp.texsis.org/texsis/LPPL
%======================================================================*
\message{- indexing macros}
\catcode`@=11                           % @ is a letter here to hide workings

\newif\ifmarkindex \markindexfalse      % put proof marks in text?
\newif\ifmakeindex \makeindextrue       % set false to suppress .idx output

%---------------------------*
% Index Entries:
%
% \idx{word} is the quickest way to make an index entry.
% The word is put in the text and an index entry is made at the
% same time.  It is the same as typing ``word\index{word}''.
% If \markintdextrue is selected the word appears in the text with a 
% box around it so you know it has been included in the index.


\def\idx#1{% include a word in the index output file
   #1\index{#1}%                        % put word in text and \index it
   \ifmarkindex                         % proof marks?
     \llap{\lower\jot\vbox to 0pt{\vss  % box it
        \tightboxit{\loosebox{\phantom{#1}}}}\hskip-\jot}%
   \fi}                                  % put a ruled box around word


% \index{key} makes an index entry for the given key.
% Since MakeIndex can use special characters like @ | ! and " in the key
% we must make sure that they are printed correctly to the raw index file.

\def\index{%  make an index entry for a given key
   \begingroup                  % turn MakeIndex special characters to letters
     \catcode`@=11 \catcode`"=11 \catcode`!=11 \catcode`|=11 \catcode`-=11 
    \@index}

\def\Index{%  alternate entry for \index (in case of tex2xindy)
   \begingroup                  % turn MakeIndex special characters to letters
     \catcode`@=11 \catcode`"=11 \catcode`!=11 \catcode`|=11 \catcode`-=11 
    \@index}



\def\@index#1{%  get the index entry and write it to the file
   \endgroup                    % special characters back to before
     \ifmakeindex               % .idx file output enabled?
       \indexwrite\indexout{\indexentry{#1}}% write entry to file
     \fi}


% \loosebox put a loose  box around a box.
% \tightboxit draws a rule box around the box #1 without any added space

\def\loosebox#1{%
    \vbox{\vskip\jot
        \hbox{\hskip\jot #1\hskip\jot}%
        \vskip\jot}}

\def\tightboxit#1{\vbox{\hrule\hbox{\vrule\vbox{#1}\vrule}\hrule}}

%---------------------------*
% Index Formatting (printing the processed index file) 


% The index is begun by \theindex or \begin{theindex} and ended
% with \endtheindex or \end{theindex}


\def\theindex{%  begin a formatted index
   \begingroup
     \parskip = 0pt                     % no extra space between items
     \def\item{\indexitem{0pt}}%        % level 0 item separator
     \def\subitem{\indexitem{20pt}}%    % level 1 item separator
     \def\subsubitem{\indexitem{30pt}}% % level 2 item separator
     \def\indexspace{\medskip}%         % intergroup vertical space
     \def\setcounter##1##2{\global\csname ##1no\endcsname=##2}% to set page counter
     \def\bold##1{{\bf ##1}}%           % boldface for |bold
     \def\italic##1{{\it ##1}}%         % italics for |italic
     \def\slanted##1{{\sl ##1}}%        % slanted for |slanted
     \def\see##1##2{{\it see} ##1}%     % italics for |see
     \def\seealso##1{{\it see also} ##1}%% italics for |seealso
     \def\also##1{{\it see also} ##1}%   % italics for |also
   }

\def\indexitem#1{%  how to make an entry for an item in the index
     \vskip 0pt                         % force vertical mode
     \hangindent=30pt\hangafter=1       % hanging indent for extra lines
     \noindent\hskip #1}                % level N item separator

\def\endtheindex{%  end a formatted index
   \endgroup}


% If you don't have MakeIndex you can still make a sorted index.
% (Even though it may not look as good.  If you are really going to
% do it right, do get MakeIndex).  The Unix sort(1) command or a similar
% program can be used to sort the \jobname.idx file.  You can then
% edit the file to collect all the page numbers for a key into 
% one \indexentry, like ``\indexentry{foo}{29,47-48}'' , and \indexentry
% will format the items as best it can. 


\def\indexentry#1#2{%  prints an index entry (from the raw file)
     \indexitem{0pt}#1, #2}             % keyword, page number


%-------------------------*
% Simple \begin .. \end support (like in LaTeX):  There is a conspiracy
% to preserve job security for typists by making sure one has to 
% type \begin{thing} and \end{thing} everywhere.  In TeXsis it's just
% \thing and \endthing, so here we just make \begin{thing} become \thing
% and \end{thing} become \endthing.  Then we can use MakeIndex in it's
% default mode, even though that is for LaTeX.
% Note: we don't check that you begin and end the same thing.  After all,
% you might want to say \begin{midfigure} followed by \end{figure}.


\def\begin#1{%  \begin{foo} just becomes \foo
   \begingroup                  % changes to \end are temporary
     \let\end=\endbegin         % now \end will end the \begin
     \expandafter\ifx\csname #1\endcsname\relax\relax % is \thing defined?
        \def\next{\beginerror{#1}}% NO: flag an error
     \else                      %
        \def\next{\csname #1\endcsname}% YES: just invoke it
     \fi\next}

\def\endbegin#1{%  \end{foo} just becomes \endfoo
   \endgroup                    % now \end goes back to normal
   \expandafter\ifx\csname end#1\endcsname\relax\relax % is \endthing defined?
      \def\next{\begingroup\beginerror{end#1}}% % NO: flag an error
   \else                        %
      \def\next{\csname end#1\endcsname}% YES: just invoke it
   \fi\next}


\newhelp\beginhelp{begin: 
    The \string\begin\space or \string\end\space marked above is for a^^M% 
    non-existant environment.  Check for spelling errors and such.}


\def\beginerror#1{% \begin{foo} or \end{foo} fail if no \foo or \endfoo
   \endgroup                    % make sure \end is back to normal
   \errhelp=\beginhelp          % longer help message
   \newlinechar=`\^^M           % ^^M is line break
   \errmessage{Undefined environment for \string\begin\space or \string\end}}


%---------------------------*
% Index file output:  
%

\newwrite\indexout              % raw index output file


% \indexinit will only get called once.  It opens the output file,
% write an identifying comment to it, and then undefines itself.

\def\indexinit{%                     open and initialize raw index file
  \immediate\openout\indexout=\jobname.idx % open file as \jobname.idx
  \immediate\write\indexout{\@comment Raw index file ``\jobname.idx''}%
  \immediate\write\indexout{\@comment ====================================}%
  \gdef\indexinit{\relax}}      % so we initialize only once

%  \@comment is for writing % to a file.  It expands to '% '.
     
{\catcode`\%=11 \gdef\@comment{% }}


% \indexwrite  writes an entry to the raw index file named by #1. Argument
% #2 is the \indexentry{foo}, so it is not expanded (which is why this is so 
% complicated), while \@indexpage is the page number, which *is* expanded.

\def\indexwrite#1#2{%           % write entry to raw index file
   \indexinit                   % open output file if not already
   \def\@finwrite{\write#1}%    % to write to index output file (#1)
   \begingroup                  % begin collecting tokens on stack
    \aftergroup\@finwrite       % put \write\indexout on stack
    \aftergroup{\relax          % put { on stack
    \@stackNX#2\@endstack       % puts \noexpand\token... on stack 
    \aftergroup\@indexpage      % expanded {enclosed} page number
    \aftergroup}\relax          % put } on stack
   \endgroup}                   % now dump from stack to \write

\def\@indexpage{{\folio}}       % to get the {enclosed} page number 

% Saying \@stackNX <stuff>\@endstack will take all the tokens
% in <stuff> and put them on the stack, with every control sequence
% prefaced by \noexpand.  \indexwrite uses this for unexpanded write.

\def\@stackNX{\futurelet\next\@stackswitch} 

\def\@stackswitch{%        decides what to do with various types of tokens
    \ifx\next\@endstack\relax           % if \@endstack then we'll quit
    \else\ifcat\noexpand\next\@stoken   % if token is a space,
        \aftergroup\space\let\next=\@eatnext%   write \space and eat token
    \else\ifcat\noexpand\next\bgroup    % if token is \bgroup
        \aftergroup{\let\next=\@eatnext %   write { and eat it
    \else\ifcat\noexpand\next\egroup    % if token is \egroup
        \aftergroup}\let\next=\@eatnext %   write a } and eat it
    \else                               % otherwize
        \let\next=\@stacktoken          %   just copy to the stack with \NX
     \fi\fi\fi\fi                       % end all \if's
     \next}                             % do it to the token

\def\\{\global\let\@stoken= }\\ 

% \@eatnext ignores the \next token and goes on to the 
%  one following in the argument list

\def\@eatnext{\afterassignment\@stackNX\let\next= } 

% \@stacktoken copies one token to the stack with \aftergroup,
%  then calls \@stackNX to get the one following.

\long\def\@stacktoken#1{% write token to stack, unexpanded    
    \ifcat\noexpand#1\relax             % if token is a control sequence
        \aftergroup\noexpand            %   preface with \noexpand
    \else\ifcat\noexpand#1\noexpand~\relax % if token is an active character
        \aftergroup\noexpand            %   preface with \noexpand
    \fi\fi                              %
    \aftergroup#1\relax                 % put the next token on the list
    \@stackNX}                          % do next token from argument...

\def\@endstack\@endstack{}              % just marks the end of token list

\catcode`@=12                           % @ goes back to \other, not a letter

%---------------------------*
% MULTIPLE INDICES:  
%  
% If you want more than one index I can't guess how you will want to
% use them, so all I can do is tell you how to use the macros above to
% create another (or several other) additional indices:
%
% 1) Create another output file and open it, with something like:
%
%       \newwrite\otherindexout   
%       \immediate\openout\otherindexout=other.idx
%
% 2) Define a macro to make the entry to the second index, following 
%    the pattern of \index and \@index above, but using the other index
%    file (but don't use @ in a macro name).  For example:
%
%       \def\OtherIndex{\begingroup     % special characters letters
%           \catcode`@=11 \catcode`"=11 \catcode`!=11 \catcode`|=11
%               \catcode`-=11  
%           \Oindex}
%
%       \def\Oindex#1{\endgroup    % special characters return
%              \indexwrite\otherindexout{\indexentry{#1}}}
%
%    Then saying \OtherIndex{word} will make an entry into the alternate
%    index for ``word''.
%
%>>> EOF index.tex <<<