9

In the glossary, I need to show the "page/line" of each occurrence of a term, e.g.:

Glossary

  clamour
    1) plainte, cri. 24/10, 40/5
    2) requête. 50/24, 50/28

Would this be possible using the glossaries package (or any other package)?

6
  • 1
    With lineno package it is possible via cross reference, I think.
    – Leo Liu
    Commented Mar 16, 2013 at 12:33
  • Welcome to TeX.sx! Commented Mar 16, 2013 at 12:33
  • @Leo Liu: yes, with \linelabel, but \linelabel does not work in display math. So, if the term happened to be inside a display math, the equation number has to be used instead of the line number.
    – g.kov
    Commented Mar 16, 2013 at 13:27
  • 1
    Can you add a minimal working example? Commented Mar 16, 2013 at 20:48
  • 1
    @g.kov: I don't need any glossary entries inside math. Does it simplify the solution?
    – dgaspar
    Commented Mar 17, 2013 at 20:15

2 Answers 2

7
+25

If you're not interested in collating the location lists, the following will work:

% arara: pdflatex
% arara: makeglossaries
% arara: pdflatex
\documentclass{article}

\usepackage[pagewise]{lineno}
\usepackage{etoolbox}
\usepackage[subentrycounter]{glossaries}

\usepackage{lipsum}

\makeglossaries

\newcounter{glslabcount}

\renewcommand*{\glsentryfmt}{%
  \stepcounter{glslabcount}%
  \edef\thislabel{glslab:\arabic{glslabcount}}%
  \expandafter\linelabel\expandafter{\thislabel}%
  \ifcsundef{glsreflist.\glslabel}%
  {\csdef{glsreflist.\glslabel}{}}{}%
  \listcsxadd{glsreflist.\glslabel}{\thislabel}%
  \glsgenentryfmt
}

\newglossaryentry{clamour}{name={clamour},description={}}
\newglossaryentry{clamour1}{parent={clamour},description={plainte, cri}}
\newglossaryentry{clamour2}{parent={clamour},description={requ\^ete}}

\newcommand{\glslisthandler}[1]{%
  \glslisthandlersep
  \pageref{#1}/\ref{#1}%
  \def\glslisthandlersep{, }%
}

\newglossarystyle{pagelineno}%
{%
  \setglossarystyle{index}%
  \renewcommand*{\glossentry}[2]{%
     \item\glsentryitem{##1}\glstarget{##1}{\glossentryname{##1}}%
     \ifcsdef{glsreflist.##1}%
     {%
       . 
       \def\glslisthandlersep{}%
       \forlistcsloop{\glslisthandler}{glsreflist.##1}%
     }{}%
  }%
  \renewcommand{\subglossentry}[3]{%
    \ifcase##1\relax
      \item
    \or
      \subitem
      \glssubentryitem{##2}%
    \else
      \subsubitem
    \fi
    \glstarget{##2}%
    \glossentrydesc{##2}.
    \ifcsdef{glsreflist.##2}%
    {%
      \def\glslisthandlersep{}%
      \forlistcsloop{\glslisthandler}{glsreflist.##2}%
    }{}%
  }%
}

\setglossarystyle{pagelineno}

\begin{document}
\linenumbers

\lipsum*[1] TEST: \gls{clamour1}
\lipsum[2-4]

% Have some entries on a page spanning paragraph:
\lipsum*[5] TEST: \gls{clamour2}
\lipsum*[6] TEST: \gls{clamour1}, \gls{clamour2}.
\lipsum[7]

\lipsum[8]

\printglossaries
\end{document}

The glossary looks like:

Image of glossary

This works by making a label every time an entry is referenced and storing the label in a list corresponding to that entry. This list is then iterated through when the entry is displayed in the glossary. This just uses makeindex to sort the entries. It ignores the real location list. The only problem will be if you have an entry that appears more than once on the same line, as then you'll get a repeated reference.

Edit:

For the cross-referenced term, I'm assuming you don't intend to use this term in the document, but just want it to appear in the glossary with the cross-reference. This can be done by editing the style to include the location list only if \glsreflist.label hasn't been defined:

% arara: pdflatex
% arara: makeglossaries
% arara: pdflatex
\documentclass{article}

\usepackage[pagewise]{lineno}
\usepackage{etoolbox}
\usepackage[subentrycounter]{glossaries}

\usepackage{lipsum}

\makeglossaries

\newcounter{glslabcount}

\renewcommand*{\glsentryfmt}{%
  \stepcounter{glslabcount}%
  \edef\thislabel{glslab:\arabic{glslabcount}}%
  \expandafter\linelabel\expandafter{\thislabel}%
  \ifcsundef{glsreflist.\glslabel}%
  {\csdef{glsreflist.\glslabel}{}}{}%
  \listcsxadd{glsreflist.\glslabel}{\thislabel}%
  \glsgenentryfmt
}

\newglossaryentry{clamour}{name={clamour},description={}}
\newglossaryentry{clamour1}{parent={clamour},description={plainte,
cri}}
\newglossaryentry{clamour2}{parent={clamour},description={requ\^ete}}

\newglossaryentry{cri}{name={cri},description={bla bla},see=[voir]{clamour}}

\newcommand{\glslisthandler}[1]{%
  \glslisthandlersep
  \pageref{#1}/\ref{#1}%
  \def\glslisthandlersep{, }%
}

\newglossarystyle{pagelineno}%
{%
  \setglossarystyle{index}%
  \renewcommand*{\glossentry}[2]{%
     \item\glsentryitem{##1}\glstarget{##1}{\glossentryname{##1}}%
     \ifcsdef{glsreflist.##1}%
     {%
       . 
       \def\glslisthandlersep{}%
       \forlistcsloop{\glslisthandler}{glsreflist.##1}%
     }%
     {, ##2}% <- add location list to ensure cross-reference is included
  }%
  \renewcommand{\subglossentry}[3]{%
    \ifcase##1\relax
      \item
    \or
      \subitem
      \glssubentryitem{##2}%
    \else
      \subsubitem
    \fi
    \glstarget{##2}%
    \glossentrydesc{##2}.
    \ifcsdef{glsreflist.##2}%
    {%
      \def\glslisthandlersep{}%
      \forlistcsloop{\glslisthandler}{glsreflist.##2}%
    }{}%
  }%
}

\setglossarystyle{pagelineno}

\begin{document}
\linenumbers

\lipsum*[1] TEST: \gls{clamour1}
\lipsum[2-4]

% Have some entries on a page spanning paragraph:
\lipsum*[5] TEST: \gls{clamour2}
\lipsum*[6] TEST: \gls{clamour1}, \gls{clamour2}.
\lipsum[7]

\lipsum[8]

\printglossaries
\end{document}

The glossary now looks like:

Image of glossary

2
  • It works as expected, thanks! I am now trying to add an entry with a "see" reference, e.g.: \newglossaryentry{cri}{name={cri},description={bla bla},see=[voir]{clamour}}, but "see" is being ignored by the custom style, could you please advise?
    – dgaspar
    Commented Apr 21, 2014 at 19:22
  • @dgaspar I've added an extra example. Commented Apr 21, 2014 at 19:37
6

Yes, it is possible. Here is one approach. We use package lineno to do the line numbering. Then we convince the glossaries package to write <pagenumber>.<linenumber> into the raw index file. As the line number is not known when we typeset a particular glossary term in the text, we have to write the running line counter, and compute the page-wise line number from that when we typeset the glossary. To do so, we use the built-in macros of glossaries to dissect the location list. These macros exist for usage with hyperref, but we force glossaries to use them even without hyperref. In the final step, when only the composite page number is to be typeset with \@gls@numberlink, we make the page number into a link if desired, and compute the correct page-wise line number of the glossary term.

\documentclass{article}

\usepackage{lipsum}

\usepackage[colorlinks]{hyperref}
\usepackage[pagewise]{lineno}
\usepackage[subentrycounter]{glossaries}
\usepackage{glossary-tree}
\usepackage{etoolbox}

\makeglossaries
%% number sub entries with a), b) etc.
\renewcommand*{\glssubentrycounterlabel}{\alph{glossarysubentry})\space}

\makeatletter
%% write the running line number into the source index file
\patchcmd{\@@do@wrglossary}
  {\protected@xdef\@glslocref{\theglsentrycounter}}
  {\protected@xdef\@glslocref{\theglsentrycounter.\thelinenumber}}
  {}{\message{^^JPatching failed^^J}}

%% If we feed the page list (containing \delimR ranges or \delimN enumerations)
%% to \glshypernumber (even without hyperref),
%% we end up being our composite numbers (page.line) being fed to
%% \@glshypernumber, thus to \@gls@numberlink
\renewcommand{\glsnumberformat}[1]{%
  \glshypernumber{#1}}

\def\glshypernumber#1{\@glshypernumber#1\nohyperpage{}\@nil}
%% in case hyperref is not loaded, make \hyperlink just write the link text
\providecommand{\hyperlink}[2]{#2}

\let\orig@gls@numberlink\@gls@numberlink
\renewcommand{\@gls@numberlink}[1]{%
  \myformatnumb#1\@nil}

\def\myformatnumb#1.#2\@nil{%
  \orig@gls@numberlink{#1}/\getpagewiselinenumber{#2}}

\makeatother

%% a main entry and two sub-entries
\newglossaryentry{clamour}{%
  name = {clamour},
  description = {\nopostdesc},
}
\newglossaryentry{plainte}{%
  parent = clamour,
  name = {plainte, cri},
  description = {\nopostdesc},
}
\newglossaryentry{requete}{%
  parent = clamour,
  name = {requ\^ete},
  description={\nopostdesc},
}

\pagewiselinenumbers

\begin{document}
\lipsum[1-2]
\gls{plainte}

\lipsum[3-4]
\gls{requete}

\lipsum[5-6]
\gls{requete}

\gls{requete}

\gls{requete}

\lipsum[7-8]
\gls{plainte}

\nolinenumbers%
\printglossary[style=index]
\end{document}

sample output

3
  • This seems to work correctly only when the glossed terms appear at the beginnings of paragraphs. When this is not the case, the line number references in the glossary are incorrect. In your example, if you simply change \usepackage{lipsum} to \usepackage[nopar]{lipsum}, so that not all of the \gls entries begin a paragraph, the line numbers in the glossary will be inaccurate. Commented Aug 12, 2013 at 18:45
  • @JeffreyBarnes You are right. Need to investigate further.
    – mafp
    Commented Aug 14, 2013 at 22:01
  • Do you think you could come up with a simple fix to show the actual line number when inside a paragraph?
    – dgaspar
    Commented Mar 2, 2014 at 12:52

You must log in to answer this question.

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