The first letter upper case commands, such as \Gls
, use \makefirstuc
which requires its argument to either be just text or in the form \\
command{
text}
(e.g. \makefirstuc{\emph{text}}
is equivalent to \emph{\MakeUppercase{t}ext}
). What your code is attempting to do is \makefirstuc{\gls{RangeExpansion}}
which becomes \gls{\MakeUppercase{R}angeExpansion}
and the error occurs because \MakeUppercase{R}angeExpansion
is an invalid label.
Another problem with your definition is that you get nested links where \gls{RE}
is attempting to be a hyperlink both to the RE
entry in the list of acronyms and to the RangeExpansion
entry in the main glossary.
A better approach, which overcomes both the above issues is to do something like:
\documentclass{article}
\usepackage[colorlinks]{hyperref}
\usepackage[acronym,description]{glossaries}
\makeglossaries
% Define command to create linked entries
% Syntax:
% \newlinkedacr[options]{entry-label}{acr-label}{short}{long}{description}
\newcommand*{\newlinkedacr}[6][]{%
\newglossaryentry{#2}{name={#5},description={#6},#1}%
\newacronym[description={\gls{#2}}]{#3}{#4}{#5}%
}
\newlinkedacr
{RangeExpansion}% main entry label
{RE}% acronym label
{RE}% abbreviation
{range expansion}% long form
{A range expansion etc}% description
\begin{document}
First use: \gls{RE}. Subsequent use: \gls{RE}.
\glsresetall
First use: \Gls{RE}. Subsequent use: \Gls{RE}.
\printglossaries
\end{document}
Here, the description in the acronym list forms a hyperlink to the entry in the main glossary. The acronyms in the main body of the document link to the entry in the list of acronyms. If you prefer the long form in the first use to link to the main glossary rather than the list of acronyms, then this can be achieved although it's more complicated. The following example requires at least v4.0 of glossaries
:
\documentclass{article}
\usepackage[colorlinks]{hyperref}
\usepackage[acronym,hyperfirst=false]{glossaries}
\makeglossaries
% Define command to create linked entries
% Syntax:
% \newlinkedacr[options]{entry-label}{acr-label}{short}{long}{description}
\newcommand*{\newlinkedacr}[6][]{%
\newglossaryentry{#2}{name={#5},description={#6},#1}%
\newacronym[description={\glshyperlink{#2}},user1={#2}]{#3}{#4}{#5}%
}
\renewcommand*{\CustomAcronymFields}{name={\the\glsshorttok}}
\renewcommand*{\SetCustomDisplayStyle}[1]{%
\defglsentryfmt[#1]{%
\ifdefempty\glscustomtext
{%
\ifglsused\glslabel
{% subsequent use
\glsgenentryfmt
}%
{% First use
% Get the label of the corresponding main entry (stored in
% user1 field)
\edef\mainlabel{\glsentryuseri{\glslabel}}%
% If empty, then there's no linked entry
\ifdefempty\mainlabel
{% use generic format
\glsgenentryfmt
}%
{%
\glsifplural
{% plural form
\glscapscase
{% no case change
\glshyperlink[\glsentrylongpl{\glslabel}\glsinsert]{\mainlabel}%
\space (\glsentryshortpl{\glslabel})%
}%
{% first letter uppercase
\glshyperlink[\Glsentrylongpl{\glslabel}\glsinsert]{\mainlabel}%
\space (\glsentryshortpl{\glslabel})%
}%
{% all caps
\glshyperlink[\MakeTextUppercase{%
\glsentrylongpl{\glslabel}\glsinsert}]{\mainlabel}%
\MakeTextUppercase{\space (\glsentryshortpl{\glslabel})}%
}%
}%
{% singular form
\glscapscase
{% no case change
\glshyperlink[\glsentrylong{\glslabel}\glsinsert]{\mainlabel}%
\space (\glsentryshort{\glslabel})%
}%
{% first letter uppercase
\glshyperlink[\Glsentrylong{\glslabel}\glsinsert]{\mainlabel}%
\space (\glsentryshort{\glslabel})%
}%
{% all caps
\glshyperlink[\MakeTextUppercase{%
\glsentrylong{\glslabel}\glsinsert}]{\mainlabel}%
\MakeTextUppercase{\space (\glsentryshort{\glslabel})}%
}%
}%
% add main entry to glossary
\glsadd{\mainlabel}%
}%
}%
}%
{% \glsdisp used
\glscustomtext
}%
}%
}
\SetCustomStyle
\newlinkedacr
{RangeExpansion}% main entry label
{RE}% acronym label
{RE}% abbreviation
{range expansion}% long form
{A range expansion etc}% description
\begin{document}
First use: \gls{RE}. Subsequent use: \gls{RE}.
\glsresetall
First use: \Gls{RE}. Subsequent use: \Gls{RE}.
\printglossaries
\end{document}
This produces:
where the first use long form hyperlinks to the entry in the main glossary, the subsequent use acronyms link to the entry in the list of acronyms, and the description in the list of acronyms links to the corresponding entry in the main glossary.
If you have entries in the main glossary that aren't link in this way to the list of acronyms, you may need to do \glsunsetall[main]
to counteract the effect of hyperfirst=false
option.
Is this a bug?
No, it's a documented feature. From Defining Glossary Entries:
Avoid using any of the \gls
-like or \glstext
-like commands within the
text
, first
, short
or long
keys (or their plural equivalent) or any
other key that you plan to access through those commands. (For
example, the symbol
key if you intend to use \glssymbol
.) Otherwise
you end up with nested links, which can cause complications and they
won’t work with the case-changing commands. You can use them within
the value of keys that won’t be accessed through those commands. For
example, the description
key if you don’t use \glsdesc
. Additionally,
they’ll confuse the entry formatting commands, such as \glslabel
.
From Acronyms and Other Abbreviations:
Recall from the warning in §4 Defining Glossary Entries that you
should avoid using the \gls
-like and \glstext
-like commands within the
value of keys like text
and first
due to complications arising from
nested links. The same applies to abbreviations defined using
\newacronym
.
For example, suppose you have defined:
\newacronym{ssi}{SSI}{server side includes}
\newacronym{html}{HTML}{hypertext markup language}
you may be tempted to do:
\newacronym{shtml}{S\gls{html}}{\gls{ssi} enabled \gls{html}}
Don’t! This will break the case-changing commands, such as \Gls
, it
will cause inconsistencies on first use, and, if hyperlinks are
enabled, will cause nested hyperlinks. It will also confuse the
commands used by the entry formatting (such as \glslabel
).
Instead, consider doing:
\newacronym
[description={\gls{ssi} enabled \gls{html}}]
{shtml}{SHTML}{SSI enabled HTML}
or
\newacronym
[description={\gls{ssi} enabled \gls{html}}]
{shtml}{SHTML}
{server side includes enabled hypertext markup language}
The reason why the problem isn't noticeable if you remove \setacronymstyle
is related to this bit:
Additionally, they’ll confuse the entry formatting commands, such as \glslabel
.
The newer method of using \setacronymstyle
uses the new style of entry formatting that relies on \glslabel
, which can't be scoped as the post-link hook needs to be able to both look forwards (for example, the discardperiod
attribute requires this) and effectively look backwards, to know the information about the entry that has just been referenced. You can explicitly add the scoping yourself. For example:
\newacronym{OBS}{OBS}{{\gls{glsOBS}}}
However, this essentially just papers over the most noticeable symptom, whilst ignoring all the other associated problems that are listed in Nested Links.
The best solution is:
\newacronym
[description={\gls{glsOBS}}]
{OBS}{OBS}{Organizational Breakdown Structure}
The next best solution is:
\newacronym
[description={\gls{glsOBS}}]
{OBS}{OBS}{\glsentrytext{glsOBS}}
but don't use \Gls{OBS}
with this method.
Alternatively, with glossaries-extra
:
\newacronym{OBS}{OBS}{\glsxtrtext{glsOBS}}
but, again, don't use \Gls{OBS}
.
Best Answer
The simplest method is to use the
glossaries-extra
extension package. If thenohyperfirst
attribute is set, this will switch off the hyperlink on first use. Thelong-postshort-user
abbreviation style can then be used with the short part put in a hyperlink (\glsxtruserparen
is only used on first use to put the short part in parentheses). Subsequent use behaves as normal.MWE:
(If you get an undefined abbreviation style or undefined control sequence error, then you need to update your version of
glossaries-extra
.)