2

I'm try to create a custom latex class based on scrbook. I make heavy use of glossaries for my math symbols, for which pdftool tips are created showing the description and units when a mouse pointer hoovers over.

Because I have an extensive list of glossary entries, not just symbols, but also acronyms and normal entry, I would like to store them in a csv file and load them with the datatool package.

The Atom editor (which I use) allows for the auto-completion of user defined glossaries with the package autocomplete-glossaries. But this requires the creation of the jobname.glsdef file. Hence the input{glossary.tex} at the beginning of the document environment.

It appears that I have trouble with the expansion of the \si command. Either it only reference the latest csv entry, in this case grams (bogus unit needed for illustration purposes). Which probably happens due to the \glssetnoexpandfield{unit} command. But if I set this to \glssetexpandfield{unit} siunitx starts to sputter with an "Undefined control sequence".

My guess is that I need to expand the \units command but not the actual \si command. But I can't seem to get it to work.

Any help is much appreciated.

\documentclass[twoside,open=any]{scrbook}
\usepackage[automake, docdef=true]{glossaries-extra}
\usepackage{datatool}
\usepackage{pdfcomment}
\usepackage{tabu}
\usepackage{xparse}
\usepackage[
 separate-uncertainty=true,
 per-mode = symbol-or-fraction,
 list-units = brackets,
 range-units = brackets,
 round-mode=places,
 round-precision=1,
 round-integer-to-decimal=true,
 multi-part-units=single]{siunitx}
\usepackage{filecontents}

% glossary.tex file
\begin{filecontents}{glossary.tex}
 \loadglssymbolcsv{symbols.csv}
\end{filecontents}

% Symbols.csv file
\begin{filecontents}{symbols.csv}
 key,symbol,units,description
 q,q,\si{\watt},heat flow
 q_e,q_e,\si{\watt},space heat gain
 q_x,q_x,\si{\watt},heat transfer rate
 varepsilon_c,\varepsilon_c,,heating efficiency of a Carnot cycle
 varepsilon_eff,\varepsilon_{eff},,effective cooling efficiency
 varepsilon_th,\varepsilon_{th},,theoretical heating efficiency
 varepsilon_w,\varepsilon_w,\si{gram},real heating efficiency
\end{filecontents}

% hooks for the preamble environment
\AtEndPreamble{
 \loadglsentries{glossary.tex} % Loads the glossary
 \makeglossaries % Makes the glossary
}

\glsdisablehyper % Disable hyperref, Needed to allow for pdf tooltip pop-up

% Add custom unit key
\glsaddkey{unit}{\glsentrytext{\glslabel}}{\glsentryunit}{\GLsentryunit}{\glsunit}{\Glsunit}{\GLSunit}
\newglossary[slg]{symbolslist}{sys}{syo}{Symbolslist}

% When a math symbol is called with \gls{sym-key}, the symbol is displayed in math mode and a pdf tooltip is generated, with a description and the units
\defglsentryfmt[symbolslist]{
 \pdftooltip{\ensuremath{\glsgenentryfmt}}{\glsentrydesc{\glslabel}, given in: \glsentryunit{\glslabel}}
}

% Handles the th csv file with the entries
\NewDocumentCommand{\loadglssymbolcsv}{ m }{
 \DTLifdbexists{symdata}{}{\DTLloaddb{symdata}{#1}}
 \glssetexpandfield{name}
 \glssetexpandfield{desc}
 \glssetexpandfield{first}
 \glssetexpandfield{firstplural}
 \glssetexpandfield{text}
 \glssetexpandfield{plural}
 \glssetexpandfield{descplural}
 \glssetnoexpandfield{unit} % Herein lies the complexity

 % Itterate through the columns and generate a newglossaryentry
 \DTLforeach*{symdata}%
 {%
  \key=key,%
  \symbol=symbol,%
  \units=units,%
  \description=description%
 }{%
  \newglossaryentry{sym-\key}{name={\symbol},description={\description},unit={\units},type=symbolslist}%
 }
}

%Custom symbolstyle
\newglossarystyle{symbolsliststyle}{
 \renewenvironment{theglossary}
 {
  \tabulinesep=3pt
  \noindent
  \begin{longtabu}{X[1,c,m] X[6,l,m] X[1.5,c,m] X[2,r,m]}
   }
   {
  \end{longtabu}
 }
 \renewcommand*{\glossaryheader}{
  \rowfont{\sffamily\bfseries}
  SYMBOL & DESCRIPTION & UNIT & PAGE \\\endhead
 }
 \renewcommand*{\glossentry}[2]{
  \color{black}\ensuremath{\glossentryname{##1}} & \glossentrydesc{##1} & \ensuremath{\si{\glsentryunit{##1}}} & ##2 \\
 }
 \renewcommand*{\glsgroupheading}[1]{}
 \renewcommand*{\glsgroupskip}{}
}

\begin{document}
\input{glossary.tex} % The glossaries needs to be loaded with in the document environment aas-wellbecause I need to glsdef file to be created for my auto-complete in Atom

% example equation
\begin{equation}
 \gls{sym-q_e} = \gls{sym-varepsilon_eff} \times \gls{sym-q_x} + 10.
\end{equation}

% Print the symbol list
\printglossary[type=symbolslist,style=symbolsliststyle]
\end{document}
  • 1
    I hadn't come across that atom autocomplete thing. I can't say I particularly like encouraging the use of document definitions, but at least in your case the entries are actually being defined in the preamble and the definitions in the .glsdefs file should be ignored. It won't work with \makenoidxglossaries or with \GlsXtrLoadResources, which don't allow document definitions. – Nicola Talbot Jun 2 '18 at 14:06
  • @NicolaTalbot first thank you for you quick and complete answer, I was unaware of the \expandonce and the end of line characters. Much appreciated. Atom can be a full-blown Latex editor with autocomplete (commands, bibtex, glosssary), spellcheck, chktex and beautify, when the following packages are installed: latex, atom-beautify, autocomplete-glossaries, autocomplete-latex-cite, autocomplete-latex-references, language-latex, latex-autocomplete, linter-chktex, linter-spell, linter-spell-latex, pdf-view – Jelle Spijker Jun 2 '18 at 14:16
1

This is a better method:

\NewDocumentCommand{\loadglssymbolcsv}{ m }{
 \DTLifdbexists{symdata}{}{\DTLloaddb{symdata}{#1}}%
 \glsnoexpandfields
 % Iterate through the columns and generate a newglossaryentry
 \DTLforeach*{symdata}%
 {%
  \key=key,%
  \symbol=symbol,%
  \units=units,%
  \description=description%
 }{%
  \edef\defnewentry{\noexpand\newglossaryentry{sym-\key}%
    {name={\expandonce\symbol},
     description={\expandonce\description},
     unit={\expandonce\units},type=symbolslist}}%
  \defnewentry
 }%
}

It ensures that the placeholder commands are only expanded once.

Some other minor corrections:

  • \makeglossaries should go before entry definitions.
  • Be careful of end of line characters. They can cause unwanted spaces. You need to comment them out.

Complete MWE:

\documentclass[twoside,open=any]{scrbook}
\usepackage{datatool}
\usepackage{pdfcomment}
\usepackage{tabu}
\usepackage{xparse}
\usepackage[
 separate-uncertainty=true,
 per-mode = symbol-or-fraction,
 list-units = brackets,
 range-units = brackets,
 round-mode=places,
 round-precision=1,
 round-integer-to-decimal=true,
 multi-part-units=single]{siunitx}

\usepackage[automake,
 docdef=atom % see below
]{glossaries-extra}

\usepackage{filecontents}

% glossary.tex file
\begin{filecontents}{glossary.tex}
 \loadglssymbolcsv{symbols.csv}
\end{filecontents}

% hooks for the preamble environment
\AtEndPreamble{
 \makeglossaries % Opens the glossary files
 \loadglsentries{glossary.tex} % Loads the glossary
}

% Symbols.csv file
\begin{filecontents}{symbols.csv}
 key,symbol,units,description
 q,q,\si{\watt},heat flow
 q_e,q_e,\si{\watt},space heat gain
 q_x,q_x,\si{\watt},heat transfer rate
 varepsilon_c,\varepsilon_c,,heating efficiency of a Carnot cycle
 varepsilon_eff,\varepsilon_{eff},,effective cooling efficiency
 varepsilon_th,\varepsilon_{th},,theoretical heating efficiency
 varepsilon_w,\varepsilon_w,\si{gram},real heating efficiency
\end{filecontents}

\glsdisablehyper % Disable hyperref, Needed to allow for pdf tooltip pop-up

% Add custom unit key
\glsaddkey{unit}{\glsentrytext{\glslabel}}{\glsentryunit}{\GLsentryunit}{\glsunit}{\Glsunit}{\GLSunit}
\newglossary[slg]{symbolslist}{sys}{syo}{Symbolslist}

% When a math symbol is called with \gls{sym-key}, the symbol is displayed in math mode and a pdf tooltip is generated, with a description and the units
\defglsentryfmt[symbolslist]{
 \pdftooltip{\ensuremath{\glsgenentryfmt}}{\glsentrydesc{\glslabel}, given in: \glsentryunit{\glslabel}}
}

% Handles the th csv file with the entries
\NewDocumentCommand{\loadglssymbolcsv}{ m }{
 \DTLifdbexists{symdata}{}{\DTLloaddb{symdata}{#1}}%
 \glsnoexpandfields
 % Iterate through the columns and generate a newglossaryentry
 \DTLforeach*{symdata}%
 {%
  \key=key,%
  \symbol=symbol,%
  \units=units,%
  \description=description%
 }{%
  \edef\defnewentry{\noexpand\newglossaryentry{sym-\key}%
    {name={\expandonce\symbol},
     description={\expandonce\description},
     unit={\expandonce\units},type=symbolslist}}%
  \defnewentry
 }%
}

%Custom symbolstyle
\newglossarystyle{symbolsliststyle}{%
 \renewenvironment{theglossary}
 {%
  \tabulinesep=3pt
  \noindent
  \begin{longtabu}{X[1,c,m] X[6,l,m] X[1.5,c,m] X[2,r,m]}
   }%
   {%
  \end{longtabu}%
 }%
 \renewcommand*{\glossaryheader}{%
  \rowfont{\sffamily\bfseries}
  SYMBOL & DESCRIPTION & UNIT & PAGE \\\endhead
 }%
 \renewcommand*{\glossentry}[2]{%
  \color{black}\ensuremath{\glossentryname{##1}} & \glossentrydesc{##1} & \ensuremath{\si{\glsentryunit{##1}}} & ##2 \\
 }%
 \renewcommand*{\glsgroupheading}[1]{}%
 \renewcommand*{\glsgroupskip}{}%
}

\begin{document}
%\input{glossary.tex} % The glossaries needs to be loaded with in the document environment aas-wellbecause I need to glsdef file to be created for my auto-complete in Atom

% example equation
\begin{equation}
 \gls{sym-q_e} = \gls{sym-varepsilon_eff} \times \gls{sym-q_x} + 10.
\end{equation}

% Print the symbol list
\printglossary[type=symbolslist,style=symbolsliststyle]
\end{document}

image of symbol list

Regarding the need to create the .glsdefs file for use with atom's autocomplete, you can now (as from glossaries-extra version 1.34, 2018-07-29) use the package option docdef=atom, which behaves like docdef=restricted but will also create the .glsdefs file without reading it. This will allow for preamble definitions without needing to reload glossaries.tex in the document.

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.