%% 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 \@endstack will take all the tokens % in 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 <<<