# Can glossaries provide warnings when a glossary entry is used but not included in the glossary?

glossaries supports cross-referenced entries. In particular, if I use one glossary entry in another and only include the second explicitly in my document, glossaries can still figure out that it should include the first entry in the glossary.

However, this requires 2 runs of makeglossaries:

• compile -> makeglossaries -> compile -> makeglossaries -> compile

or else the first entry will be missing from the list.

So far, this is not especially problematic: just remember to run makeglossaries twice, recompiling in between.

Things get complicated, however, if the first, cross-referenced entry itself cross-references a third entry. Now the third entry should be included, but an additional run of makeglossaries is required. Moreover, should the third entry cross-reference a fourth, yet another run is needed. And so on for any fifth, sixth... entries.

For example:

\begin{filecontents}{mygloss.tex}
\newglossaryentry{animal}{%
name                        =   animal,
description     =   {A living organism. Cf.~\gls{plant}}}
\newglossaryentry{apple}{%
name                        =   apple,
description     =   {A type of \gls{fruit}}}
\newglossaryentry{fruit}{%
name                        =   fruit,
description     =   {A method of seed-dispersal favoured by some \glspl{plant}}}
\newglossaryentry{plant}{%
name                        =   plant,
description     =   {A living organism. Cf.~\gls{animal}}}
\end{filecontents}

\documentclass{article}
\usepackage{glossaries}
\makeglossaries
\begin{document}
An \gls{apple} a day keeps the doctor away.
\printglossaries
\end{document}


Unfortunately, glossaries does not provide any warning when an entry is used by not included in the glossary. It does not tell me, for example, that the reference to fruit is undefined after the first compilation cycle. It just silently includes fruit in the definition of apple without including the definition of fruit in the glossary.

Keeping track of this for complex documents which use complex databases of entries becomes rather problematic.

How can I most easily and reliably determine when an additional compilation cycle is required?

One possibility I'm wondering about is to create a shell script which compares the result of the following commands:

grep glossentry <filename>.glo | wc -l
grep glossentry <filename>.gls | wc -l


and conclude that no further runs are required if, and only if, the results of the two greps are equal.

However, I am not certain if this is generally reliable, especially when multiple .glo and .gls files are involved. Nor am I clear whether there is no more readily-available method for determining that another run is needed.

• \glsaddallunused is no option? This reduces the number of pdflatex | makeglossaries cycles to 2 runs, in my point of view – user31729 Oct 3 '15 at 14:03
• @ChristianHupfer No. I don't want to add all entries in the glossaries databases but only those which are actually used somewhere. I'm prepared to deal with the additional runs, although it would be nice if that weren't required, but I lose track of when these are needed and end up not realising I've produced an incomplete glossary. (I've been wondering if Biblatex/Biber might work better but that's another matter and would require a lot of time. And it would probably be impossible to distinguish citations from glossary term....) – cfr Oct 3 '15 at 21:25

This is not really an answer, but it does not really belong as part of the question and is rather too long for a comment.

I've written a shell script which attempts to generate a glossary even when there are multiply nested cross-references within the entries. This is highly experimental. It has only been tested on a minimal example. It WILL break. Please leave a comment if you can suggest ways to improve this which do not amount to rewriting the script in another language.

# Caveat emptor...

As currently written, the script makes the following assumptions:

• TeX Live binaries are available in /usr/local/texlive/bin/. This is unlikely to be true on systems other than mine.

• sed, grep, uniq, sort, wc, printf, echo, getopt, find, xargs etc. are available. Should be true on all reasonably sane Unix-like systems.

• bash is available as /bin/bash. Should be true on all reasonably sane Unix-like systems.

• Filenames are sane and do not contain any strange, weird or problematic characters. Should be true on all systems with reasonably sane users.

To use the script, if you really wish to, you need to save it as a file, <super-makeglossaries>, say and then make it executable:

chmod +x super-makeglossaries


Either save the script in ~/bin/ or provide the full path to the script when using it.

The syntax is pretty minimal. There are only 2 options:

• -h or --help for the minimal help;

• -o or --options if you want to pass options to pdflatex. Normally, you would wish to quote these.

For example:

super-makeglossaries -o "--synctex=1" <filename>


should, theoretically run pdflatex --synctex=1 and makeglossaries on <filename> or <filename>.tex as necessary until all glossary entries are stabilised. 'Theoretically' means 'according to my current hope' and not 'according to this theory I have worked out'.

Don't use the version I posted earlier. It didn't work even for me. It stands an icicle in the Sahara's chance of working for anybody else. Here's the current code which may, possibly, work for me, at least:

#!/bin/bash -
#set -x
PATH=/usr/local/texlive/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin
export PATH

allan=0
options=""
pdflatex=/usr/local/texlive/bin/pdflatex
makeglossaries=/usr/local/texlive/bin/makeglossaries

usage="Usage: $0 [OPTION] FILE makeglossaries wrapper which will run pdflatex and makeglossaries until cross-referenced entries are stable. Options: -h --help print this message and exit -o --options options to be passed to pdflatex FILE should be a TeX file, specified with or without the .tex extension." error () { echo "$@" 1>&2
((allan++))
usage_and_exit $allan } usage () { printf %b "$usage\n"
}
usage_and_exit () {
usage
exit $1 } tex_error () { echo "$@" 1>&2
((allan++))
exit $allan } find_gen () { find$(dirname "$1") -maxdepth 1 -type f -readable -name "$(basename $1).*.$2"
find  $(dirname "$1") -maxdepth 1 -type f -readable -name "$(basename$1).$2" } gen_exists () { n=1 k=$(find_gen "$1" "$2" | wc -l)
[[ $k -ne 0 ]] && n=0 return$n
}

[[ -x $pdflatex ]] || error Ni allaf ffeindio "$pdflatex".
[[ -x $makeglossaries ]] || error Ni allaf ffeindio "$makeglossaries".

tempargs=$(getopt -o ho: --long help,options: -- "$@")
if [ $? != 0 ]; then usage_and_exit fi eval set -- "$tempargs"

while true
do
case "$1" in -h | --help) usage; exit$allan;;
-o | --opt | --opti | --optn | --option | --options)
options="$2" shift; shift;; --) shift; break;; *) error Unrecognised option "$1".
esac
done

args="$@" [[ "$#" != 1 ]] && error Mae angen o leiaf un enw ffeil ac nid mwy nag un!
enw=${1%.tex} gen_exists "$enw" glo
if [ $? != 0 ] then printf %b "Running pdfLaTeX,$makeglossaries and pdfLaTeX to create glossary.\n"
$pdflatex$options $enw || tex_error pdfLaTeX exited with errors.$makeglossaries $enw || tex_error$makeglossaries exited with errors.
$pdflatex$options $enw || tex_error pdfLaTeX exited with errors. else gen_exists "$enw" gls
if [ $? != 0 ] then printf %b "Running$makeglossaries and pdfLaTeX to create glossary.\n"
$makeglossaries$enw || tex_error $makeglossaries exited with errors.$pdflatex $options$enw || tex_error pdfLaTeX exited with errors.
fi
fi
$(gen_exists "$enw" glo) || error Ni allaf ffeindio .glo!
$(gen_exists "$enw" gls) || error Ni allaf ffeindio .gls!
gloentries=$(find_gen "$enw" glo | xargs grep glossentry | sed 's/|setentrycounter.*$//' | sort | uniq | wc -l) glsentries=$(find_gen "$enw" gls | xargs grep glossentry | wc -l) while [ ! "$gloentries" == "$glsentries" ] do printf %b "Rerunning$makeglossaries and pdfLaTeX to resolve cross-references.\n"
$makeglossaries$enw || tex_error $makeglossaries exited with errors.$pdflatex $options$enw || tex_error pdfLaTeX exited with errors.
gloentries=$(find_gen "$enw" glo | xargs grep glossentry | sed 's/|setentrycounter.*$//' | sort | uniq | wc -l) glsentries=$(find_gen "$enw" gls | xargs grep glossentry | wc -l) done exit$allan
# vim: set nospell:


It's not really possible for glossaries to provide a warning for all those nested levels of dependency, but adding hyperref does give a warning if an entry has been used but doesn't appear in the glossary.

Example:

\documentclass{article}

\usepackage{glossaries}

\makeglossaries

\newglossaryentry{animal}{%
name                        =   animal,
description     =   {A living organism. Cf.~\gls{plant}}}
\newglossaryentry{apple}{%
name                        =   apple,
description     =   {A type of \gls{fruit}}}
\newglossaryentry{fruit}{%
name                        =   fruit,
description     =   {A method of seed-dispersal favoured by some
\glspl{plant}}}
\newglossaryentry{plant}{%
name                        =   plant,
description     =   {A living organism. Cf.~\gls{animal}}}

\begin{document}
An \gls{apple} a day keeps the doctor away.
\printglossaries
\end{document}


With the first pdflatex run, pdfTeX produces the following warning:

pdfTeX warning (dest): name{glo:apple} has been referenced but does not exist,
replaced by a fixed one


This is because hyperref has inserted an internal hyperlink but the target doesn't exist. At this point, only apple has been used. The other entries, including fruit, haven't been used. The fruit entry doesn't get used until the glossary has been created. Then pdfTeX warns

pdfTeX warning (dest): name{glo:fruit} has been referenced but does
not exist, replaced by a fixed one


This doesn't help with the nested dependencies. The problem here is that glossaries doesn't know that the apple entry requires the fruit entry until it processes the apple entry description, which it doesn't do until the apple entry is in the glossary.

The glossaries-extra package, which extends the glossaries package, provides a solution to this type of problem, but only when the dependency is indicated by the see key. For example:

% arara: pdflatex
% arara: makeglossaries
% arara: pdflatex
\documentclass{article}

\usepackage{glossaries-extra}

\makeglossaries

\newglossaryentry{animal}{%
name                        =   animal,
description     =   {A living organism},
see=[cf.]{plant}}
\newglossaryentry{apple}{%
name                        =   apple,
description     =   {A type of \gls{fruit}},
see={fruit}}
\newglossaryentry{fruit}{%
name                        =   fruit,
description     =   {A method of seed-dispersal favoured by some
\glspl{plant}},
see={plant}}
\newglossaryentry{plant}{%
name                        =   plant,
description     =   {A living organism},
see=[cf.]{animal}}

\begin{document}
An \gls{apple} a day keeps the doctor away.
\printglossaries
\end{document}


This just requires pdflatex, makeglossaries and pdflatex to produce:

This puts the cross-reference in the location list, which may not be what you want, but it does make the .gls file easier to post-process with a script if required. The .gls file for this example contains:

\glossarysection[\glossarytoctitle]{\glossarytitle}\glossarypreamble
\glossentry{animal}{\glossaryentrynumbers{\relax
\setentrycounter[]{page}\glsxtrunusedformat{1}\delimN
\glsseeformat[cf.]{plant}{Z}}}%
\glossentry{apple}{\glossaryentrynumbers{\relax
\setentrycounter[]{page}\glsnumberformat{1}\delimN
\glsseeformat[\seename ]{fruit}{Z}}}\glsgroupskip

So each cross-reference in the location list is in the form \\delimN\\s*\\n\\s+\\glsseeformat$.+?$\{.+?\}{Z}