A new implementation of L^{A}TEX’s indexing commands^{∗}

David M. Jones

15 September 1993

1 Introduction

This style file reimplements L^{A}TEX’s indexing macros to provide better and more robust support for indexes. In particular, it provides the following features:

1. Support for multiple indexes.

2. A ∗-variant of the \index command that, in addition to putting it’s argument in the index, also typesets it in the running text.

3. A \shortindexingon command that makes ^and _shorthand for \index and \index*, respectively (but only outside of math mode, of course). This can be turned of with the \shortindexingoff command.

4. The showidx style option has been merged into this file. The command \proofmodetrue can be used to enable the printing of index entries in the margin of pages. The size and style of font can be controlled with the

\indexproofstyle command.

5. A two-stage process for creating the raw index files, similar to that used to create tables of contents. This means that if you have a large document consisting of several \include’d files, you no longer lose the index if you format only part of the document with \includeonly.

6. The \index command has been rewritten to be more robust. In particular, it no longer depends on \catcode changes to work properly, so the new \index command can be used in places that the original couldn’t, such as inside the arguments of other macros.

∗This file has version number v3.02, last revised 15 September 1993, documentation dated 15 September 1993. The definitive version of this file is theory.lcs.mit.edu:pub/tex/index.doc.

2 Creating an index with L^{A}TEX

Conceptually, there are three stages to creating an index with L^{A}TEX. First, the raw index information has to be written out to a file. Then, the raw information needs to be processed and turned into a finished index. Finally, the finished index has to be read back in by L^{A}TEX and formated.

In L^{A}TEX, this is accomplished with the commands \makeindex, \index, \printindex, and (most often) with the auxiliary program makeindex. Assuming that your main file is called foo.tex, \makeindex opens the file foo.idx and initializes it for holding the raw index entries and \index is used to put raw index entries into foo.idx. Then the raw index file is processed by makeindex, which puts the finished index in foo.ind. Finally, the \printindex command is used in your L^{A}TEX document to indicate where the file foo.idx should be read back in, i.e., where the index should appear in your document.

This style modifies the \makeindex, \index, and \printindex commands, as described below.

3 The user interface

There are four pieces of information associated with each index:

1. A short, unique tag that identifies the index.

2. The extension of the output file where the raw index information will be put by L^{A}TEX.

3. The extension of the input file where the processed information will be put by makeindex to be read in later by L^{A}TEX.

4. The title of the index.

\newindex Correspondingly, the \newindex command takes four arguments. For example, if you wanted to declare an author index, you might use the following:

   \newindex{aut}{adx}{and}{Name Index}

Here, aut is the tag used to identify the author index, and “Name Index” is the title of the index. If the name of your main file is root.tex, then L^{A}TEX will write the raw index entries to the file root.adx, and you will execute the following makeindex command to process the author index:

   makeindex -o root.and root.adx

\renewindex The \renewindex command takes the same four arguments as the \newindex command and can be used to redefine indexes that have been previously declared.

\makeindex For backwards compatibility, the \makeindex command is redefined to use \newindex. It is essentially equivalent to

   \newindex{default}{idx}{ind}{Index}

The index labeled default is special: it is the one that will be used by \index and \printindex unless another index is specified (see below).

\printindex The \printindex command is modified by the addition of an optional ar-

gument, which is the tag of the index that should be printed. \index The \index command is modified in two ways. First, there is a ∗-variant

of the command that, in addition to putting its argument in an index, also typesets it on the page. Second, \index now takes an optional argument that should be the tag of the index where its argument should be put. If no such tag is supplied, the default index (such as that opened by \makeindex above) is used.

\shortindexingon Perhaps the most dubious feature of index.sty is that it allows you to \shortindexingoff define the characters ^and _to be abbreviations for \index* and \index out-

side of math mode. These abbreviations are enables by the \shortindexingon command and disabled by the \shortindexingoff command. Both of these commands make their changes locally rather than globally, so they can be used to enable or disable the abbreviations within a group. (This might be useful, for example, if you wanted the abbreviations turned on throughout most of the documentation, but turned off in one particular environment.) In addition,

shortindexingon shortindexingon can be used as an environment if that seems appropriate. \proofmodetrue As mentioned above, the showidx document-style option has been merged

\proofmodefalse
\indexproofstyle

into index.sty. It can be turned on with \proofmodetrue and turned off with \proofmodefalse. When it is turned on, all^{1} index entries will be put in the margin of the page where they appear. By default, they appear in the typewriter font at \footnotesize, but the user can override this with the \indexproofstyle command, for example,

   \indexproofstyle{\footnotesize\it}

will cause them to be put in italics instead.

\disableindex There are some circumstances where it might be helpful to suppress the writing of a particular raw index file. The \disableindex command is provided for this purpose. It takes one argument, a comma-separated list of tags of the indexes that should be disabled. This command should come before the declarations for the indexes that are being disabled^{2}. One situation where the \disableindex command might be useful is if you have so many indexes that you are exhausting TEX’s supply of output streams^{3}. For example, suppose you have 10 indexes, but only 5 output streams available for indexes. Then you could add a \disableindex command to the top of your file to suppress the writing of all but 5 of the indexes. (Note that the index entries would still get written to the .aux file; they just wouldn’t get copied to the individual raw index files at the end of the run.) At the end of the run, you could then re-run your main file a couple of times with different indexes disabled until you had created all of the raw index files. This is somewhat clumsy, but safer than any alternative I’ve come up with^{4}.

1Well, most, at least. There are some circumstances under which the index entries won’t show up in the proofs, although they will show up in the index.

4 Caveats

In order to implement this style file, it’s been necessary to modify a number of L^{A}TEX commands seemingly unrelated to indexing, namely, \@starttoc,

\raggedbottom, \flushbottom, \addcontentsline, \markboth, and \markright.

Naturally, this could cause incompatibilities between index.sty and any style files that either redefine these same commands or make specific assumptions about how they operate. See Section 6 for explanations of why these various commands needed modification.

It’s also been necessary to modify the \theindex environment, but I’ve tried to do so very conservatively. If your style file uses \indexname and your definition of \theindex doesn’t take any arguments, you should be ok. Otherwise, you’ll have to redefine the \theindex environment yourself if you don’t want the L^{A}TEX book.sty default.

In the current implementation, index.sty uses one output stream for each index. Since there are a limited number of output indexes, this means that there is a limit on the number of indexes you can have in a document. See the description of \disableindex for a fuller discussion of this problem and one way around it.

2This limits its usefulness somewhat, but since the output file for an index is opened when the index is declared, the damage has already been done. We could close the file, but we can’t prevent a new output stream from being allocated and we can’t keep the old file from being truncated.

3TEX only has 16 output streams, which are allocated with the \newwrite command. The standard L^{A}TEX styles use from 3 to 7 of these, which should leave room for up to 9 indexes. Of course, if you have extra output files, then there will be fewer output streams left for indexes.

4A less clumsy (for the user, at least) solution would be to read the .aux file multiple times at the end of the run, each time writing just one of the raw index files. The main disadvantage of this scheme is that it would require a modification of \enddocument.

5 To do’s

It might be nice if the \index* command parsed its argument so that, for example, instead of writing ‘\index{sin@$\sin$}$\sin$’, one could write ‘\index*{sin@$\sin$}’. However, this fraught with numerous dangers, and I’m both too lazy and too cowardly to undertake it now.

Maybe the user should be given the option of deciding which characters are used for the shortindexing abbreviations

The documentation should be carefully read, edited, and finished. (In particular, I should add some scathing comments about some of the problems that made it necessary to redefine so many of L^{A}TEX’s commands.)

Maybe it would be nice if this package were compatible with plain TEX.

6 The code

As is customary, we first make sure the file is loaded only once. Then we print an identifying message to the terminal. loaded

1 ⟨∗style⟩

 2 \@ifundefined{newindex}{}{\endinput}

3

 4 \typeout{Style-Option: `index' \fileversion\space <\filedate> (dmj)}

\@ifundefined We begin by redefining the L^{A}TEX command \@ifundefined to prevent it from expanding its arguments prematurely. This also requires us to redefine \@leftmark and \@rightmark to make them \long. The following three definitions are borrowed from amsart.sty, v1.1b ⟨31 Jul 1991⟩. I rely heavily upon this more robust definition of \@ifundefined.

 5 \def\@ifundefined#1{%
 6  \expandafter\ifx\csname#1\endcsname\relax
 7  \expandafter\@leftmark
 8  \else
 9  \expandafter\@rightmark
10  \fi

11 }

12

13 \long\def\@leftmark#1#2{#1}
14 \long\def\@rightmark#1#2{#2}

\disableindex The \disableindex should come before the declarations of the indexes it refers to. (Question: If an index has been disabled, should it show up in index proofs? Maybe there should be a separate command to disable index proofs on and index-by-index basis.)

15 \def\disableindex#1{%
16  \@for\@tempa:=#1\do{%
17  \@namedef{disable@\@tempa}{}%

18  \@ifundefined{tf@\@tempa}{}{%
19  \typeout{index.sty> Warning! It's too late to disable the
20  `\@tempa' index; the output}%
21  \typeout{index.sty> file \jobname.\@tempa\space has already
22  been opened for output. You should}%
23  \typeout{index.sty> put the \string\disableindex\space
24  command before the declaration of the}%
25  \typeout{index.sty> `\@tempa' index.}%
26  }%
27  }%

28 }

\if@newindex \newindex \renewindex The \newindex and \renewindex commands are defined on analogy with the

\[re]newcommand macros. Each index is identified by a unique tag, which is specified in the first argument of \newindex. Most of the information about the index labeled ⟨tag⟩ is kept in the macro \idx@⟨tag⟩, so we can check to see if a particular index has already been defined by checking whether \idx@⟨tag⟩ is defined. \newindex and \renewindex both check to see if their first argument is already associated with an index and then either issue an appropriate error message or call \@newindex.

The \if@newindex flag will be used to keep \renewindex from re-allocating \write and \toks registers later.

29 \newif\if@newindex

30

31 \def\newindex#1{%
32  \@ifundefined{idx@#1}%
33  {\@newindextrue\@newindex{#1}}%
34  {%
35  \@latexerr{Index type `\string#1' already defined}\@ehc
36  \expandafter\@gobble\@gobbletwo
37  }%

38 }

39

40 \def\renewindex#1{%
41  \@ifundefined{idx@#1}%
42  {%
43  \@newindextrue
44  \@latexerr{Index type `\string#1' not defined}\@ehc
45  }%
46  {\@newindexfalse}%
47  \@newindex{#1}%

48 }

\@preamblecmds Neither \newindex, \renewindex, nor \disableindex should be used anywhere

except inside style files or in the preamble of a document, so we add them to

the \@preamblecmds list.

49 \begingroup
50  \def\do{\noexpand\do\noexpand}%
51  \xdef\@preamblecmds{%
52  \@preamblecmds
53  \do\newindex
54  \do\renewindex
55  \do\disableindex

56 }

57 \endgroup

\@newindex \@newindex does most of the work. First, it picks up the first three arguments of the \[re]newindex command and stores the second two in an appropriate \idx@ macro. The title of the index is treated differently, however, since it is potentially fragile in a particularly odd way. To prevent mishaps, it is stored in a token register. In addition to stashing away the information about the index, \@newindex also opens an appropriate output files if we are writing auxiliary files (i.e., unless \nofiles has been called).

\my@newtoks Since we need to declare new token registers on the fly, we need a non-\outer version of \newtoks.

58 \def\my@newtoks{\csname newtoks\endcsname}

59

60 \def\@newindex#1#2#3{%
61  \@namedef{idx@#1}{#2:#3}%
62  \if@filesw
63  \@ifundefined{disable@#1}{%
64  \if@newindex
65  \expandafter\newwrite\csname tf@#1\endcsname
66  \expandafter\my@newtoks\csname idxtitle@#1\endcsname
67  \else
68  \immediate\closeout\@nameuse{tf@#1}%
69  \fi
70  \immediate\openout\@nameuse{tf@#1}=\jobname.#2 %
71  \typeout{index.sty> Writing index file \jobname.#2 }%

72 }

73  {\typeout{index.sty> Index `#2' disabled -- not opening
74  \jobname.#2 }}%
75  \fi
76  \expandafter\csname idxtitle@#1\endcsname

77 }

\@second This is a useful macro for retreiving the second field of an index specification.

78 \def\@second#1:#2\@nil{#2}
\@nearverbatim \@meaning  \@nearverbatim\foo is much like \meaning\foo, except that it suppresses the

“macro ->” string produced when \meaning expands a macro. It is used by \@wrindex and \@vwritefile to produce an “almost verbatim” copy of their arguments. This method replaces the use of \@sanitize from latex.tex and allows indexing macros to be used in places (such as inside macro arguments) where the original \index command could not. Thanks to Donald Arseneau ⟨asnd@erich.triumf.ca⟩ for pointing out this trick to me. (For more information on this trick, see Dirty Trick #3 of the TEXbook, page 382).

As defined, nearverbatim only works on macros. It would be nice if it could work with other tokens, but it’s more important that it work only by expansion, which means we can’t put in tests to see what the next token is.

79 {\@nearverbatim}
80 \def\@nearverbatim{\expandafter\@meaning\meaning}

81

82 \def\@meaning#1>{}

Now we define the \index macro itself. The following definitions are adapted from latex.tex v2.09 ⟨25 March 1992⟩.

\makeindex First we redefine \makeindex to define the default index using \newindex. We use \edef to make sure that \indexname gets expanded here. Otherwise we’ll get into an infinite loop later on when we try to redefine \indexname inside the \theindex environment.

83 \edef\makeindex{%
84  \noexpand\newindex{default}{idx}{ind}{%
85  \expandafter\ifx\csname indexname\endcsname\relax
86  Index%
87  \else
88  \indexname
89  \fi
90  }%

91 }

\if@silentindex \if@addtoindex \if@proofmode We need three new flags. The first, \if@silentindex, indicates whether the

entry should be typeset in running text, as well as written out to the index; this is used to implement the \index* command. The second, \if@addtoindex, indicates whether entries should be written to the index; this is used to disable the \index command inside of page headings and tables of contents. The third, \ifproofmode, indicates whether index entries should be put in the margin of the page for proofing purposes.

92 \newif\if@silentindex\@silentindextrue

93

94 \newif\if@addtoindex\@addtoindextrue

95

96 \newif\ifproofmode\proofmodefalse

\index \p@index \x@index \index will be made self-protecting (a la \em, etc.) so it can be used inside, for example, sectioning commands. Unfortunately, to really make \index robust, we have to redefine some of L^{A}TEX’s commands for dealing with tables of contents and page headings. (See below.) ∗sigh∗

97 \def\index{\protect\p@index}

98

99 \def\p@index{%
100  \if@silentindex\@bsphack\fi
101  \@ifstar{\@silentindexfalse\@xindex}{\@silentindextrue\@xindex}%

102 }

103

104 \def\@xindex{\@ifnextchar[{\@index}{\@index[default]}}

\@index \@@index \@wrindex The following is much more complicated than it should have to be. First, note the check to see if \index is equal to \@gobble. This is so I don’t have to rede-

fine \@outputpage, which temporarily disables \label, \index, and \glossary

by \let’ing them equal to \@gobble. (For this reason, we have to be very careful to make sure that \index has expanded to \p@index before it gets to \@outputpage.) Second, note that if \if@addtoindex is false, we don’t complain about undefined index types. This is because if your page headings, for example, are being typeset in all uppercase, you might end up with something

like \index[AUT]{...} instead of \index[aut]{...}.
105 \def\@index[#1]{%
106  \ifx\index\@gobble
107  \@addtoindexfalse
108  \fi
109  \def\@tempf{\@@index{#1}}%
110  \if@addtoindex
111  \@ifundefined{idx@#1}%

112 {%

113  \def\@tempf{%
114  \@latexerr{Index type `\string#1' undefined}%
115  \@ehc
116  \@silentindextrue
117  \@gobble

118 }% 119 }%

120  {}%
121  \fi
122  \@tempf

123 }

124

125 \def\@@index#1#2{%
126  \if@addtoindex
127  \if@filesw\@wrindex{#1}{#2}\fi
128  \ifproofmode\@showidx{#2}\fi
129  \fi
130  \if@silentindex\expandafter\@esphack\else\@silentindextrue#2\fi

131 }

133 \def\@wrindex#1#2{%
134  \begingroup
135  \let\thepage\relax
136  \def\@tempa{#2}%
137  \edef\@tempa{%
138  \write\@auxout{%
139  \string\@vwritefile{#1}{%
140  \string\indexentry{\@nearverbatim\@tempa}{\thepage}%

141 }% 142 }% 143 }%

144  \expandafter\endgroup\@tempa
145  \if@nobreak\ifvmode\nobreak\fi\fi

146 }

\seename \see \printindex \@printindex The following are adapted from makeidx.sty, v2.09 ⟨21 Oct 91⟩.
147 \@ifundefined{seename}{\def\seename{see}}{}

148

149 \def\see#1#2{{\em \seename\/} #1}

150

151 \def\printindex{\@ifnextchar [{\@printindex}{\@printindex[default]}}

152

153 \def\@printindex[#1]{%
154  \def\@indextype{#1}%
155  \@ifundefined{idx@#1}%
156  {\@latexerr{Index type `\string#1' undefined}\@ehc}%

157 {%

158  \edef\@tempa{\@nameuse{idx@#1}}%
159  \@input{\jobname.\expandafter\@second\@tempa\@nil}%

160 }% 161 }

\@indexstar@ Now we set things up for \shortindexing. First, we define a one-token shorthand for \index*. This will be needed in the definition of \idx@activehat.

162 \def\@indexstar@{\index*}

\idx@activehat \idx@activebar Next, we define the values that ^and _will have when shortindexing is turned on.

163 \def\idx@activehat{%
164  \relax
165  \ifmmode\expandafter\sp\else\expandafter\@indexstar@\fi

166 }

167

168 \def\idx@activebar{
169  \relax
170  \ifmmode\expandafter\sb\else\expandafter\index\fi

171 }

\shortindexingon \shortindexingoff Now we define the \shortindexingon and \shortindexinoff commands to

turn shortindexing on and off (surprise!). \shortindexingon saves the old definitions and \catcode’s of ^and _so they can later be restored by \shortindexingoff. Both of these make their changes local to any enclosing group, so they can be used as declarations to disable or enable shortindexing temporarily. In addition, shortindexingon can also be used as an environment.

This is potentially very confusing. My basic rationale (if it can be described as such) was that under normal circumstances, one would put \shortindexingon in the preamble of one’s document, and never want to turn it off. \shortindexingoff is an attempt to make allowance for the contingency that someone might want to turn shortindexing off, either permanently or temporarily.

172 \newif\if@shortindexing

173

174 \begingroup

175

176  \catcode`\^=\active
177  \catcode`\_=\active

178

179  \gdef\shortindexingon{%
180  \@shortindexingtrue
181  \chardef\old@idxhatcode=\catcode`\^\relax
182  \chardef\old@idxbarcode=\catcode`\_\relax
183  \catcode`\^=\active
184  \catcode`\_=\active
185  \let\old@idxhat=^%
186  \let\old@idxbar=_%
187  \let^\idx@activehat
188  \let_\idx@activebar

189 }

190

191  \gdef\shortindexingoff{%
192  \if@shortindexing
193  \@shortindexingfalse
194  \let^=\old@idxhat
195  \let_=\old@idxbar
196  \catcode`\^=\old@idxhatcode
197  \catcode`\_=\old@idxbarcode
198  \fi

199 }

200

201 \endgroup

Now we redefine \theindex. We try to make the minimal possible change, but if the user’s style doesn’t know about \indexname, we have no alternative but to redefine the entire environment and issue a warning.

Thanks to Alan Jeffrey ⟨alanje@cogs.sussex.ac.uk⟩ for pointing out how the package should behave when \indexname is already defined and for the code to implement that case.

202 \expandafter\ifx\csname indexname\endcsname\relax

203

204  \typeout{index.sty> Uh oh!  It looks like your document style
205  doesn't use \string\indexname.}
206  \typeout{index.sty> I'll have to redefine the
207  \string\theindex\space environment, using}
208  \typeout{index.sty> the `book' style default.}

209

210  \def\indexname{Index}

The following is adapted from book.sty v2.09 ⟨14 Jan 92⟩.

211  \def\theindex{%
212  \@restonecoltrue
213  \if@twocolumn\@restonecolfalse\fi
214  \columnseprule\z@ \columnsep 35\p@
215  \edef\@indexname{%
216  \expandafter\the\@nameuse{idxtitle@\@indextype}%

217 }%

218  \twocolumn[\@makeschapterhead{\@indexname}]%
219  \@mkboth{\uppercase{\@indexname}}{\uppercase{\@indexname}}%
220  \thispagestyle{plain}%
221  \parindent\z@
222  \parskip\z@ plus .3\p@\relax\let\item\@idxitem

223 }

224

225 \else

226

227  \@temptokena={%
228  \edef\indexname{\the\@nameuse{idxtitle@\@indextype}}%

229 }

230  \toks0=\expandafter{\theindex}
231  \edef\theindex{\the\@temptokena\the\toks0}

232

233 \fi
\@vwritefile \x@vwritefile \y@vwritefile Now we define the \@vwritefile macro, which copies information from the

aux file to one of the other auxiliary files. \@vwritefile performs essentially the same function as \@writefile, except that it does not expand it second argument (i.e., it writes it out verbatim (well, almost verbatim)).

NOTE: There doesn’t seem to be any reason why \@writefile *should* expand its second argument and in fact, we later redefine \addcontentsline to use \@vwritefile instead of \@writefile. A slight extension of this idea could be used to solve the problem of fragility in sectioning commands.

\@vwritefile, like \@writefile, should be disabled when the aux file is being read by \begin{document}. To avoid having to redefine \document, we make the behaviour of \@vwritefile conditional on the current meaning of

\@writefile.
234 \def\@vwritefile{%
235  \ifx\@writefile\@gobbletwo
236  \expandafter\@gobbletwo
237  \else
238  \expandafter\x@vwritefile
239  \fi

240 }

241

242 \def\x@vwritefile#1{%
243  \@ifundefined{tf@#1}{\@gobbletwo}{\y@vwritefile}{#1}%

244 }

245

246 \long\def\y@vwritefile#1#2{%
247  \def\@tempa{#2}%
248  \immediate\write\csname tf@#1\endcsname{\@nearverbatim\@tempa}%

249 }

Now we take some code from showidx.sty and merge it into our new system. There are four reasons for redefining the commands here rather than just inputting showidx.sty (or requiring the user to do so). First, showidx.sty ends with a call to \flushbottom, which I want to avoid. Second, the instructions for successfully using showidx.sty along with index.sty would be somewhat tricky. This way, I can just tell users not to use showidx.sty at all. Third, I need to make some alterations to \@showidx anyway. In particular, (a) I need to add the \@sanitizeat command so this works correctly with AMS-L^{A}TEX and (b) I want to add the \indexproofstyle command so the user can customize the size and font used for the index proofs. Finally, showidx.sty has at least two annoying bugs in it. See the edit-history for version 2.01 for a description.

\@indexbox This code is adapted from showidx.sty, v2.09 ⟨16 Jun 1991⟩.

250 \newinsert\@indexbox

251

252 \dimen\@indexbox=\maxdimen

\@sanitizeat The definition of \@sanitizeat is slightly tricky, since we need @ to be active when this macro is defined, but we also need it to be part of the control sequence name.

253 \begingroup
254  \catcode`\@=\active
255  \expandafter\gdef\csname\string @sanitizeat\endcsname
256  {\def @{\char`\@}}
257 \endgroup

\indexproofstyle \@showidx \@leftidx \@rightidx \@mkidx \raggedbottom \flushbottom \@texttop Note the cautious way of calling \reset@font, which is necessary for this to

work correctly under both the Old and New Font Selection Schemes.

258 \newtoks\indexproofstyle

259

260 \indexproofstyle{\footnotesize\csname reset@font\endcsname\tt}

261

262 \def\@showidx#1{%
263  \insert\@indexbox{%
264  \@sanitizeat
265  \the\indexproofstyle
266  \hsize\marginparwidth
267  \hangindent\marginparsep \parindent\z@
268  \everypar{}\let\par\@@par \parfillskip\@flushglue
269  \lineskip\normallineskip
270  \baselineskip .8\normalbaselineskip\sloppy
271  \raggedright \leavevmode
272  \vrule \@height .7\normalbaselineskip \@width \z@\relax#1\relax
273  \vrule \@height\z@ \@depth.3\normalbaselineskip \@width\z@\relax

274 }%

275  \ifhmode\penalty\@M \hskip\z@skip\fi

276 }

277

278 \def\@leftidx{\hskip-\marginparsep \hskip-\marginparwidth}

279

280 \def\@rightidx{\hskip\columnwidth \hskip\marginparsep}

281

282 \def\@mkidx{%
283  \vbox to \z@{%
284  \rlap{%
285  \if@twocolumn
286  \if@firstcolumn \@leftidx \else \@rightidx \fi
287  \else
288  \if@twoside
289  \ifodd\c@page \@rightidx \else \@leftidx \fi
290  \else
291  \@rightidx
292  \fi
293  \fi
294  \box\@indexbox

295 }%

296  \vss

297 }% 298 }

299

300 \def\raggedbottom{%
301  \def\@textbottom{\vskip\z@ plus.0001fil}%
302  \let\@texttop\@mkidx

304

305 \def\flushbottom{\let\@textbottom\relax \let\@texttop\@mkidx}

306

307 \let\@texttop\@mkidx

Now, this next bit really gets up my nose. The only way to make sure that the \index command gets handled correctly when used inside of sectioning commands is to redefine a bunch of L^{A}TEX’s table of contents and running-heads macros. ∗blech∗ Fragility rears its ugly head again. (Incidentally, it should be possible to use the \@nearverbatim trick to make arguments of sectioning commands robust. I’ll have to explore this.)

These are based on latex.tex 2.09 ⟨25 March 1992⟩.

\addcontentsline We need to redefine \addcontentsline to keep it from expanding \index

commands too far. In particular, we have removed \index from the list of macros that are set equal to \@gobble and we substitute \@vwritefile for \@writefile. This latter change also means that we can simplify the definition of \protect somewhat.

308 \def\addcontentsline#1#2#3{%
309  \if@filesw
310  \begingroup
311  \let\label\@gobble
312  \let\glossary\@gobble
313  \def\protect##1{\string##1\space}%
314  \@temptokena{\thepage}%
315  \edef\@tempa{%
316  \write\@auxout{%
317  \string\@vwritefile{#1}{\string\contentsline{#2}{#3}%
318  {\the\@temptokena}}%

319 }% 320 }%

321  \@tempa
322  \endgroup
323  \if@nobreak\ifvmode\nobreak\fi\fi
324  \fi

325 }

\@starttoc We need to redefine \@starttoc to \@addtoindexfalse so that items don’t get

written to the index from within tables of contents. The only change here is the

addition of \@addtoindexfalse.
326 \def\@starttoc#1{%
327  \begingroup
328  \@addtoindexfalse
329  \makeatletter
330  \@input{\jobname.#1}%

331  \if@filesw
332  \expandafter\newwrite\csname tf@#1\endcsname
333  \immediate\openout \csname tf@#1\endcsname \jobname.#1\relax
334  \fi
335  \global\@nobreakfalse
336  \endgroup

337 }

\markboth \markright Finally, we have to redefine \markboth and \markright to keep them from disabling the expansion of \index while putting section heads into the \mark. Otherwise, we’d end up with “\index” in the mark, which would cause problems when \@outputpage redefines \index to be equal to \@gobble. Instead, we want \index to expand to \p@index in the \mark, so we retain control over what happens in outputpage.

This time, the only change is to remove \index from the list of macros that are \let equal to \relax.

338 \def\markboth#1#2{%
339  \gdef\@themark{{#1}{#2}}%
340  \begingroup
341  \let\protect\noexpand
342  \let\label\relax
343  \let\glossary\relax
344  \mark{\@themark}%
345  \endgroup
346  \if@nobreak\ifvmode\nobreak\fi\fi

347 }

348

349 \def\markright#1{%
350  \begingroup
351  \let\protect\noexpand
352  \let\label\relax
353  \let\glossary\relax
354  \expandafter\@markright\@themark{#1}%
355  \mark{\@themark}%
356  \endgroup
357  \if@nobreak\ifvmode\nobreak\fi\fi

358 } 359 ⟨/style⟩

7 Edit history

v1.00 (4 Mar 1993) initial version, posted to comp.text.tex.

v1.01 (4 Mar 1993) added \renewindex command and checking to make sure index is (or is not) defined in \newindex, \index and \printindex.

Also tightened up the code in various places and added check to make sure file is only loaded once.

v2.00 (24 Mar 1993) added support for \index*, proofmode, \shortindexingon

and \shortindexingoff.

v2.01 (24 Jun 1993) Fixed 3 bugs. (1) If proofmode was turned on, then something like “\index{WORD}WORD” would suppress the hyphenation of WORD. This was fixed by adding “\penalty\@M\hskip\z@skip” to the end of \@showidx. (This is just the definition of \allowhyphens borrowed from german.sty, v2 ⟨4 Nov 1988⟩). (2) The \hbox in \@mkidx was being set at its natural width, which had a tendency to interfere with the width of the page. The \hbox is now replaced by \rlap. (3) If the title of an index (i.e., the fourth argument of \newindex) contained a particularly fragile command like \d, havoc would ensue when \theindex tried to extract the title. Titles are now kept in token registers to prevent such unpleasantness. Bugs (2) and (3) were reported by Dominik Wujastyk ⟨D.Wujastyk@ucl.ac.uk⟩ on 24 June 1993. Note that bugs (1) and (2) are actually bugs in showidx.sty, v2.09 ⟨16 Jun 1991⟩.

v2.02 (25 Jun 1993) Rewrote the code that implements the short indexing commands (^and _) to make index.sty compatible with other style files that need to make ^and _active in some contexts. See the code for more details.

v2.03 (30 Jun 1993) Once again rewrote the code that implements the short indexing commands. Dumped the shortindexing environment and rewrote

the \shortindexingon and \shortindxingoff commands to save and

restore the \catcode’s and meanings of ^and _in the safest possible (I hope) order. Also added the \if@shortindexing flag to keep \shortindexingoff from doing anything if it is called outside of the scope

of a \shortindexingon command. (Question: Should \shortindexingon

check that flag before doing anything?)

v2.04 (beta) (14 Jul 1993) Added \disableindex command. Added \newindex

and \renewindex to \@preamblecmds. Add \if@newindex flag to

\@newindex to prevent \renewindex from re-allocating new \write and \toks registers. Rewrote using doc.sty and DocStrip. Also cleaned up the code somewhat.

v3.00 (15 Jul 1993) Made further minor tweaks to code and internal documentation. Booted version number up to 3.00 and released on the world.

v3.01 (19 Jul 1993) Fixed DocStrip CheckSum.

v3.02 (15 Sep 1993) Corrected spelling of \@shortindexingfalse in definition of \shortindexingoff. Thanks to Hendrik G. Seliger ⟨hank@Blimp.automat.uni− essen.de⟩ for this bug report. Also added redefinitions of \@leftmark and \@rightmark to fix a bug reported by Dominik Wujastyk ⟨D.Wujastyk@ucl.ac.uk⟩.

8 The sample file

360 ⟨test⟩%% This is a sample file for index.sty.  To run the sample,
361 ⟨test⟩%% execute the following commands:

362 ⟨test⟩%%

363 ⟨test⟩%% latex sample.tex
364 ⟨test⟩%% makeindex sample
365 ⟨test⟩%% makeindex -o sample.and sample.adx
366 ⟨test⟩%% makeindex -o sample.nnd sample.ndx
367 ⟨test⟩%% latex sample.tex

368 ⟨test⟩

369 ⟨test⟩\documentstyle[index]{book}

370 ⟨test⟩

371 ⟨test⟩\makeindex
372 ⟨test⟩\newindex{aut}{adx}{and}{Name Index}
373 ⟨test⟩\newindex{not}{ndx}{nnd}{List of Notation}

374 ⟨test⟩

375 ⟨test⟩\shortindexingon

376 ⟨test⟩

377 ⟨test⟩\proofmodetrue

378 ⟨test⟩

379 ⟨test⟩\def\aindex{\index*[aut]}

380 ⟨test⟩

381 ⟨test⟩\begin{document}

382 ⟨test⟩

383 ⟨test⟩\tableofcontents

384 ⟨test⟩ 385 ⟨test⟩\newpage 386 ⟨test⟩

387 ⟨test⟩\chapter{Here is a ^[aut]{chapter} title}

388 ⟨test⟩

389 ⟨test⟩\section{Section header\index[aut]{section}}

390 ⟨test⟩

391 ⟨test⟩Here is some text.\index{subject}

392 ⟨test⟩

393 ⟨test⟩Here is \index[not]{notation}some more \index[not]{sin@$\sin$}

394 ⟨test⟩text. 395 ⟨test⟩

396 ⟨test⟩Here is some ^{more} _[not]{notation} text.

397 ⟨test⟩

398 ⟨test⟩Here is yet more \aindex{text}.

399 ⟨test⟩

400 ⟨test⟩\section{Another Section header _[aut]{section2}}

401 ⟨test⟩

402 ⟨test⟩And here is some math: $x^1_b$.

403 ⟨test⟩

404 ⟨test⟩Here is an ^[aut]{index} entry \fbox{inside an
405 ⟨test⟩\index[not]{min@$\min$}fbox}

406 ⟨test⟩

407 ⟨test⟩\fbox{Here is an ^[aut]{entry} in a box.}

408 ⟨test⟩

409 ⟨test⟩\printindex[not]

410 ⟨test⟩

411 ⟨test⟩\printindex[aut]

412 ⟨test⟩

413 ⟨test⟩\printindex

414 ⟨test⟩

415 ⟨test⟩\end{document}