[Tex/LaTex] One hyperref per acronym per page

acronymshyperref

Currently, I'm using the acronym package to keep my thesis clear and understandable, because it is quite heavy on the use of acronyms in some parts. Because of this, some pages have so many acronyms, that they more or less look like someone went haywire with a blue text coloring tool.

So my question is: is it possible for either the acronym package, or the hyperref package, to only use one hyperref per acronym per page? So if one encounters an acronym for the first time on a page, he will be able to click on it and taken to the acronym definition list. The rest of the same acronyms on the same page will be printed without link.

I do not know if it is even possible for LaTeX to have this kind of 'reflection' on pages and links while compiling the document. Searching on this provided no results, which is why I'm resorting to the gurus over here.

Best Answer

I don't know how to achieve what you want with the acronym package, but here's a solution that uses glossaries. In order to get it as close as possible to the acronym package, I've used the shortcuts, nonumberlist, nogroupskip and nopostdot package options and used new commands introduced in glossaries version 4.04 that allow you to create the list of acronyms without the need to use makeindex or xindy. You just need to use pdflatex twice to make the list of acronyms appear.

\documentclass{report}

\usepackage{lipsum} % dummy text

\usepackage{etoolbox}
\usepackage[colorlinks]{hyperref}
\usepackage
 [
   acronyms,% create list of acronyms
   nohypertypes={acronym},% disable automated hyperlinks
   shortcuts,% enable acronym-like commands
   nonumberlist,% suppress location list
   nogroupskip,% suppress gap between letter groups
   nopostdot% suppress terminating full stop after descriptions
 ]{glossaries}

% Adjust the way entries are displayed:

\newif\ifshowacrlink

\newacronymstyle{long-short-hyperlinkperpage}
{%
  \ifglsused{\glslabel}%
  {%
    \ifcsdef{ac@curpg@\glslabel}%
    {%
      \edef\thispage{\thepage}%
      \ifcsequal{ac@curpg@\glslabel}{thispage}%
      {% on the same page
        \showacrlinkfalse
      }%
      {% now on a new page
        \showacrlinktrue
        \csedef{ac@curpg@\glslabel}{\thepage}%
      }%
    }%
    {%
      \csedef{ac@curpg@\glslabel}{\thepage}%
      \showacrlinktrue
    }%
  }%
  {%
    % don't hyperlink on first use:
    \showacrlinkfalse
  }%
  \ifshowacrlink
    \glshyperlink[\glsgenacfmt]{\glslabel}%
  \else
    \glsgenacfmt
  \fi
}%
{%
  \GlsUseAcrStyleDefs{long-short}%
}%

\setacronymstyle{long-short-hyperlinkperpage}

\makenoidxglossaries

\newacronym{html}{HTML}{hypertext markup language}
\newacronym{xml}{XML}{extensible markup language}

\begin{document}

\chapter{Sample Chapter}

First use: \ac{html}, \ac{xml}.
Subsequent use: \ac{html}, \ac{xml}.

Filler text: \lipsum[1]

Use acronyms again: \ac{html}, \ac{xml}.

More filler text: \lipsum[2]

Use acronyms again: \ac{html}, \ac{xml} and have a page spanning
paragraph of filler text. \lipsum*[3] Use acronyms again: \ac{html},
\ac{xml}.

Next paragraph: \ac{html}, \ac{xml}.
And again: \ac{html}, \ac{xml}.

\printnoidxglossary
[
  type=acronym,% list of acronyms
  sort=def% list in order of definition
]

\end{document}

First page:

Image of first page

Second page:

Image of second page

Third page:

Image of third page

The only drawback with this approach is the old problem of the page number not getting updated until the page-spanning paragraph has been completed. (See Page number is wrong at start of page.) It would require a bit of trickery with writing the page number to the aux file to fix it.

Edit:

I've just uploaded glossaries version 4.06 to CTAN. (It make take a few days to get across all the mirrors and into the TeX distributions.) This version introduces a new command (\glsifhyper) that can be used within the acronym style to determine if the starred or non-starred version of commands like \ac was used. This means you can force off the hyperlink for individual entries (although you might want to wait until the final version of your document before you make such manual adjustments).

Updated MWE:

\documentclass{report}

\usepackage{lipsum} % dummy text

\usepackage{etoolbox}
\usepackage[colorlinks]{hyperref}

\usepackage
 [
   acronyms,% create list of acronyms
   nohypertypes={acronym},% disable automated hyperlinks
   shortcuts,% enable acronym-like commands
   nonumberlist,% suppress location list
   nogroupskip,% suppress gap between letter groups
   nopostdot% suppress terminating full stop after descriptions
 ]{glossaries}

% Adjust the way entries are displayed:

\newif\ifshowacrlink

\newacronymstyle{long-short-hyperlinkperpage}
{%
  \glsifhyper
  {% unstarred version used
    \ifglsused{\glslabel}%
    {%
      \ifcsdef{ac@curpg@\glslabel}%
      {%
        \edef\thispage{\thepage}%
        \ifcsequal{ac@curpg@\glslabel}{thispage}%
        {% on the same page
          \showacrlinkfalse
        }%
        {% now on a new page
          \showacrlinktrue
          \csedef{ac@curpg@\glslabel}{\thepage}%
        }%
      }%
      {%
        \csedef{ac@curpg@\glslabel}{\thepage}%
        \showacrlinktrue
      }%
    }%
    {%
      % don't hyperlink on first use:
      \showacrlinkfalse
    }%
  }%
  {% starred version has been used so switch off the link:
     \showacrlinkfalse
  }%
  \ifshowacrlink
    \glshyperlink[\glsgenacfmt]{\glslabel}%
  \else
    \glsgenacfmt
  \fi
}%
{%
  \GlsUseAcrStyleDefs{long-short}%
}%

\setacronymstyle{long-short-hyperlinkperpage}

\makenoidxglossaries

\newacronym{html}{HTML}{hypertext markup language}
\newacronym{xml}{XML}{extensible markup language}

\begin{document}

\chapter{Sample Chapter}

First use: \ac{html}, \ac{xml}.
Subsequent use: \ac{html}, \ac{xml}.

Filler text: \lipsum[1]

Use acronyms again: \ac{html}, \ac{xml}.

More filler text: \lipsum[2]

Use acronyms again: \ac{html}, \ac{xml} and have a page spanning
paragraph of filler text. \lipsum*[3] Use acronyms again: \ac{html},
\ac{xml}.

Next paragraph: \ac{html}.
Suppress the link on this one: \ac*{xml}.
And again: \ac{html}, \ac{xml}.

\printnoidxglossary
[
  style=tree,%
  type=acronym,% list of acronyms
  sort=def% list in order of definition
]

\end{document}

The second page looks like:

Image of second page

Update:

Here's a solution using glossaries-extra (at least v1.08). It's slightly different from the above in that it has a hyperlink on first use, whereas with the above examples the first hyperlink is the first subsequent use. (The problem with the page-spanning paragraph is still present.) The glossaries-extra package automatically implements the nopostdot option, so I've omitted it from the option list.

\documentclass{report}

\usepackage{lipsum}
\usepackage[colorlinks]{hyperref}
\usepackage
[
   acronyms,% create list of acronyms
   shortcuts,% enable acronym-like commands
   nogroupskip% suppress gap between letter groups
]{glossaries-extra}

\GlsXtrEnableEntryUnitCounting{acronym}{0}{page}

\setabbreviationstyle[acronym]{long-short}

\newacronym{html}{HTML}{hypertext markup language}
\newacronym{xml}{XML}{extensible markup language}

\renewcommand*{\glslinkcheckfirsthyperhook}{%
  \ifnum\glsentrycurrcount\glslabel>0
   \setkeys{glslink}{hyper=false}%
  \fi
}

\begin{document}
\chapter{Sample Chapter}

First use: \ac{html}, \ac{xml}.
Subsequent use: \ac{html}, \ac{xml}.

Filler text: \lipsum[1]

Use acronyms again: \ac{html}, \ac{xml}.

More filler text: \lipsum[2]

Use acronyms again: \ac{html}, \ac{xml} and have a page spanning
paragraph of filler text. \lipsum*[3] Use acronyms again: \ac{html},
\ac{xml}.

Next paragraph: \ac{html}.
Suppress the link on this one: \ac*{xml}.
And again: \ac{html}, \ac{xml}.

\printunsrtglossary[type=\acronymtype]

\end{document}

This uses the entry-counting mechanism to switch off the hyperlink. It also uses a new command \printunsrtglossary rather than the \makenoidxglossaries and \printnoidxglossary combination. The \printunsrtglossary command is the closest match to the acronym package as it doesn't sort or produce a location list, but simply lists the terms in the order of definition. This means you only need to use pdflatex once to make the list appear.

Start of first page:

image of top of first page

Second page:

image of second page

Related Question