2

Is there a command---for example, something like \pages{pangolins}--- that represents the page numbers (and page ranges) of an index entry "pangolins"? If not, is there any elegant way to code such a command, with or without the use of existing index packages like imakeidx?

Here is a minimal example of how such a command could be used:

\documentclass{book}

\usepackage{imakeidx}
\makeindex

\begin{document}

Here is a paragraph about pangolins\index{pangolins}.  Pangolins are the only mammals covered in scales.

Here is a paragraph about meerkats.  Meerkats are immune to the venom of scorpions and snakes.

Here is another paragraph about pangolins.  A single pangolin can consume 20,000 ants per day.  If you want to learn more about pangolins, see page \pages{pangolins}.

\end{document}
  • I don't know of any such instruction, but the index entries with page numbers are written out (in order of occurrence) to an .idx file. It should be possible to read these in, look for the desired entry (it can occur multiple times), and collect the page numbers recorded there. – barbara beeton Feb 26 at 16:25
  • Interesting idea, though it sounds above my current skill level in LaTeX. Does anyone have a code example? – SapereAude Feb 26 at 17:02
  • Let me add that, for my application, it would be fine to assume that there is only a single, simple \index command per index entry -- just one \index{panolins}, \index{meerkats}, etc. in the text, and no page ranges, subentries, cross-referencing, or similar complexity. – SapereAude Feb 26 at 18:39
3

This supports also page ranges and also multiple pages (but page ranges should not mix with single references). It uses Barbara Beeton's idea in comments to the question.

\documentclass{book}
\usepackage{imakeidx}
\usepackage{xparse}

\usepackage{lipsum}

\ExplSyntaxOn
\NewDocumentCommand{\readindex}{O{\c_sys_jobname_str}}
 {
  \group_begin:
  \cs_set_eq:NN \indexentry \readindexentry
  \file_if_exist_input:n { #1.idx }
  \group_end:
 }

\NewDocumentCommand{\pages}{m}
 {
  \prop_item:Nn \g_readindex_prop { #1 }
 }

\NewDocumentCommand{\readindexentry}{>{\SplitArgument{1}{|}}m m}
 {
  \readindex_process:nnn #1 { #2 }
 }

\prop_new:N \g_readindex_prop

\cs_new_protected:Nn \readindex_process:nnn
 {
  \str_case:nnF { #2 }
   {
    { ( }{ \readindex_start:nn { #1 } { #3 } }
    { ) }{ \readindex_end:nn   { #1 } { #3 } }
   }
   { \readindex_standard:nn { #1 } { #3 } }
 }

\cs_new_protected:Nn \readindex_standard:nn
 {
  \prop_if_in:NnTF \g_readindex_prop { #1 }
   {
    \prop_gput:Nnx \g_readindex_prop { #1 }
     { \prop_item:Nn \g_readindex_prop { #1 } , ~ #2 }
   }
   {
    \prop_gput:Nnn \g_readindex_prop { #1 } { #2 }
   }
 }

\cs_new_protected:Nn \readindex_start:nn
 {
  \prop_gput:Nnn \g_readindex_prop { #1 } { #2 }
 }
\cs_new_protected:Nn \readindex_end:nn
 {
  \prop_gput:Nnx \g_readindex_prop { #1 }
   { \prop_item:Nn \g_readindex_prop { #1 } -- #2 }
 }

\ExplSyntaxOff

\readindex
\makeindex % must be ***after*** \readindex

\begin{document}

For elephants, see \pages{elephants}.

Here we also talk about unicorns\index{unicorns}, treated on \pages{unicorns}.

Here is a paragraph about pangolins\index{pangolins}.  
Pangolins are the only mammals covered in scales.

Here is a paragraph about meerkats.  Meerkats are immune to 
the venom of scorpions and snakes.

Here is another paragraph about pangolins.  A single pangolin 
can consume 20,000 ants per day.  If you want to learn more about 
pangolins, see page \pages{pangolins}.

Now we talk about elephants\index{elephants|(}
\lipsum[1-10]
End of elephant talk\index{elephants|)}.

Again a unicorn\index{unicorns}.

\end{document}

enter image description here

One could add automatic “page”-“pages” prefixes based on the value stored in the property list.

Multiple indices are supported, but a specific \readindex command should be used for each: \readindex[<index name>], where the name is the file name for the corresponding .idx file.

4

Given the rather precise promises you make (only one index entry per item, only one page reference etc) you could just alter the \index command so that it automatically creates a label with the same name as well. Then you just use the ordinary \pageref command to cross-reference it.

\documentclass{article}
\usepackage{makeidx}

\makeatletter
\def\@wrindex#1{%
\protected@write\@indexfile{}%
{\string\indexentry{#1}{\thepage}}%
\protected@write\@auxout{}%
{\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
\endgroup
\@esphack}
\makeatother

\makeindex

\begin{document}


If \index{pangolins} are referred to here, we can wait a little while and then

\clearpage


Refer to the place (\pageref{pangolins}) where we previously referred to them!

\printindex

\end{document}
  • 1
    It would probably be a good idea to insert an anchor point so that a hyperlink would be a little more localized than just access the page; however, that wasn't part of the question. – barbara beeton Feb 26 at 20:11
  • Note that hyperrref redefines both \@wrindex and \newlabel. – John Kormylo Feb 27 at 16:09
0

And just to round out the answers, a simplistic method that came up in trying various options was to label particular words using \phantomsection and \label and then to use \pageref to place the page number where needed:

\documentclass{book}

\newcommand{\ps}{\phantomsection}

\begin{document}

Here is a paragraph about {\ps}pangolins\label{pangolins}.

Here is another paragraph about pangolins.  If you want to learn more about pangolins, see page \pageref{pangolins}.

\end{document}

This appeared to work in the cases I tried, but I have a limited understanding of what is going on behind the scenes in LaTeX; this approach may be flawed in ways that I haven't appreciated. (Critiques encouraged.)

  • 1
    All you need is \refstepcounter for some counter to set up \label. – John Kormylo Feb 27 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.