9

I am trying to work out a modification of the index in a complex document. The point is, I have a table of contents and so on. But we also want to add an index for specific terms like in:

" .... a so-called analysis of variance \index{analysis of variance}: ......".

Now, with hyperref the command index usually produces an entry to the index which is associated with the page number, then in the index you click on the page number and you get to the correct page. Very good, but we want to make the hyperlink to the SECTION instead of the page. I have found that I can change the way the .idx file is written by makeindex under hyperref, but to get to the end of it I need to insert into the command the label of the section instead of the page number. Now the present version does the page with the "\thepage" command, so I am looking to find something similar for the section by referencing to the section label which would allow things to work fine (I have tried to insert the label manually in the .idx file and it is OK, but I want makeindex to do that.... ;) ). Or, of course, if someone knows of an easier way to solve my original problem, I would be even happier....

  • Welcome to TeX.SX! No variable contains the string of the last label. Maybe it's better to explain your real problem; do you mean the value the label is assigned to? – egreg Nov 19 '14 at 17:00
  • Well the opriginal problem is that I am trying to make an index with hyperlinks to the sections instead of to the pages, which is what the hyperref package does. To do so, I have found that I can chage the way the .idx file is written by makeindex under hyperref, but to get to the end of it I need to insert into the command the label of the section instead of the page number. Now the present version does the page with the "\thepage" command, I was looking for something similar about the section.... I hope I have been more clear this time! Thank you! – Pier Giorgio Nov 19 '14 at 17:02
  • For that use don't you want the section title (or section number) rather than the internal identifier used by label? label values are not intended to ever be printed. – David Carlisle Nov 19 '14 at 17:03
  • @PierGiorgio I think we are going to need a fuller example to see what you mean here: sections are not normally indexed (perhaps you mean a table of contents?). It looks a bit like an 'X-Y' problem (you want to solve X but you've asked Y). – Joseph Wright Nov 19 '14 at 17:06
  • Of course I will want the section number to be printed, but the hyperreference wouldn't work if I didn't provide it with a label. And yes, I know my labels are very long, this is due to the fact that this is a cooperative writing and it is the best way we could find not to make a mess with labels written by different persons........ – Pier Giorgio Nov 19 '14 at 17:07
6

Assumptions:

  • Document class with numbered sections, subsections, and subsubsections.
  • No index entries in unnumbered (sub)(sub)sections.
  • In the index should appear the (sub)(sub)section number instead of the page number.
  • hyperref is loaded.
  • Unspecified is the link target for the section numbers. Should the link go to the start of the section (maybe some pages earlier) or to the indexed page? The example provides both, see the two lines with \hyperlink.
  • Standard anchor generation of hyperref (hypertexnames, naturalnames=false, pageanchor).
  • Arabic (sub)(sub)section numbers.

With these assumptions, the following example patches the index writing to add the (sub)(sub)section values to the page number, constructing a composite page number (Makeindex supports up to ten parts). This also should automatically disable implicit page ranges (don't make too much sense with section numbers).

A project specific style file \jobname.mst redefines some keys to insert a macro in front of the page numbers. Because of the fixed format of the page number curly braces around the argument are not needed.

Then the anchor names can be calculated using the counter values stored in the composite artificial page number of the index entry.

Full example:

% Project specific makeindex style file "\jobname.mst"
% CAUTION: The file "\jobname.mst" will be overwritten
%          without asking, if package "filecontents" is loaded.
\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.mst}
delim_0 ", \\MyIndexPage "
delim_1 ", \\MyIndexPage "
delim_2 ", \\MyIndexPage "
delim_3 ", \\MyIndexPage "
delim_n ", \\MyIndexPage "
delim_r "--\\MyIndexPage "
encap_prefix "\\MyEncap\\"
encap_infix "{\\MyIndexPage "
encap_suffix "}"
\end{filecontents*}

\documentclass{article}

\usepackage{makeidx}
\makeindex

\usepackage{etoolbox}
\makeatletter
\patchcmd{\@wrindex}{\thepage}{%
  \thepage
  -% page compositor
  \the\value{section}%
  -% page compositor
  \the\value{subsection}%
  -% page compositor
  \the\value{subsubsection}%
  -42% end tag
}{}{%
  \errmessage{Could not patch \string\@wrindex}%
}

\@addtoreset{subsubsection}{section}% before hyperref

\newcommand*{\MyEncap}{\@gobble{MyEncap}}
\newcommand*{\MyIndexPage}{%
  \@ifnextchar{\MyEncap}{}{\@MyIndexPage}%
}
\def\@MyIndexPage #1-#2-#3-#4-42{%
  % #1: \thepage
  % #2: \value{section}
  % #3: \value{subsection}
  % #4: \value{subsubsection}
  \edef\SectionNumber{%
    \number#2%
    \ifnum#3>0 %
      .\number#3%
      \ifnum#4>0 %
        .\number#4%
      \fi
    \fi
  }%
  \edef\SectionAnchor{%
    \ifnum#4>0 %
      subsubsection.\number#2.\number#3.\number#4%
    \else
      \ifnum#3>0 %
        subsection.\number#2.\number#3%
      \else
        section.\number#2%
      \fi
    \fi  
  }%
  % \hyperlink{page.#1}{\SectionNumber}% link to page
  \hyperlink{\SectionAnchor}{\SectionNumber}% link to start of section
}


\usepackage[
  hyperindex=false,
  colorlinks,
]{hyperref}
\usepackage{bookmark}
\bookmarksetup{
  open,
  numbered,
}

\begin{document}

\section{First section}
\index{First}
\index{Section}
\index{Section!First}
\index{Foo|see{bar}}

\section{Second section}
\index{Second}
\index{Section}
\index{Section!Second}

\subsection{First subsection}
\index{First}
\index{Subsection}
\index{Subsection!First|textbf}

\subsubsection{First subsubsection}
\index{First}
\index{Subsubsection}
\index{Subsubsection!First|textit}

\subsection{Second subsection}
\index{Second}
\index{Subsection}
\index{Subsection!Second}

\subsection{Third subsection}
\index{Third}
\index{Subsection}
\index{Subsection!Third}

\subsubsection{Second subsubsection}
\index{Second}
\index{Subsubsection}
\index{Subsubsection!Second}

\addtocounter{subsection}{6}
\subsection{Last subsection}
\index{Last|fbox}
\index{Subsection}
\index{Subsection!Last}

\printindex
\end{document}

The raw index file \jobname.idx:

\indexentry{First}{1-1-0-0-42}
\indexentry{Section}{1-1-0-0-42}
\indexentry{Section!First}{1-1-0-0-42}
\indexentry{Foo|see{bar}}{1-1-0-0-42}
\indexentry{Second}{1-2-0-0-42}
\indexentry{Section}{1-2-0-0-42}
\indexentry{Section!Second}{1-2-0-0-42}
\indexentry{First}{1-2-1-0-42}
\indexentry{Subsection}{1-2-1-0-42}
\indexentry{Subsection!First|textbf}{1-2-1-0-42}
\indexentry{First}{1-2-1-1-42}
\indexentry{Subsubsection}{1-2-1-1-42}
\indexentry{Subsubsection!First|textit}{1-2-1-1-42}
\indexentry{Second}{1-2-2-0-42}
\indexentry{Subsection}{1-2-2-0-42}
\indexentry{Subsection!Second}{1-2-2-0-42}
\indexentry{Third}{1-2-3-0-42}
\indexentry{Subsection}{1-2-3-0-42}
\indexentry{Subsection!Third}{1-2-3-0-42}
\indexentry{Second}{1-2-3-1-42}
\indexentry{Subsubsection}{1-2-3-1-42}
\indexentry{Subsubsection!Second}{1-2-3-1-42}
\indexentry{Last|fbox}{1-2-10-0-42}
\indexentry{Subsection}{1-2-10-0-42}
\indexentry{Subsection!Last}{1-2-10-0-42}

The index file \jobname.ind, generated by Makeindex:

\begin{theindex}

  \item First, \MyIndexPage 1-1-0-0-42, \MyIndexPage 1-2-1-0-42, \MyIndexPage 
        1-2-1-1-42
  \item Foo, \MyIndexPage \MyEncap\see{bar}{\MyIndexPage 1-1-0-0-42}

  \indexspace

  \item Last, \MyIndexPage \MyEncap\fbox{\MyIndexPage 1-2-10-0-42}

  \indexspace

  \item Second, \MyIndexPage 1-2-0-0-42, \MyIndexPage 1-2-2-0-42, \MyIndexPage 
        1-2-3-1-42
  \item Section, \MyIndexPage 1-1-0-0-42, \MyIndexPage 1-2-0-0-42
    \subitem First, \MyIndexPage 1-1-0-0-42
    \subitem Second, \MyIndexPage 1-2-0-0-42
  \item Subsection, \MyIndexPage 1-2-1-0-42, \MyIndexPage 1-2-2-0-42, \MyIndexPage 
        1-2-3-0-42, \MyIndexPage 1-2-10-0-42
    \subitem First, \MyIndexPage 
        \MyEncap\textbf{\MyIndexPage 1-2-1-0-42}
    \subitem Last, \MyIndexPage 1-2-10-0-42
    \subitem Second, \MyIndexPage 1-2-2-0-42
    \subitem Third, \MyIndexPage 1-2-3-0-42
  \item Subsubsection, \MyIndexPage 1-2-1-1-42, \MyIndexPage 1-2-3-1-42
    \subitem First, \MyIndexPage 
        \MyEncap\textit{\MyIndexPage 1-2-1-1-42}
    \subitem Second, \MyIndexPage 1-2-3-1-42

  \indexspace

  \item Third, \MyIndexPage 1-2-3-0-42

\end{theindex}

And finally the index on the page:

Result

Update for \see

The first token after \MyIndexPage is the "encap" command (e.g.,\see). Therefore the updated example adds macro \MyEncap before the "encap" command and puts an additional \MyIndexPage before the page number in the argument of the "encap" command via the style file for makeindex:

encap_prefix "\\MyEncap\\"
encap_infix "{\\MyIndexPage "
encap_suffix "}"

Then \MyIndexPage is redefined in such a way, that it ignores itself, if an "encap" command follows, detected by the macro \MyEncap:

\newcommand*{\MyEncap}{\@gobble{MyEncap}}
\newcommand*{\MyIndexPage}{%
  \@ifnextchar{\MyEncap}{}{\@MyIndexPage}%
}
\def\@MyIndexPage #1-#2-#3-#4-42{%
  ...
}
  • There's no need for \RequirePackage{filecontents}. – egreg Nov 19 '14 at 18:41
  • If the contents of the file changes, then I want that it is automatically overwritten. Alternatively the part before \documentclass can be omitted and the file \jobname.mst can be created by an editor directly. – Heiko Oberdiek Nov 19 '14 at 18:55
  • There's a question on the site about a case where a badly named filecontents environment caused deletion of the main file. You certainly know how to use the package and the environment, my concern is about the newbies. – egreg Nov 19 '14 at 20:32
  • @egreg I have added a warning hint in the source code. – Heiko Oberdiek Nov 20 '14 at 5:40
  • @Heiko, your solution works very well, with some modifications I could do almost all I needed to do, but now I am stuck again, what happens is that I now need to add a \see command for some of the index entries, now having the \myindex before the \see does not allow it to work properly (for the \see, I do not want any hyperlink, just writing the argument of the \see); I tried to delete manually the \myindex from the .ind file, and it works fine, now I am trying to skip it automatically, any idea how I could do? – Pier Giorgio Nov 26 '14 at 16:51

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.