9

I am trying to use the approach given in the solution here Glossary entry with extra parameter (which looks really neat) for an application where i am having more than one glossary; in the original i have only a symbolslist and abbreviations, but here's an mwe adapting the symbolslist to the main list provided in the solution of the link above

\documentclass{scrbook}
%
\usepackage[acronym,toc]{glossaries}
%this line is new
\newglossary[slg]{symbolslist}{syi}{syg}{List of Symbols}
\makeglossaries
\glsnoexpandfields

\newcommand*{\glsarg}{i}

\newglossaryentry{BetragVektor}{
     name=\ensuremath{|\overline{u_i}|},
     text=|\overline{u_{\glsarg}}|,
    description={ABC}}
\newglossaryentry{s:tP}{
    name=\ensuremath{T_p\mathcal M},
    text=T_\glsarg\mathcal M,
    description={},
    type=symbolslist %in own list
}
% modify the entry's format

\defglsentryfmt{%
  \let\orgglsarg\glsarg
  \ifdefempty\glsinsert
  {}%
  {%
    \let\glsarg\glsinsert
    \let\glsinsert\relax
  }%
  \glsgenentryfmt
  \let\glsarg\orgglsarg
}

\begin{document}

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}$

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}[2]$

$\gls{BetragVektor}[]$

$\gls{s:tP}[1]$

$\gls{s:tP}$

$\gls{s:tP}[1]$

$\gls{s:tP}[2]$

$\gls{s:tP}[]$

\printglossaries
\end{document}

As mentioned, the only thing new is that I introduce a second list. The solution still seems to work for the main list as the result shows.

symbols

So somehow the new argument gets added in the and and \glsarg stays the same. How can I solve this, such that my new glossary also can have optional parameters on their entries?

Ronny
  • 6,110

2 Answers2

6

Method 1: Specific Glossary

\defglsentryfmt has an optional argument that indicates which glossary this format should govern. If omitted, main is assumed, so you also need to do the same for the new glossary:

\defglsentryfmt[symbolslist]{%
  \let\orgglsarg\glsarg
  \ifdefempty\glsinsert
  {}%
  {%
    \let\glsarg\glsinsert
    \let\glsinsert\relax
  }%
  \glsgenentryfmt
  \let\glsarg\orgglsarg
}

Method 2: All Glossaries

Alternatively, you can just redefine \glsentryfmt to apply to all glossaries. (Individual glossaries may be overridden using \defglsentryfmt, which \newacronym does automatically.)

\documentclass{scrbook}
%
\usepackage[acronym,toc]{glossaries}
%this line is new
\newglossary[slg]{symbolslist}{syi}{syg}{List of Symbols}
\makeglossaries
\glsnoexpandfields

\newcommand*{\glsarg}{i}

\newglossaryentry{BetragVektor}{
     name=\ensuremath{|\overline{u_i}|},
     text=|\overline{u_{\glsarg}}|,
    description={ABC}}
\newglossaryentry{s:tP}{
    name=\ensuremath{T_p\mathcal M},
    text=T_\glsarg\mathcal M,
    description={},
    type=symbolslist %in own list
}
% modify the entry's format

\renewcommand*{\glsentryfmt}{%
  \let\orgglsarg\glsarg
  \ifdefempty\glsinsert
  {}%
  {%
    \let\glsarg\glsinsert
    \let\glsinsert\relax
  }%
  \glsgenentryfmt
  \let\glsarg\orgglsarg
}

\begin{document}

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}$

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}[2]$

$\gls{BetragVektor}[]$

$\gls{s:tP}[1]$

$\gls{s:tP}$

$\gls{s:tP}[1]$

$\gls{s:tP}[2]$

$\gls{s:tP}[]$

\printglossaries
\end{document}

This produces:

image of result

Method 3: Specific Category (glossaries-extra)

If you want to use the extension package glossaries-extra, this is a better method:

\documentclass{scrbook}
%
\usepackage[abbreviations]{glossaries-extra}

\newglossary[slg]{symbolslist}{syi}{syg}{List of Symbols}
\makeglossaries
\glsnoexpandfields

\newcommand*{\glsdefaultarg}{i}
\newcommand*{\glsarg}{\glsdefaultarg}

\newglossaryentry{BetragVektor}{
    category=arg,% requires an argument
     name=\ensuremath{|\overline{u_i}|},
     text=|\overline{u_{\glsarg}}|,
    description={ABC}}
\newglossaryentry{s:tP}{
    category=arg,% requires an argument
    name=\ensuremath{T_p\mathcal M},
    text=T_\glsarg\mathcal M,
    description={},
    type=symbolslist %in own list
}
% modify the entry's format

\preto\glsentryfmt{%
  \glsifcategory{\glslabel}{arg}% if category set to "arg"
  {%
    \ifdefempty\glsinsert
    {\let\glsarg\glsdefaultarg}%
    {%
      \let\glsarg\glsinsert
      \let\glsinsert\empty
    }%
  }%
  {}%
}

\begin{document}

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}$

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}[2]$

$\gls{BetragVektor}[]$

$\gls{s:tP}[1]$

$\gls{s:tP}$

$\gls{s:tP}[1]$

$\gls{s:tP}[2]$

$\gls{s:tP}[]$

\printglossaries
\end{document}

Now you just need to tag which entries require an argument by using category=arg in the entry definition. You can also store the default argument, if it should be different for each entry. For example:

\documentclass{scrbook}
%
\usepackage[abbreviations]{glossaries-extra}

\newglossary[slg]{symbolslist}{syi}{syg}{List of Symbols}
\makeglossaries
\glsnoexpandfields

\newcommand*{\glsarg}{}

\newglossaryentry{BetragVektor}{
    category=arg,% requires an argument
    user1={i},
     name=\ensuremath{|\overline{u_i}|},
     text=|\overline{u_{\glsarg}}|,
    description={ABC}}
\newglossaryentry{s:tP}{
    category=arg,% requires an argument
    user1={p},
    name=\ensuremath{T_p\mathcal M},
    text=T_\glsarg\mathcal M,
    description={},
    type=symbolslist %in own list
}
% modify the entry's format

\preto\glsentryfmt{%
  \glsifcategory{\glslabel}{arg}% if category set to "arg"
  {%
    \ifdefempty\glsinsert
    {\glsfieldfetch{\glslabel}{useri}{\glsarg}}%
    {%
      \let\glsarg\glsinsert
      \let\glsinsert\empty
    }%
  }%
  {}%
}

\begin{document}

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}$

$\gls{BetragVektor}[1]$

$\gls{BetragVektor}[2]$

$\gls{BetragVektor}[]$

$\gls{s:tP}[1]$

$\gls{s:tP}$

$\gls{s:tP}[1]$

$\gls{s:tP}[2]$

$\gls{s:tP}[]$

\printglossaries
\end{document}

Method 4: Specific Entry (glossaries-extra)

Here's another method: use \glsxtrfmt for the cases where a parameter is required. This deviates from the concept of an optional parameter, but it's worth considering as it doesn't alter the normal display format.

A designated field (by default user1, but may be changed by redefining \GlsXtrFmtField) stores the name (without the leading backslash) of a command that takes a single mandatory argument that's associated with the formatting of the given entry. Then \glsxtrfmt[options]{label}{parameter} applies that command to parameter (encapsulated by \glslink to index and, if enabled, hyperlink to the glossary).

For example, define:

\newcommand{\vectorlength}[1]{|\overline{u_{#1}}|}
\newcommand{\tP}[1]{T_#1\mathcal{M}}

Then the entries can be defined as:

\newglossaryentry{BetragVektor}{
 user1={vectorlength},
 name=\ensuremath{\vectorlength{i}},
 description={ABC}}

\newglossaryentry{s:tP}{
 user1={tP},
 name=\ensuremath{\tP{p}},
 description={},
 type=symbolslist
}

So now \gls{BetragVektor} uses the value of the first/text field (as normal, which here is obtained from the name field) but \glsxtrfmt{BetragVektor}{1} is essentially like \glslink{BetragVektor}{\vectorlength{1}}

Modified MWE:

\documentclass{scrbook}

\usepackage[automake]{glossaries-extra}

\newglossary[slg]{symbolslist}{syi}{syg}{List of Symbols}

\makeglossaries
\glsnoexpandfields

\newcommand{\BetragVektor}[1]{|\overline{u_{#1}}|}
\newcommand{\tP}[1]{T_#1\mathcal{M}}

\newglossaryentry{BetragVektor}{
 user1={BetragVektor},
 name=\ensuremath{\BetragVektor{i}},
 description={ABC}}

\newglossaryentry{s:tP}{
 user1={tP},
 name=\ensuremath{\tP{p}},
 description={},
 type=symbolslist %in own list
}

\begin{document}

$\glsxtrfmt{BetragVektor}{1}$

$\gls{BetragVektor}$

$\glsxtrfmt{BetragVektor}{1}$

$\glsxtrfmt{BetragVektor}{2}$

$\gls{BetragVektor}$

$\glsxtrfmt{s:tP}{1}$

$\gls{s:tP}$

$\glsxtrfmt{s:tP}{1}$

$\glsxtrfmt{s:tP}{2}$

$\gls{s:tP}$

\printglossaries

\end{document}

There are some more examples in Section 3.1 "Functions" of glossaries-extra and bib2gls: An Introductory Guide (that section is general to glossaries-extra regardless of whether or not you're using bib2gls).


¹ It's a little more complicated: \glsxtrfmt[options]{label}{text} effectively does \glslink[default options,options]{label}{\glsxtrfmtdisplay{csname}{text}{}} where csname is the control sequence name obtained from the designated field. (If the field is unset csname defaults to @firstofone.)

The starred version \glsxtrfmt*[options]{label}{text}[insert] is effectively \glslink[default options,options]{label}{\glsxtrfmtdisplay{csname}{text}{insert}}.

Nicola Talbot
  • 41,153
  • Oh, that was an easy fix - actually it's enough to have it for just my symbolslist, so having the one list entry fixed already solves the problem. Thanks for the fast (and so simple) answer :) – Ronny Jun 27 '16 at 10:09
  • 2
    @Ronny I added glossaries-extra alternative for completeness. – Nicola Talbot Jun 27 '16 at 10:17
  • Thanks, looks like a safer version, because only some (all of one category) are extended by an optional argument and not all symbols. – Ronny Jun 27 '16 at 13:46
0

I have chosen the third option as mentioned in Nicola's answer and it works like charm!

However there are a few remarks I would like to make regarding the syntax which weren't apparent to me and I had to experiment a little to make it work as expected. So:

  1. You can build other glossary entries on top of more primitive ones simply by calling \gls{<primitive entry name>} inside the respective field (see example; i guess that works for the whole glossaries package).
  2. You can pass the argument from the more complicated glossary entry to the more primitive one (category=arg has to be set in the complicated entry as well for you to be able to pass the argument).
    • the argument is passed implicitly (see example)
  3. And a few other things mentioned in the comments of the example

Example

\documentclass{article}

\usepackage[automake]{glossaries-extra}

\makeglossaries
\glsnoexpandfields

\newcommand*{\glsarg}{}

\newglossaryentry{simple}{
    category=arg,% requires an argument
    user1={a},% default argument for \glsarg
    name={\(A_{i}\)},
    text={A_{\glsarg}},
    description={simpler}}
\newglossaryentry{simple2}{
    category=arg,% requires an argument
    user1={b},
    name={\(B_{\glsarg}\)},% \glsarg has no effect here nor does user1=b, it has to be B_{b} to appear that way in the glossary, this will evaluate to just \(B\)
    text={B_{\glsarg}},% \glsarg works as usual here
    description={simpler}}
\newglossaryentry{complex}{
    category=arg,% required to require an argument
    name={\(C_{\gls{simple}[k]}\)},% will evaluate as \(C_{A_k}\) in the glossary
    text={C_{\gls{simple}}},% \glsarg will be passed to \gls{simple} without mentioning it here
    description={more complex. You can use \(\gls{simple2}\) here as well}}

\preto\glsentryfmt{%
    \glsifcategory{\glslabel}{arg}%
    {%
        \ifdefempty\glsinsert
        {\glsfieldfetch{\glslabel}{useri}{\glsarg}}%
        {%
            \let\glsarg\glsinsert
            \let\glsinsert\empty
        }%
    }%
    {}%
}

\begin{document}

\[\gls{simple}\]% shows as A_a
\[\gls{simple}[i]\]% shows as A_i
\[\gls{simple2}[j]\]% shows as B_j
\[\gls{complex}[k]\]% shows as C_{A_k}

    \printglossaries
\end{document}
VaNa
  • 337
  • 1
    Actually, you shouldn't nest \gls inside of descriptions of other entries. –  Nov 13 '17 at 15:17
  • 1
    As a supplement to @ChristianHupfer's comment, see the section Nested Links in the glossaries-extra documentation. – Nicola Talbot Nov 13 '17 at 17:37
  • @Nicola Talbot Oh, I have already rewritten my glossary and document to use the nesting :-D how bad can it get? So it only works because it takes \gls inside the definitions as \glstext[hyper=false,noindex]? – VaNa Nov 13 '17 at 18:19
  • 1
    @VaNa As long as you group it and have hyper=false (e.g. {\gls*{simple}[k]}) and don't use it for abbreviations (or something that has different first and text values) and you don't need the corresponding \glsentry... to be expandable (which it won't be anyway, since the values are in math-mode) and it doesn't interfere with the case-changing commands like \Gls (which aren't applicable in this case) then you should be okay. Suppressing the indexing isn't quite such a problem (unless you feel it inappropriate). The other issues are the primary concerns. – Nicola Talbot Nov 13 '17 at 18:51
  • 1
    It might be easier to have a wrapper command, for example \newcommand{\ngls}[2]{{\gls[hyper=false]{#1}[#2]}} and use that (e.g. name={\(C_{\ngls{simple}{k}}\)}, text={C_{\ngls{simple}{}}}). – Nicola Talbot Nov 13 '17 at 18:54
  • @Nicola Talbot Thank you very much, that is a good solution for me because I already have \let\g\gls there since I use \gls extensively. Just one more question. Can I somehow overcome an issue with \gls{simple}^a not having the upper index above the lower one but treating the A_a as a box becoming roughly A_a^{\: a}? – VaNa Nov 14 '17 at 19:29
  • @VaNa Use the optional argument \gls{simple}[^a] – Nicola Talbot Nov 14 '17 at 19:37
  • @NicolaTalbot You got me, that works but I have given this example to keep it simple however I actually need that for the complex case which does not work this way. I am sorry to bother you all the time btw :D – VaNa Nov 14 '17 at 23:06
  • 1
    @VaNa If you can create a MWE demonstrating it you can always post a question with a reference to this one. – Nicola Talbot Nov 15 '17 at 11:06
  • @NicolaTalbot Didn't know you weren't meant to nest. I've been nesting for ages. However, I don't use glossaries with hyperref, which probably helps. OP: \let\g\gls is horrible. You really ought never do this. That is, unless you first check that \g is not already defined. – cfr Dec 17 '17 at 05:16
  • @cfr Why is it so bad? Does something like \let\g\undefined in front of it help? – VaNa Dec 17 '17 at 21:07
  • 1
    Do you know if \g is already used? If not, you don't know what you're overwriting. \newcommand\g{}\let\g\gls is better as you'll get an error if it is already defined. But you are also making your code less readable in order to save typing 2 characters. \gls is hardly a macro with a long name. It would be better to set up a shortcut in your editor if you really want to save the typing. But at least set it so that either you check if it is defined or you use something which will do the check for you. – cfr Dec 17 '17 at 22:30
  • @cfr It's not just the problem with hyperlinks. It's documented in the glossaries manual (for example, in the 3rd red box near the start of 6. Links to Glossary Entries) and explained in more detail in the glossaries-extra manual. – Nicola Talbot Dec 18 '17 at 13:41
  • @NicolaTalbot I didn't realise that red box applied to using them inside entries since it only mentioned captions and titles etc. I realise 'moving argument' is more general, but I guess I'd have expected a specific note if it applied to use inside the fields of glossary entries, since cross-referencing other entries is a pretty common thing to do in the description of a term in a glossary, and this isn't a field affected by the warning on 126 either. Is there a good alternative? – cfr Dec 19 '17 at 00:09
  • 1
    @cfr It's not a problem in the description field (and is quite common, as you mention) as long as you don't use \glsdesc. The first red box relates to section headings. The 3rd red box is "Avoid nesting these commands. For example don’t do \glslink{⟨label⟩}{\gls {⟨label2⟩}} as this is likely to cause problems. By implication, this means that you should avoid using any of these commands within the text, first, short or long keys (or their plural equivalent) or any other key that you plan to access through these commands. (For example, the symbol key if you intend to use \glssymbol.) " – Nicola Talbot Dec 19 '17 at 00:35
  • @NicolaTalbot Oh, right. OK. I thought from the discussion that all nesting was to be avoided, where that includes any use in an entry at all. I don't remember whether I ever use them anywhere else, but it was description I had in mind. I don't use \glsdesc that I recall either. I just want cross-references in descriptions, really. – cfr Dec 19 '17 at 00:45
  • @NicolaTalbot So Christian's initial comment in this discussion is incorrect? There isn't a general problem with nesting them in descriptions of other entries? – cfr Dec 19 '17 at 00:47
  • 2
    @cfr Just to confirm: it's okay to have \gls in the description field if you don't use \glsdesc and if you don't try using \glsentrydesc in the final optional argument of arguments like \gls (or insert the description in any other way into text produced by commands like \gls, for example in \glsentryfmt). When I read Christian's initial comment, I interpreted "descriptions" as meaning field values in general (such as the text field, which will cause a problem) rather than specifically the value of the description field. My concern was focused on text={C_{\gls{simple}}}. – Nicola Talbot Dec 20 '17 at 11:09