[Tex/LaTex] Get the value of current \label

cross-referencing

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….

Best Answer

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{%
  ...
}
Related Question