15

Is it possible to direct the hyperlink created by \gls{term} to the first use of the term in the main text instead of the glossary list?

I'm writing a thesis that uses a lot of abbreviations, but I don't want to include a glossary list in the document. Rather, I'd like to define each abbreviation on first use but provide a hyperlink to the first use during all subsequent uses of the abbreviation. Is this possible?

The following is an example of the code I'm currently using to set-up the glossaries and hyperref packages and define a term:

\documentclass{report}
\usepackage[acronym,hyperfirst=false,nonumberlist,nowarn]{glossaries}
\usepackage[hidelinks]{hyperref}
...
\newacronym{FEA}{FEA}{Finite Element Analysis}
...
\begin{document}
    ...this includes a \gls{FEA} tool to...    % first use of term
    ...the \gls{FEA} tool...                   % subsequent uses of term, want to hyperlink to first use above within PDF
\end{document}

2 Answers 2

10

I recommend you upgrade to the latest version of glossaries (v4.01 at time of writing) and try the following:

\documentclass{report}

\usepackage[colorlinks]{hyperref}
\usepackage[acronym,nowarn,hyperfirst=false]{glossaries}

% Switch off hyperlinks for all uses of \gls etc.
% Hyperlinks will be inserted manually in the custom display style
\setkeys{glslink}{hyper=false}

\renewcommand*{\CustomAcronymFields}{%
  name={\the\glsshorttok},%
  description={\the\glslongtok},%
}

\renewcommand*{\SetCustomDisplayStyle}[1]{%
  \defglsentryfmt[#1]{%
    \ifdefempty\glscustomtext
    {%
      \ifglsused\glslabel
      {% subsequent use
       % Assuming all acronyms are written in upper case, so
       % not bother to check for case changes.
        \glsifplural
        {% subsequent use, plural
          \glshyperlink[\glsentryshortpl{\glslabel}]{\glslabel}%
        }%
        {% subsequent use, singular
          \glshyperlink[\glsentryshort{\glslabel}]{\glslabel}%
        }%
      }%
      {% first use
        \glsifplural
        {% first use, plural
          \glscapscase
          {% no case change
            \glstarget{\glslabel}{\glsentrylongpl{\glslabel}\glsinsert}%
            \space(\glsentryshortpl{\glslabel})%
          }%
          {% first letter upper case
            \glstarget{\glslabel}{\Glsentrylongpl{\glslabel}\glsinsert}%
            \space(\glsentryshortpl{\glslabel})%
          }%
          {% all caps
            \glstarget{\glslabel}{\MakeTextUppercase{%
              \glsentrylongpl{\glslabel}\glsinsert}}%
            \MakeTextUppercase{\space(\glsentryshortpl{\glslabel})}%
          }%
        }%
        {% first use, singular
          \glscapscase
          {% no case change
            \glstarget{\glslabel}{\glsentrylong{\glslabel}\glsinsert}%
            \space(\glsentryshort{\glslabel})%
          }%
          {% first letter upper case
            \glstarget{\glslabel}{\Glsentrylong{\glslabel}\glsinsert}%
            \space(\glsentryshort{\glslabel})%
          }%
          {% all caps
            \glstarget{\glslabel}{\MakeTextUppercase{%
              \glsentrylong{\glslabel}\glsinsert}}%
            \MakeTextUppercase{\space(\glsentryshort{\glslabel})}%
          }%
        }%
      }%
    }%
    {% \glsdisp used
      \ifglsused\glslabel
      {% subsequent use
        \glshyperlink[\glscustomtext]{\glslabel}%
      }%
      {% first use
        \glstarget{\glslabel}{\glscustomtext}%
      }%
    }%
  }%
}

\SetCustomStyle

\newacronym{FEA}{FEA}{Finite Element Analysis}

\begin{document}

First use: \gls{FEA}.

Next use: \gls{FEA}.

\end{document}

I've used the colorlinks option so you can see where the link is in the result:

Image of resulting document

The link target is the first use. Be careful not to reset the acronyms (via \glsreset etc) or you'll end up with multiply defined targets.

Edit: there's a simpler method with the glossaries-extra extension package:

\documentclass{article}
\usepackage[colorlinks]{hyperref}
\usepackage{glossaries-extra}

\setabbreviationstyle[acronym]{long-short}

\glssetcategoryattribute{acronym}{nohyperfirst}{true}

\renewcommand*{\glsdonohyperlink}[2]{%
 {\glsxtrprotectlinks \glsdohypertarget{#1}{#2}}}

\newacronym{FEA}{FEA}{Finite Element Analysis}

\begin{document}

First use: \gls{FEA}.

Next use: \gls{FEA}.

\end{document}

This will create a target when the hyperlink is suppressed. This can cause a problem if you reset the first use flag or if you want to use the starred version \gls*. A minor modification can keep track of whether the target has been set:

\documentclass{article}
\usepackage[colorlinks]{hyperref}
\usepackage{glossaries-extra}

\setabbreviationstyle[acronym]{long-short}

\glssetcategoryattribute{acronym}{nohyperfirst}{true}

\renewcommand*{\glsdonohyperlink}[2]{%
 {\glsxtrprotectlinks 
   \edef\fieldvalue{\glsxtrusefield{\glslabel}{hastarget}}%
   \ifdefstring\fieldvalue{true}
   {%
     #2%
   }%
   {%
     \gGlsXtrSetField{\glslabel}{hastarget}{true}\glsdohypertarget{#1}{#2}%
   }%
 }%
}

\newacronym{FEA}{FEA}{Finite Element Analysis}

\begin{document}

First use: \gls{FEA}.

Next use: \gls{FEA}.

No hyperlink: \gls*{FEA}.

Another use: \gls{FEA}.

\end{document}
1
  • Thanks, Nicola! That works perfectly - although it should be noted for others that you do need the latest update of glossaries to allow the commant \SetCustomStyle (v4.01 at the time of writing). Commented Nov 23, 2013 at 18:41
0

Not an answer this, more of a bug report but it doesn't fit in a comment, sorry...

In my document, I used \setacronymstyle in the text multiple times, so I can change the acronym first use output from long-short to short-long. Note that there is a very subtle bug when using @Nicola Talbot's answer in this context, and that is:

Once you use \setacronymstyle, first the "name" entry in the .glsdefs file changes:

$ grep name test.glsdefs
name={JAA1},%
name={\acronymfont {\glsentryshort {JAA2}}},%
name={\acronymfont {\glsentryshort {JAA3}}},%
name={\acronymfont {\glsentryshort {JAA4}}},%

... but that seems to be not as much of a problem -- as the fact that after the use of that command, the \gls@acronym@entryfmt format command changes from "standalone" code that includes \glshyperlink and \glstarget; to \GlsUseAcrEntryDispStyle {long-short} which eventually calls e.g. \glsgenacfmt which is similar "standalone" code, but which uses no hyperlinks targets (apparently because \setkeys{glslink}{hyper=false}). And as far as I can see, trying to work around this while using \setacronymstyle is possible - that is, it is possible to restore the hyperlinks, but in that case \setacronymstyle will simply have no effect (i.e. long-short would not change to short-long).

EDIT: Actually, the fix seems to be to use, in the MWE below:

% \let\glsgenacfmt\oldglsgenacfmt % this allows that the short-long effect is back; but unfortunately there are no hyperlink targets in it
\def\glsgenacfmt{\glstarget{\glslabel}{\oldglsgenacfmt}} % this makes link targets work!

... that is, temporarily make a new definition, which you'll manually wrap in a link target.

Here is an MWE that demonstrates that (see comments inside):

\documentclass[a4paper]{book}

\usepackage{lipsum}
\usepackage{xcolor}
\usepackage{hyperref}
\colorlet{mycolr}{red}
\hypersetup{colorlinks=true, citecolor=mycolr, filecolor=mycolr, linkcolor=mycolr, urlcolor=mycolr}

\usepackage[acronym,hyperfirst=false,nomain]{glossaries}
% nomain "This suppresses the creation of the main glossary and associated .glo file, if unrequired."
% hyperfirst "This is a boolean option that specifies whether each term has a hyperlink on first use."
% acronym "This creates a new glossary with the label acronym."
\setkeys{glslink}{hyper=true}
\setacronymstyle{long-short}
\let\oldglsgenacfmt\glsgenacfmt

% https://tex.stackexchange.com/questions/140666/glossaries-hyperlink-to-first-entry-not-list-of-acronyms
% Switch off hyperlinks for all uses of \gls etc.
% Hyperlinks will be inserted manually in the custom display style
\setkeys{glslink}{hyper=false}

\renewcommand*{\CustomAcronymFields}{%
  name={\the\glsshorttok},%
  description={\the\glslongtok},%
}

\renewcommand*{\SetCustomDisplayStyle}[1]{%
  \defglsentryfmt[#1]{%
    \ifdefempty\glscustomtext
    {%
      \ifglsused\glslabel
      {% subsequent use
       % Assuming all acronyms are written in upper case, so
       % not bother to check for case changes.
        \glsifplural
        {% subsequent use, plural
          \glshyperlink[\glsentryshortpl{\glslabel}]{\glslabel}%
        }%
        {% subsequent use, singular
          \glshyperlink[\glsentryshort{\glslabel}]{\glslabel}%
        }%
      }%
      {% first use
        \glsifplural
        {% first use, plural
          \glscapscase
          {% no case change
            \glstarget{\glslabel}{\glsentrylongpl{\glslabel}\glsinsert}%
            \space(\glsentryshortpl{\glslabel})%
          }%
          {% first letter upper case
            \glstarget{\glslabel}{\Glsentrylongpl{\glslabel}\glsinsert}%
            \space(\glsentryshortpl{\glslabel})%
          }%
          {% all caps
            \glstarget{\glslabel}{\MakeTextUppercase{%
              \glsentrylongpl{\glslabel}\glsinsert}}%
            \MakeTextUppercase{\space(\glsentryshortpl{\glslabel})}%
          }%
        }%
        {% first use, singular
          \glscapscase
          {% no case change
            \glstarget{\glslabel}{\glsentrylong{\glslabel}\glsinsert}%
            \space(\glsentryshort{\glslabel})%
          }%
          {% first letter upper case
            \glstarget{\glslabel}{\Glsentrylong{\glslabel}\glsinsert}%
            \space(\glsentryshort{\glslabel})%
          }%
          {% all caps
            \glstarget{\glslabel}{\MakeTextUppercase{%
              \glsentrylong{\glslabel}\glsinsert}}%
            \MakeTextUppercase{\space(\glsentryshort{\glslabel})}%
          }%
        }%
      }%
    }%
    {% \glsdisp used
      \ifglsused\glslabel
      {% subsequent use
        \glshyperlink[\glscustomtext]{\glslabel}%
      }%
      {% first use
        \glstarget{\glslabel}{\glscustomtext}%
      }%
    }%
  }%
}

\SetCustomStyle

\makeatletter
\def\printDefs#1{%
  \typeout{\space\space\space
    newacronym #1 is:
    \meaning\newacronym
  }%
  \typeout{\space\space\space
    \\newacronym #1 is:
    \expandafter\meaning\csname\string\newacronym\endcsname
  }%
  \typeout{\space\space\space
    gls #1 is:
    \meaning\gls
  }%
  \typeout{\space\space\space
    \\@gls #1 is:
    \expandafter\meaning\csname\string\@gls\endcsname
  }%
  \typeout{\space\space\space
    gls@acronym@entryfmt #1 is:
    \meaning\gls@acronym@entryfmt
  }%
  \typeout{\space\space\space
    glsgenacfmt #1 is:
    \meaning\glsgenacfmt
  }%
  \typeout{\space\space\space
    glsgenentryfmt #1 is:
    \meaning\glsgenentryfmt
  }%
  \typeout{\space\space\space}
}
\makeatother
% \GlsUseAcrEntryDispStyle: macro:#1->\csuse {@glsacr@dispstyle@#1}
% \@glsacr@dispstyle@long-short: macro:->\ifglshaslong {\glslabel }{\glsgenacfmt }{\glsgenentryfmt }
% default: gls@acronym@entryfmt

\begin{document}

\section{Testing}

% \let\oldnewacronym\newacronym% no can do; doesn't actually change (protected)
\makeatletter
\let\oldacronymentryfmt\gls@acronym@entryfmt
\makeatother

Testing first:
\newacronym{JAA1}{JAA1}{just another acronym One}%
\gls{JAA1}%
\printDefs{1}

\setacronymstyle{long-short} % this changes things!!! kills all the hyperlinks, even if there is a previously correct .glsdefs file (generated if this line is commented)!

Testing second:
\newacronym{JAA2}{JAA2}{just another acronym Two}%
\gls{JAA2}%
\printDefs{2}

% \let\oldglsgenacfmt\glsgenacfmt % now in preamble
\let\glsgenacfmt\oldacronymentryfmt % this restores all hyperlinks again, but the second one will be broken!
Testing third:
\newacronym{JAA3}{JAA3}{just another acronym Three}%
\gls{JAA3}%
\printDefs{3}

\setkeys{glslink}{hyper=true}% no effect
\setacronymstyle{short-long} % now does not kill links, but has no effect
\let\glsgenacfmt\oldglsgenacfmt % this allows that the short-long effect is back; but unfortunately there are no hyperlink targets in it
Testing fourth:
\newacronym{JAA4}{JAA4}{just another acronym Four}%
\gls{JAA4}%
\setkeys{glslink}{hyper=false}
\let\glsgenacfmt\oldacronymentryfmt % again this, to restore links for below commands


Testing refs: \gls{JAA1} and \gls{JAA2} and \gls{JAA3} and \gls{JAA4} % here 1 and 3 work, 2 and 4 are broken

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .