1

I have glossary entries fields (as name, text, symbol fields) define by another glossary entry like below (the compressor_motor entry is define with the compressor entry):

\newglossaryentry{compressor_motor}
{
    name={\glsname{compressor} Motor},
    sort={compressor motor},
    text={\gls{compressor} motor},
    description={Motor of the \glsname{compressor}},
    symbol={\glssymbol{compressor}m},
    parent=compressor
}

I would be glad to have (letter to Santa Claus ;):

  • The \Gls, \GLS, \Glssymbol and \GLSsymbol commands work with the compressor_motor entry (for the moment is not working, see MWE below);
  • The \Gls command able to capitalize the first letter of EACH word, not just the first word (same behaviour as proposed by karlkoeller answer with the possibility of putting a '~' character before each word - to prevent the 'lettered' word from being capitalized - as pointed out by Nicholas Hamilton in comment to the karlkoeller answer);
  • Compatibility with Beamer AND article document class;

Here a MWE:

\documentclass{article}
\usepackage[style=tree]{glossaries-extra}

\usepackage{verbatim}

\makenoidxglossaries

\newglossaryentry{subsytem}{name={Subssytems},description={\glspar},sort={1}}   
\newglossaryentry{compressor}
{
    name={Compressor},
    text={compressor},
    sort={compressor},
    description={Air Compressor},
    symbol={cp},
    parent=subsytem
}
\newglossaryentry{ejector}
{
    name={Ejector},
    text={ejector},
    sort={Ejector},
    description={Air Ejector},
    symbol={ej},
    parent=subsytem
}

\newglossaryentry{compressor_motor}
{
    name={\glsname{compressor} Motor},
    sort={compressor motor},
    text={\gls{compressor} motor},
    description={Motor of the \glsname{compressor}},
    symbol={\glssymbol{compressor}m},
    parent=compressor
}

\newglossaryentry{compressor_ejector}
{
    name={\glsname{compressor}~and \glsname{ejector}},
    sort={compressor and ejector},
    text={\gls{compressor}~and \gls{ejector}},
    description={Air \glsname{compressor} and \glsname{ejector}},
    symbol={\glssymbol{compressor}\glssymbol{ejector}},
    parent=subsytem
}


\begin{document}

    \gls{compressor};
    \gls{compressor_motor};
    \gls{compressor_ejector};
    
    \bigskip
    
    % This is not working: 
    %\verb!\Gls{compressor_motor}: !\Gls{compressor_motor};
    
    %\verb!\GLS{compressor_motor}: !\GLS{compressor_motor};
    
    %\verb!\Gls{compressor_ejector}: !\Gls{compressor_ejector};
    
    %\verb!\GLS{compressor_ejector}: !\GLS{compressor_ejector};
    
    %\verb!\Glssymbol{compressor_motor}: !\Glssymbol{compressor_motor};
    
    %\verb!\GLSsymbol{compressor_motor}: !\GLSsymbol{compressor_motor};


    \printnoidxglossary
\end{document}

So, I would like this kind of results:

enter image description here


Why I define gls entries with another gls entries?

Because I have a lot of entries (tens) depending to another entries and I don't want to change a lot of things if I just decide to change the word compressor by compresseur (in french for exemple). So, I had the idea to define all the entries using the word compressor by using the \gls{compressor} command...

1 Answer 1

1

This answer is here in order to not let this question without an almost "working" answer, if someone (by the greatest of chance) comes across this solution and wishes (strangely) to use it.
So, if someone comes with a more "LaTeX based" and robust solution (without using external tools) it would be great!

Two "bypass-solutions".

With both methods, the idea is the same: create a new glossary_entriesPostTreated.txt file used to define glossary entries but with all \gls like commands already "expanded".

This new file can be used instead of the original one (glossary_entries.tex) and the entries will capitalized without problem.

  • The first method needs make4ht and a tool for html to text conversion (as html2text).
  • The second method write directly to a text file (without an external tool) but use "low level" macros for writing the "output" of some \gls like commands to the file (thanks to Marijn's answer).

Prerequisite:

  • All glossary entries definitions must be stored into a text file (.tex, .bib, etc.).
    • A newline MUST be present after each \newglossaryentry with no comments "%". So this is Ok:
\newglossaryentry{subsystem}
{% A new line is needed after each \newglossaryentry key !!!
name={Subssytems},description={},sort={1}}

But NOT this (a character is inserted just after {subsystem} and just before the first {):

\newglossaryentry{subsystem}% A comment here
{% A new line is needed after each \newglossaryentry key !!!
name={Subssytems},description={},sort={1}}

or also NOT this (no newline inserted just after {subsystem} and just before the first {):

\newglossaryentry{subsystem}{% No newline here just after {subsystem}
{%
name={Subssytems},description={},sort={1}}
  • Needs 3 packages: listofitems (to extract the entry fields, thanks to Steven B. Segletes answer), tikz (to have a nice for loop), catchfile (to extract the content of the text file containing the entries definitions, thanks to egreg answer).

  • The first method needs make4ht and a tool for html to text conversion (as html2text).

1. First Method (with make4ht and html2text)

MWE.tex (see explanations below):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{listofitems}
\usepackage{tikz}% To make a nice for loop
\usepackage{catchfile}% To read the glossary entries file
\usepackage[style=tree]{glossaries-extra}
\input{glossary_entries.tex}

% For a good print of underscore
\catcode`_=12

\begin{document}
\IfFileExists{glossary_entries.tex}% 
{\CatchFileEdef{\glsEntriesListString}{glossary_entries.tex}{\endlinechar=13}}%
\glsEntriesListString % This call is needed to a good behaviour of \readlist
\noindent
\ignoreemptyitems % Ingnore empty items from le list
\setsepchar{\newglossaryentry|| /,}% Define separator for nested list with e.g. first list separator "\newglossaryentry" or " " (space) and second list separator "," (comma)
\readlist\myglsentrylist{\glsEntriesListString}% Extract the list from glossary entriesc
\setsepchar{,}% Define separator for the list inside a glossary entry (in order to extract fields)
\foreach \i in {1,2,...,\myglsentrylistlen}{%Loop under the glossary entry list
  \ifodd\i% If odd, print the list element
    \itemtomacro\myglsentrylist[\i]\myglsentrylisttowrite   
    \textbackslash{}newglossaryentry\{\myglsentrylisttowrite\}\{\%\newline
  \else % If even, make another list with the fields after removing curly braces "{}" surronding the fields
    \itemtomacro\myglsentrylist[\i]\myfieldslisttemp    \expandafter\def\expandafter\myfieldslisttemp\myfieldslisttemp % Removing curly braces "{}"
    \setsepchar{,}% Define separator for the list inside a glossary entry (in order to extract fields)
    \readlist*\myfieldslist{\myfieldslisttemp}% Ignore extreme spaces
    \foreach \j in {1,2,...,\myfieldslistlen}{%Loop under the glossary entry list
    \itemtomacro\myfieldslist[\j]\myfieldskeylisttemp
    \setsepchar{=}% Define separator for the list inside a glossary entry (in order to extract fields)
    \readlist\myfieldskeylist{\myfieldskeylisttemp}%
    \itemtomacro\myfieldskeylist[1]\myfieldskeylistONEtowrite
    \indent\myfieldskeylist[1]=\{%First item = field key name     
    \itemtomacro\myfieldskeylist[2]\myfieldskeylistTWOtowrite   
    \ifnum \j=\myfieldslistlen % Last field with NO comma at the end
        \myfieldskeylist[2]\}\newline\}\%\newline
    \else
        \myfieldskeylist[2]\},\newline
    \fi
    }%
  \fi
}%
\end{document}

Contents of glossary_entries.tex file:

\newglossaryentry{subsystem}
{% A new line is needed after each \newglossaryentry key !!!
name={Subssytems},description={},sort={1}}
\newglossaryentry{compressor}
{% A new line is needed after each \newglossaryentry key !!!
    name={Compressor},
    sort={compressor},
    text={compressor},
    description={Compressor},
    symbol={Cp},
    parent={subsystem}
}
\newglossaryentry{compressor_motor}
{% A new line is needed after each \newglossaryentry key !!!
    name={\glsname{compressor} Motor},
    text={\gls{compressor} motor},
    description={Motor of the \gls{compressor}},
    symbol={\glssymbol{compressor}m},
    parent={compressor}
}
\newglossaryentry{ejector}
{% A new line is needed after each \newglossaryentry key !!!
    name={Ejector},
    text={Ejector},
    description={Air Ejector},
    symbol={ej},
    parent={subsystem}
}

Build with:

$ make4ht -l MWE.tex
$ html2text -style pretty MWE.html > glossary_entries_PostTreated.txt

Explanations:

  • The goal of the code is to print all the fields of all glossary entries using a similar method as the one used in this answer, called hereafter as the "\printallglossaryfields answer".

  • Basically the code split the glossary entries fields with the \readlist command of the listofitems by considering them as a comma separated list (see \printallglossaryfields answer for more details).

  • In order to print the curly braces around the fields (after the = symbol), the \readlist command is used to split the field key name (e.g. sort) from the field label (e.g. compressor) using = symbol as list separator (this feature was not present in the orignal code in the \printallglossaryfields answer).

  • Underscore is defined with \catcode'_=12 in order to be printed easily (need LuaLaTeX compilation with make4ht, see michal.h21 answer).

Limitations and possible improvements (same as the \printallglossaryfields answer):

  • Not robust with the need of newline after each \newglossaryentry with no comments "%" (because the code detects the space after each key in order to separate the key from the fields listed after the key).
  • The use of packages tikz and catchfile could probably be avoided.
  • Need an external tool for html to text conversion (e.g. html2text)

Bonus :

2. Second Method (with only LaTeX)

MWE (see explanations below):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{listofitems}
\usepackage{tikz}% To make a nice for loop
\usepackage{catchfile}% To read the glossary entries file
\usepackage[style=tree]{glossaries-extra}
\newcommand{\entriesfilename}{glossary_entries}
\input{\entriesfilename.tex}

% For a good print of curly braces, percent and underscore
% Curly braces
\begingroup
\catcode`<=1 \catcode`>=2
\catcode`{=12 \catcode`}=12
\gdef\wbgroup<{>
\gdef\wegroup<}>
\endgroup    
% Percent
\def\percentchar#1{}
\edef\percentchar{\expandafter\percentchar\string\%}
% Underscore
\catcode`_=12

% Redefinition of some \gls like commands by their respective "low level" macro in order to use them with \write command
\makeatletter
\renewcommand{\gls}[1]{\csname glo@#1@text\endcsname}
\renewcommand{\glsname}[1]{\csname glo@#1@name\endcsname}
\renewcommand{\glsdesc}[1]{\csname glo@#1@desc\endcsname}
\renewcommand{\glstext}[1]{\csname glo@#1@text\endcsname}
\renewcommand{\glssymbol}[1]{\csname glo@#1@symbol\endcsname}
\makeatother

\newwrite\myoutputfile
\immediate\openout\myoutputfile=\entriesfilename_PostTreated.txt

\begin{document}
\noindent
% Read the text (.tex or .bib...) file containing the glossary entries definition
\IfFileExists{\entriesfilename.tex}%
{\CatchFileEdef{\glsEntriesListString}{\entriesfilename.tex}{\endlinechar=13}}%
\glsEntriesListString% This call is needed to a good behaviour of \readlist
\ignoreemptyitems% Ingnore empty items from le list
\setsepchar{\newglossaryentry|| /,}% Define separator for nested list with e.g. first list separator "\newglossaryentry" or " " (space) and second list separator "," (comma)
\readlist\myglsentrylist{\glsEntriesListString}% Extract the list from glossary entriesc
\setsepchar{,}% Define separator for the list inside a glossary entry (in order to extract fields)
\foreach \i in {1,2,...,\myglsentrylistlen}{%Loop under the glossary entry list
  \ifodd\i% If odd, print the list element
    \itemtomacro\myglsentrylist[\i]\myglsentrylisttowrite   
    \textbackslash{}newglossaryentry\{\myglsentrylisttowrite\}\{\%\newline
    \immediate\write\myoutputfile{\unexpanded{\newglossaryentry}\myglsentrylisttowrite\wbgroup\percentchar}%
  \else% If even, make another list with the fields after removing curly braces "{}" surronding the fields
    \itemtomacro\myglsentrylist[\i]\myfieldslisttemp    \expandafter\def\expandafter\myfieldslisttemp\myfieldslisttemp % Removing curly braces "{}"
    \setsepchar{,}% Define separator for the list inside a glossary entry (in order to extract fields)
    \readlist*\myfieldslist{\myfieldslisttemp}% Ignore extreme spaces
    \foreach \j in {1,2,...,\myfieldslistlen}{%Loop under the glossary entry list
    \itemtomacro\myfieldslist[\j]\myfieldskeylisttemp
    \setsepchar{=}% Define separator for the list inside a glossary entry (in order to extract fields)
    \readlist\myfieldskeylist{\myfieldskeylisttemp}%
    \itemtomacro\myfieldskeylist[1]\myfieldskeylistONEtowrite
    \indent\myfieldskeylist[1]=\{%First item = field key name     
    \itemtomacro\myfieldskeylist[2]\myfieldskeylistTWOtowrite   
    \ifnum \j=\myfieldslistlen% Last field with NO comma at the end
        \myfieldskeylist[2]\}\newline\}\%\newline
        \immediate\write\myoutputfile{\myfieldskeylistONEtowrite=\myfieldskeylistTWOtowrite}%
        \immediate\write\myoutputfile{\wegroup\percentchar}% closing }
    \else
        \myfieldskeylist[2]\},\newline
        \immediate\write\myoutputfile{\myfieldskeylistONEtowrite=\myfieldskeylistTWOtowrite,}%
    \fi
    }%
  \fi
}
\immediate\closeout\myoutputfile
\end{document}

Explanations:

  • Basically the same code goal as Method 1 but here the entries are also printed directly into a text file (glossary_entries_PostTreated.txt).

  • Some \gls like commands are redefine by their respective "low level" macros in order to use them with \write command (for good expand to the text file) (thanks to Marijn's answer.

  • Curly braces are redefined in order to be printed to a file (see egreg answer).

  • Percent character is redefined in order to be printed to a file (see Joseph Wright answer)..

Limitations and possible improvements :

  • Same as Method 1.
  • Use non documented and non suported "low level" macros as \glo@..@name (the code may break on any update as pointed out by David Carlisle in comment of this question).
  • Only few \gls like commands usable here (\gls=\glstext \glsname \glssymbol).
  • Doesn't Work with new custom fields created by the user.

Bonus:

  • No external tool needed as make4ht or html2text.

Result of both method (glossary_entriesPostTreated.txt file content):

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .