Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hyperref shifts location of "see" and "see also" in index #243

Open
CDChao opened this issue Jun 4, 2022 · 5 comments
Open

Hyperref shifts location of "see" and "see also" in index #243

CDChao opened this issue Jun 4, 2022 · 5 comments

Comments

@CDChao
Copy link

CDChao commented Jun 4, 2022

First a minimal working example is as follows.

\documentclass{report}

\usepackage{makeidx}
\makeindex

\usepackage{hyperref}

\begin{document}
  foo\index{foo}\index{foo|seealso{bar}}
  foo\index{foo}
  bar\index{bar}
  \printindex
\end{document}

Index page output without the \usepackage{hyperref} line is as follows. The last output line correctly sees the pageno located before the see also reference.

Index
bar, 1
foo, 1, see also bar

However, index page output including the \usepackage{hyperref} line incorrectly/undesirably relocates the see also reference before the pageno.

Index
bar, 1
foo, see also bar, 1

Question: How can I have my cake and eat it too, i.e., include hyperref but locate pageno references before see and see also index entry text as in the output without hyperref?

Could hyperref fix the question?

@muzimuzhi
Copy link
Contributor

@CDChao
Copy link
Author

CDChao commented Jun 4, 2022

Similar: Hyperref shifts location of "see" and "see also" in index. How to restore? on TeX-SX

While the solution in the link doesn't work as before since it produces no hyperlinks on pagenoes any more. Also I think it should be a bug of hyperref.

@muzimuzhi
Copy link
Contributor

muzimuzhi commented Jun 5, 2022

While the solution in the link doesn't work as before since it produces no hyperlinks on pagenoes any more.

No hyperlinks on page numbers, really? In some examples of that answer, although package option hyperindex=false is used, hyperlink commands like \hyperpage are added back through .ist files.

When two indices share the same entry are

  • on different pages, then they're ordered by page numbers;
  • on the same page, and only one has encap field, like \index{foo}\index{foo|seealso{bar}}, then the one without encap comes first (that's why see also comes last in your example, without hyperref);
  • on the same page, and both have encap field, then they're ordered by their encap fields/strings, see relevant lines in makeindex's source file.

The third case is the case when hyperref is loaded with default setting hyperindex=true. It converts \index{foo} and \index{foo|seealso{bar}} to \indexentry{foo|hyperpage}{1} and \indexentry{foo|hyperindexformat{\seealso{bar}}}{1}, respectively. Then since i < p, see also comes first.

Inn the latex step which generates .idx, it may be impossible to keep two group of index entries having the same order:

  • \indexentry{foo}{1} and \indexextry{foo|seealso{bar}}{1}
  • \indexentry{foo|<encap1>}{1} and \indexentry{foo|<encap2>{\seealso{bar}}}{1}

But it's feasible to solve the problem in the makeindex step, which generates .ind from .idx, with a .ist style file. hyperref package manual, sec. 13.2 Index with makeindex contains one such .ist example, but it seems it doesn't work for entries with encap. Here's my attempt:

\begin{filecontents}[noheader, force]{hyperpage.ist}
delim_0 ", \\hyperpageIdx{"
delim_1 ", \\hyperpageIdx{"
delim_2 ", \\hyperpageIdx{"
delim_n "}\\nil, \\hyperpageIdx{"
delim_t "}\\nil"
encap_prefix "\\"
encap_infix "}{{"
encap_suffix "}"
\end{filecontents}

\documentclass{article}
\usepackage{makeidx}
\makeindex

\usepackage{etoolbox} % for \ifstrempty
\usepackage[hyperindex=false]{hyperref}

% no encap,   e.g., \hyperpageIdx{1}\relax
% with encap, e.g., \hyperpageIdx{\seealso{bar}}{{2}}\relax
\def\hyperpageIdx#1#2\nil{%
  \ifstrempty{#2}
    {\hyperpage{#1}}
    {\ignorespaces#1{\hyperpage#2}}%
}

\def\seexalso#1#2{\emph{see xalso} #1} % "a" < "x" so "seealso" < "seexalso" 
\begin{document}
  text\index{bar}
  \index{diff pages I}
  \index{diff pages II|seealso{bar}}
  \index{same page, one encaped}
    \index{same page, one encaped|seealso{bar}}
  \index{same page, both encaped|seealso{bar}}
    \index{same page, both encaped|seexalso{bar}}
  \newpage

  text
  \index{diff pages I|seealso{bar}}
  \index{diff pages II}
  
  \printindex
\end{document}

image

@CDChao
Copy link
Author

CDChao commented Jun 5, 2022

While the solution in the link doesn't work as before since it produces no hyperlinks on pagenoes any more.

No hyperlinks on page numbers, really? In some examples of that answer, although package option hyperindex=false is used, hyperlink commands like \hyperpage are added back through .ist files.

When two indices share the same entry are

  • on different pages, then they're ordered by page numbers;
  • on the same page, and only one has encap field, like \index{foo}\index{foo|seealso{bar}}, then the one without encap comes first (that's why see also comes last in your example, without hyperref);
  • on the same page, and both have encap field, then they're ordered by their encap fields/strings, see relevant lines in makeindex's source file.

The third case is the case when hyperref is loaded with default setting hyperindex=true. It converts \index{foo} and \index{foo|seealso{bar}} to \indexentry{foo|hyperpage}{1} and \indexentry{foo|hyperindexformat{\seealso{bar}}}{1}, respectively. Then since i < p, see also comes first.

Inn the latex step which generates .idx, it may be impossible to keep two group of index entries having the same order:

  • \indexentry{foo}{1} and \indexextry{foo|seealso{bar}}{1}
  • \indexentry{foo|<encap1>}{1} and \indexentry{foo|<encap2>{\seealso{bar}}}{1}

But it's feasible to solve the problem in the makeindex step, which generates .ind from .idx, with a .ist style file. hyperref package manual, sec. 13.2 Index with makeindex contains one such .ist example, but it seems it doesn't work for entries with encap. Here's my attempt:

\begin{filecontents}[noheader, force]{hyperpage.ist}
delim_0 ", \\hyperpageIdx{"
delim_1 ", \\hyperpageIdx{"
delim_2 ", \\hyperpageIdx{"
delim_n "}\\nil, \\hyperpageIdx{"
delim_t "}\\nil"
encap_prefix "\\"
encap_infix "}{{"
encap_suffix "}"
\end{filecontents}

\documentclass{article}
\usepackage{makeidx}
\makeindex

\usepackage{etoolbox} % for \ifstrempty
\usepackage[hyperindex=false]{hyperref}

\makeatletter
% no encap,   e.g., \hyperpageIdx{1}\relax
% with encap, e.g., \hyperpageIdx{\seealso{bar}}{{2}}\relax
\def\hyperpageIdx#1#2\nil{%
  \ifstrempty{#2}
    {\hyperpage{#1}}
    {\ignorespaces#1{\hyperpage#2}}%
}
\makeatother

\def\seexalso#1#2{\emph{see xalso} #1} % "a" < "x" so "seealso" < "seexalso" 
\begin{document}
  text\index{bar}
  \index{diff pages I}
  \index{diff pages II|seealso{bar}}
  \index{same page, one encaped}
    \index{same page, one encaped|seealso{bar}}
  \index{same page, both encaped|seealso{bar}}
    \index{same page, both encaped|seexalso{bar}}
  \newpage

  text
  \index{diff pages I|seealso{bar}}
  \index{diff pages II}
  
  \printindex
\end{document}

image

I don't know why this doesn't work in MacTeX 2022 which is used on my Mac.

@muzimuzhi
Copy link
Contributor

Did you specify makeindex -s hyperpage.ist <main>?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants