[Tex/LaTex] Long table with X column for usage with glossaries

best practicesglossariesltxtabletabutabularx

Question: I am searching for a way to use X columns in combination with multipage tables in a custom written glossary style.

Update

According to Nicola Talbot's comment, I have created the following MWEs:

1. old approach using tabu:

\documentclass[a4paper,parskip=half]{scrreprt}
\usepackage{setspace}
\AtBeginDocument{\setstretch{1.25}} 
\usepackage{tabu}
\usepackage[xindy, acronyms, nonumberlist, nogroupskip,shortcuts]{glossaries}
\newglossarystyle{customlong}{%
 \renewenvironment{theglossary}%
     {\tabulinesep=1.2mm \begin{longtabu}{@{}lX}}%
     {\end{longtabu}}%
  \renewcommand*{\glossaryheader}{}%
  \renewcommand*{\glsgroupheading}[1]{}%
  \renewcommand*{\glossaryentryfield}[5]{%
    \glstarget{##1}{##2} & ##3\glspostdescription\space ##5\\}%
  \renewcommand*{\glossarysubentryfield}[6]{%
     & \glstarget{##2}{\strut}##4\glspostdescription\space ##6\\}%
  \renewcommand*{\glsgroupskip}{ & \\}%
}

\newacronym{DMSO}{DMSO}{dimethyl sulfoxide}
\newacronym{DABCO}{DABCO}{1,4-diazabicyclo[2.2.2]octane}
\newacronym{longacronym}{longacronym}{description of a long acronym}


\begin{document}
\printglossary[type=acronym,style=customlong]
\acs{DABCO}
\acs{DMSO}
\end{document}

This essentially yields the desired output: The width of the abbreviation column is as expected and the line spacing is not too big.

2. new approach using the alttree style:

\documentclass[a4paper,parskip=half]{scrreprt}
\usepackage{setspace} 
\usepackage[xindy, acronyms, nonumberlist, nopostdot,  numberline, numberedsection=autolabel, nogroupskip,style=long, shortcuts]{glossaries}
\renewcommand{\glossarypreamble}{\glsfindwidesttoplevelname[\currentglossary]}
\renewcommand*{\glstreenamefmt}[1]{#1}
\renewcommand*{\chapterheadstartvskip}{\vspace*{-\topskip}}
\AtBeginDocument{\setstretch{1.25}}

\newacronym{DMSO}{DMSO}{dimethyl sulfoxide}
\newacronym{DABCO}{DABCO}{1,4-diazabicyclo[2.2.2]octane}

\begin{document}
\printglossary[type=acronym,style=alttree]
\acs{DABCO}
\acs{DMSO}
\end{document}

This approach yields the desired width of the abbreviation column, however the linepacing in the list ist too big. This distance seems to be effected by parskip=half and \setstretch{1.25} but as I need those commands to get the desired line spacing in the rest of the document I don't konw how to get rid of them.

3. new approach using the alttree style, strange spacing:

\documentclass[a4paper,parskip=half]{scrreprt}
\usepackage{setspace} 
\usepackage[xindy, acronyms, nonumberlist, nopostdot,  numberline, numberedsection=autolabel, nogroupskip,style=long, shortcuts]{glossaries}
\renewcommand{\glossarypreamble}{\glsfindwidesttoplevelname[\currentglossary]}
\renewcommand*{\glstreenamefmt}[1]{#1}
\renewcommand*{\chapterheadstartvskip}{\vspace*{-\topskip}}
\AtBeginDocument{\setstretch{1.25}}

\newacronym{DMSO}{DMSO}{dimethyl sulfoxide}
\newacronym{DABCO}{DABCO}{1,4-diazabicyclo[2.2.2]octane}
\newacronym{longacronym}{longacronym}{description of a long acronym}

\begin{document}
\printglossary[type=acronym,style=alttree]
\acs{DABCO}
\acs{DMSO}
\end{document}

In this MWE I have included the definition of a long acronym that is not explicitly used in the document itself. However, this long acromym seems to be taken into account while calculating the width of the widest acronym.


Background: I am currently using the glossaries package to print a list of abbreviations and acronyms. The desired style of the list is a two-colum table with the acronym in the left and the long form or description in the right column. Basically this can be achieved by the acronymstyle long-short.

The only problem I have when using this style occurs when I have long acronyms in combination with long forms that need a linebreak in the second column. For these cases I have manually been changing \setlength{\glsdescwidth} to a value that roughly fits the textwidth minus left column width. As the lenght of aconyms keeps changing throughout the writing process I have to keep changing the \setlength{\glsdescwidth} according to the currently needed width. This is always try and error and not that accurate and therefore quite annoying to me.

I have therefore written a custom style that uses the X column and the longtabu environment of the tabu package to determine the width of the second column automatically:

\newglossarystyle{customlong}{%
 \renewenvironment{theglossary}%
     {\tabulinesep=1.2mm \begin{longtabu}{@{}lX}}%
     {\end{longtabu}}%
  \renewcommand*{\glossaryheader}{}%
  \renewcommand*{\glsgroupheading}[1]{}%
  \renewcommand*{\glossaryentryfield}[5]{%
    \glstarget{##1}{##2} & ##3\glspostdescription\space ##5\\}%
  \renewcommand*{\glossarysubentryfield}[6]{%
     & \glstarget{##2}{\strut}##4\glspostdescription\space ##6\\}%
  %\renewcommand*{\glsgroupskip}{ & \\}%
}
\setglossarystyle{customlong}

This has always worked fine for me, but recently I was warned about the usage of the tabu package due to it being buggy and I myself have encountered some strange beahviour as well (although not with the above described glossarystyle).

I have thus considered switching to the tabularx package, that offers variable width X columns as well. But as my list of acronym spreads over more than one page, I need a long table with X columns.
According to the Overview of packages to create tables there are the ltxtable and the ltablex packages to achieve this.
According to the Comparison of ltxtable and ltablex the ltablex seems to have bugs. Unfortunately, the ltxtable requires the table to be in a separate file. I am aware of the filecontents package, but don't konw how to implement it in my case.

Best Answer

As you've noticed \glsfindwidesttoplevelname checks all defined entries rather than only those that have been used. The glossaries-extra-stylemods package (loaded with \usepackage[stylemods]{glossaries-extra}) provides \glsFindWidestUsedTopLevelName which only checks entries that have been marked as used.

This is useful if your glossary is in the back matter. If your glossary is in the front matter (as in your MWE) then the widest used entry must be calculated at the end of the document and saved in the .aux file for the next LaTeX run.

\makeatletter
\AtEndDocument{\glsFindWidestUsedTopLevelName[\acronymtype]%
 \protected@write\@auxout{}{\string\xglssetwidest{\glsgetwidestname}}%
}
\makeatother

The only problem here is that \acs doesn't mark the entry as used, so you'll need at least one \ac (or \gls etc) for each entry referenced in the document for this to work. If you don't want any of the abbreviations to show the full form use the short-nolong abbreviation style.

\setabbreviationstyle[acronym]{short-nolong}% glossaries-extra.sty
\newacronym{DMSO}{DMSO}{dimethyl sulfoxide}
\newacronym{DABCO}{DABCO}{1,4-diazabicyclo[2.2.2]octane}
\newacronym{longacronym}{longacronym}{description of a long acronym}

If you want some abbreviations to show the full form on first use then use \newabbreviation instead of \newacronym for those abbreviations:

\setabbreviationstyle[acronym]{short-nolong}
\setabbreviationstyle{long-short}

% short-nolong abbreviations:
\newacronym{DMSO}{DMSO}{dimethyl sulfoxide}
\newacronym{DABCO}{DABCO}{1,4-diazabicyclo[2.2.2]octane}

% long-short abbreviations:
\newabbreviation{longacronym}{longacronym}{description of a long acronym}

(These abbreviation styles are actually the default settings for glossaries-extra. You'll need to change the acronyms package option to abbreviations if you want this mixture.)

If you really don't want to use \ac (or \gls) then you have to determine which entries have been indexed (rather than being marked as used). This requires either hooking into the indexing mechanism or hooking into the glossary style, both of which still require saving information to the .aux file for the next run.

(Note that longtable also requires saving information to the .aux file to determine the correct column widths for specifiers like l. The contents of each cell needs to be measured to determine the appropriate width for the given column.)

The extra spacing between entries can be dealt with by locally switching off KOMA's parskip option which can be done in \glossarypreamble.

Amended MWE:

\documentclass[a4paper,parskip=half]{scrreprt}
\usepackage{setspace} 
\usepackage[xindy,
  acronyms,% use 'abbreviations' instead for mixture of `\newacronym` and `\newabbreviation`
  nonumberlist,
 %nopostdot, % 'nopostdot' is the default with glossaries-extra.sty
  numberline,
  numberedsection=autolabel,
  nogroupskip,
  stylemods% load glossaries-extra-stylemods.sty
]{glossaries-extra}

\GlsXtrDefineAcShortcuts % provide \ac etc shortcut commands

\renewcommand{\glossarypreamble}{\KOMAoptions{parskip=off}}
\renewcommand*{\glstreenamefmt}[1]{#1}

\renewcommand*{\chapterheadstartvskip}{\vspace*{-\topskip}}
\AtBeginDocument{\setstretch{1.25}}

\makeatletter
\AtEndDocument{\glsFindWidestUsedTopLevelName%
 \protected@write\@auxout{}{\string\xglssetwidest{\glsgetwidestname}}%
}
\makeatother

\makeglossaries

\setabbreviationstyle[acronym]{short-nolong}
\newacronym{DMSO}{DMSO}{dimethyl sulfoxide}
\newacronym{DABCO}{DABCO}{1,4-diazabicyclo[2.2.2]octane}
\newacronym{longacronym}{longacronym}{description of a long acronym}

\begin{document}
\printglossary[type=acronym,style=alttree]
\ac{DABCO}
\ac{DMSO}
\end{document}

image of document

Related Question