9

Here, siunitx abbreviations throw an error if used inside a glossary entry key, however, if the unit is given without abbreviations, no error shows up.

\documentclass{article}

\usepackage{lipsum}
\usepackage{booktabs}
\usepackage{calc,siunitx}
\sisetup{load-configurations = abbreviations}
\usepackage{glossaries}

\makenoidxglossaries

\newlength\glsnamewidth
\newlength\glsunitwidth

\settowidth{\glsnamewidth}{\textbf{sign}}
\settowidth{\glsunitwidth}{\textbf{unit}}

\newglossarystyle{namedescunit}{%
  \setlength{\glsdescwidth}{\linewidth-\glsnamewidth-\glsunitwidth-6\tabcolsep}%
  \renewenvironment{theglossary}%
    {\begin{supertabular}{p{\glsnamewidth}p{\glsunitwidth}p{\glsdescwidth}}}%
    {\end{supertabular}}%
 \renewcommand*{\glossaryheader}{}%
  \renewcommand*{\glsgroupheading}[1]{}%
  \renewcommand{\glossentry}[2]{%
    \raggedright\glstarget{##1}{\glossentryname{##1}} & 
    \centering\glossentrysymbol{##1} &
    \glossentrydesc{##1}\tabularnewline
  }%
  \renewcommand{\subglossentry}[3]{\glossentry{##2}{##3}}%
  \renewcommand*{\glsgroupskip}{}%
}

\setglossarystyle{namedescunit}

%%%%%%%%% this code block causes the crash %%%%%%%%%%%
    \makeatletter
    \appto\@newglossaryentryposthook{%
        \settowidth{\dimen@}{\glsentryname{\@glo@label}}%
        \ifdim\dimen@>\glsnamewidth
        \setlength{\glsnamewidth}{\dimen@}%
        \fi
        \settowidth{\dimen@}{\glsentrysymbol{\@glo@label}}%
        \ifdim\dimen@>\glsunitwidth
        \setlength{\glsunitwidth}{\dimen@}%
        \fi
    }%
    \makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\glssetnoexpandfield{symbol}
\newglossaryentry{L}{name={L},description={Buchstabe},symbol={---}}
\newglossaryentry{P}{name={Cp},description={specific heat},symbol={[\si{\J\per\kg\per\K}]}}

\begin{document}

\lipsum[1]
\glsaddall

\printnoidxglossaries

\end{document}
  • 1
    Right, that does throw an Undefined control sequence on the abbreviated units. (By the way, \sisetup{load-configurations = abbreviations} is actually deprecated syntax, the correct in versions 2.3 and above of siunitx would be \sisetup{abbreviations=true}, which is also the default behaviour. See manual sections 8.3 and 5.11.) – Torbjørn T. Sep 6 '17 at 0:19
  • 1
    Maybe add \glsnoexpandfields to the preamble, as discussed in this question: tex.stackexchange.com/questions/390273/… – Steven B. Segletes Sep 8 '17 at 15:34
  • @StevenB.Segletes I already have \glssetnoexpandfield{symbol} in the preamble before the new glossary entries. – Diaa Sep 8 '17 at 15:36
  • 3
    The problem can be reduced to \documentclass{article} \usepackage{etoolbox,siunitx} \newcommand{\tmp}{} \appto\tmp{\settowidth{\dimen0}{[\si{\J\per\kg\per\K}]}} \tmp \begin{document} \end{document}. (This is essentially what the glossaries code is trying to do.) If the \tmp block is moved to the document environment the error goes away. – Nicola Talbot Sep 8 '17 at 16:36
  • 1
    Nicola's comment seems to be the proper way to proceed. Perhaps ask her to provide the answer. – Steven B. Segletes Sep 8 '17 at 16:46
7

It seems that \si the \si abbreviation commands like \J (see Ulrike's answer) can't be processed in the preamble. This can be demonstrated with:

\documentclass{article}

\usepackage{siunitx}

\settowidth{\dimen0}{[\si{\J\per\kg\per\K}]}

\begin{document}
\end{document}

This causes the error:

! Undefined control sequence.
<argument> \J 
              \per \kg \per \K 

Moving \settowidth to the document environment gets rid of the error.

This means that the unit width can't be calculated in the preamble for your MWE, but \makenoidxglossaries won't permit \newglossaryentry in the document environment (and it's not recommended with \makeglossaries). Instead you can make use of the \glsFindWidestUsedAnyNameSymbol command provided with glossaries-extra-stylemods:

\documentclass{article}

\usepackage{lipsum}
\usepackage{booktabs}
\usepackage{calc,siunitx}
\sisetup{load-configurations = abbreviations}
\usepackage[stylemods]{glossaries-extra}

\makenoidxglossaries

\newlength\glsnamewidth
\newlength\glsunitwidth

\settowidth{\glsnamewidth}{\textbf{sign}}
\settowidth{\glsunitwidth}{\textbf{unit}}

\newglossarystyle{namedescunit}{%
  \setlength{\glsdescwidth}{\linewidth-\glsnamewidth-\glsunitwidth-6\tabcolsep}%
  \renewenvironment{theglossary}%
    {\begin{supertabular}{p{\glsnamewidth}p{\glsunitwidth}p{\glsdescwidth}}}%
    {\end{supertabular}}%
 \renewcommand*{\glossaryheader}{}%
  \renewcommand*{\glsgroupheading}[1]{}%
  \renewcommand{\glossentry}[2]{%
    \raggedright\glstarget{##1}{\glossentryname{##1}} & 
    \centering\glossentrysymbol{##1} &
    \glossentrydesc{##1}\tabularnewline
  }%
  \renewcommand{\subglossentry}[3]{\glossentry{##2}{##3}}%
  \renewcommand*{\glsgroupskip}{}%
}

\setglossarystyle{namedescunit}

\newglossaryentry{L}{name={L},description={Buchstabe},symbol={---}}
\newglossaryentry{P}{name={Cp},description={specific heat},symbol={[\si{\J\per\kg\per\K}]}}

\begin{document}
\lipsum[1]
\gls{L}, \gls{P}.


\glsFindWidestUsedAnyNameSymbol{\glsunitwidth}
\settowidth{\dimen0}{\glsgetwidestname}
\ifdim\dimen0>\glsnamewidth
 \glsnamewidth=\dimen0
\fi

\printnoidxglossaries

\end{document}

\glsFindWidestUsedAnyNameSymbol only checks entries that have been marked as used (through commands like \gls) so needs to be used just before the glossary (provided it's at the end of the document). If you use \glsaddall instead, use \glsFindWidestAnyNameSymbol which can be placed at the start of the document:

\begin{document}
\glsFindWidestAnyNameSymbol{\glsunitwidth}
\settowidth{\dimen0}{\glsgetwidestname}
\ifdim\dimen0>\glsnamewidth
 \glsnamewidth=\dimen0
\fi

\lipsum[1]
\glsaddall

\printnoidxglossaries

\end{document}
6
+50

The definitions for the abbreviations are loaded only at begin document. So you should either move your glossary definition behind \begin{document}, not use abbreviations in the glossary definitions or load the abbreviations earlier:

\documentclass{article}

\usepackage{lipsum}
\usepackage{booktabs}
\usepackage{calc,siunitx}

%load abbreviations:
\ExplSyntaxOn
\__siunitx_load_abbreviations:
\ExplSyntaxOff

\usepackage{glossaries}

\makenoidxglossaries

\newlength\glsnamewidth
\newlength\glsunitwidth

\settowidth{\glsnamewidth}{\textbf{sign}}
\settowidth{\glsunitwidth}{\textbf{unit}}

\newglossarystyle{namedescunit}{%
  \setlength{\glsdescwidth}{\linewidth-\glsnamewidth-\glsunitwidth-6\tabcolsep}%
  \renewenvironment{theglossary}%
    {\begin{supertabular}{p{\glsnamewidth}p{\glsunitwidth}p{\glsdescwidth}}}%
    {\end{supertabular}}%
 \renewcommand*{\glossaryheader}{}%
  \renewcommand*{\glsgroupheading}[1]{}%
  \renewcommand{\glossentry}[2]{%
    \raggedright\glstarget{##1}{\glossentryname{##1}} &
    \centering\glossentrysymbol{##1} &
    \glossentrydesc{##1}\tabularnewline
  }%
  \renewcommand{\subglossentry}[3]{\glossentry{##2}{##3}}%
  \renewcommand*{\glsgroupskip}{}%
}

\setglossarystyle{namedescunit}

%%%%%%%%% this code block causes the crash %%%%%%%%%%%
    \makeatletter
    \appto\@newglossaryentryposthook{%
        \settowidth{\dimen@}{\glsentryname{\@glo@label}}%
        \ifdim\dimen@>\glsnamewidth
        \setlength{\glsnamewidth}{\dimen@}%
        \fi
        \settowidth{\dimen@}{\glsentrysymbol{\@glo@label}}%
        \ifdim\dimen@>\glsunitwidth
        \setlength{\glsunitwidth}{\dimen@}%
        \fi
    }%
    \makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\glssetnoexpandfield{symbol}
\newglossaryentry{L}{name={L},description={Buchstabe},symbol={---}}
\newglossaryentry{P}{name={Cp},description={specific heat},symbol={[\si{\J\per\kg\per\K}]}}

\begin{document}

\lipsum[1]
\glsaddall

\printnoidxglossaries

\end{document}

You could make a feature request for siunitx that it adds a option to load them directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.