# Making Back-Referencing More Pretty

The question Back-referencing in LaTeX was marked a duplicate, so I can't post to that thread. Nonetheless, I found the code provided there by Ryan Reich to be a good learning exercise. His solution provided a comma-separated list of back references, without spaces.

I just thought that his approach would be even more useful, if it could be modified to produce not just a string of comma separated numbers, but actual legible text that might be used in a document.

So I tried to improve his solution

-
@RyanReich Your code is cited here. –  Steven B. Segletes Mar 13 '13 at 13:45
@lockstep I added back strings as a tag, because the method requires string manipulation (as embodied in \convertword) in order to remove redundant occurances of "and" from the constructed string –  Steven B. Segletes Mar 13 '13 at 18:12
So I am surprised to find. Though, note, that @ tags don't alert someone who isn't already part of the comment thread, so this is purely a coincidence. –  Ryan Reich Mar 13 '13 at 18:32

So here is one solution:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{stringstrings}

\makeatletter

\def\@newbackl@bel#1#2#3{%
\@ifundefined{#1@#2}%
{\global\@namedef{#1@#2}{#3}}
{\cs@g@appendpair{#1@#2}{#3}}%
}
% #1 and #2 are each of the form {a}{b}, and the a and b groups are to be
% concatenated independently.
\def\cs@g@appendpair#1#2{{%
\edef\first{\csname #1\endcsname}%
\edef\firsta{\expandafter\@firstoftwo\first}%
\convertword[q]{\firsta}{and}{}%
\edef\firsta{\thestring}%
\edef\firstb{\expandafter\@secondoftwo\first}%
\convertword[q]{\firstb}{and}{}%
\edef\firstb{\thestring}%
\csxdef{#1}%
{{\firsta, and \@firstoftwo#2}%
{\firstb, and \@secondoftwo#2}}%
}}

% Patching into the existing commands
\def\newbacklabel{\@newbackl@bel B}
\let\backlabel=\label
\patchcmd\backlabel{\newlabel}{\newbacklabel}{}{}
\let\backref=\ref
\patchcmd\backref{r@#1}{B@#1}{}{}
\let\pagebackref=\pageref
\patchcmd\pagebackref{r@#1}{B@#1}{}{}
\pretocmd\ref{\backlabel{#1}}{}{}

\makeatother

\begin{document}
\begin{enumerate}
\item \label{e:1} Part 1, referenced by part(s) \backref{e:1}
on page(s) \pagebackref{e:1}.
\item \label{e:x} Part 2, referenced by part(s) \backref{e:x} on
page(s) \pagebackref{e:x}, and referencing part \ref{e:1}.
\item \label{e:2} Part 3, referencing part \ref{e:1} and \ref{e:x}
\item \label{e:3} Part 4, referencing part \ref{e:1}.
\end{enumerate}
\newpage
\section{A section}
\label{s:1}
Here is another reference to part \ref{e:1}.

\end{document}


And for those frustrated with the slowness of the stringstrings package, here is a longer, but much faster alternative

\documentclass{article}
\usepackage{etoolbox}
\usepackage{stringstrings}

\makeatletter

\def\@newbackl@bel#1#2#3{%
\@ifundefined{#1@#2}%
{\global\@namedef{#1@#2}{#3}}
{\cs@g@appendpair{#1@#2}{#3}}%
}
% #1 and #2 are each of the form {a}{b}, and the a and b groups are to be
% concatenated independently.
\def\cs@g@appendpair#1#2{{%
\edef\first{\csname #1\endcsname}%
\edef\firsta{\expandafter\@firstoftwo\first}%
\replacewordF[q]{\firsta}{and}{}%
\edef\firsta{\thestring}%
\edef\firstb{\expandafter\@secondoftwo\first}%
\replacewordF[q]{\firstb}{and}{}%
\edef\firstb{\thestring}%
\csxdef{#1}%
{{\firsta, and \@firstoftwo#2}%
{\firstb, and \@secondoftwo#2}}%
}}

% Patching into the existing commands
\def\newbacklabel{\@newbackl@bel B}
\let\backlabel=\label
\patchcmd\backlabel{\newlabel}{\newbacklabel}{}{}
\let\backref=\ref
\patchcmd\backref{r@#1}{B@#1}{}{}
\let\pagebackref=\pageref
\patchcmd\pagebackref{r@#1}{B@#1}{}{}
\pretocmd\ref{\backlabel{#1}}{}{}

\usepackage{ifnextok}
\usepackage{ifthen}

\def\string@end{\$}
\def\converttilde{T}
\newcounter{arg@index}
\let\SaveHardspace~

\def\getargsF#1{%
\if T\converttilde\def~{ }\fi%
\protected@edef\the@string{#1}%
\def\argi{}\setcounter{arg@index}{1}%
\expandafter\parse@Block\the@string\string@end%
\let~\SaveHardspace%
}

%ifthenelse needed when leading spaces end up as \argi
\def\parse@Block{\IfNextToken\string@end%
{\edef\narg{\arabic{arg@index}}\@gobble}%
\expandafter\def\csname arg\roman{arg@index}\endcsname{}%

\csname arg\roman{arg@index}\endcsname%
{\csname arg\roman{arg@index}\endcsname#2}\fi#1}

\newcounter{word@count}

% Replaces a word of alphanumeric phrase with another
% Syntax: \replacewordF[mode]{orig_string}{word}{replacement}
% mode is v for verbose, q for quiet (saved in \thestring}
% word is one whole word; cannot contain spaces.
% replacement can be multiword
\newcommand\replacewordF[4][v]{%
\getargsF{#2}%
\edef\thestring{\argi}%
\setcounter{word@count}{1}%
\whiledo{\value{word@count} < \narg}{%
\ifthenelse{\equal{\csname arg\roman{word@count}\endcsname}{#3}}%
{\edef\the@string{\thestring\@sptoken}\edef\thestring{\the@string#4}}%
{\edef\the@string{\thestring\@sptoken}%
\edef\thestring{\the@string\csname arg\roman{word@count}\endcsname}}%
}%
\if v#1\thestring\fi%
}

\makeatother

\begin{document}
\begin{enumerate}
\item \label{e:1} Part 1, referenced by part(s) \backref{e:1}
on page(s) \pagebackref{e:1}.
\item \label{e:x} Part 2, referenced by part(s) \backref{e:x} on
page(s) \pagebackref{e:x}, and referencing part \ref{e:1}.
\item \label{e:2} Part 3, referencing part \ref{e:1} and \ref{e:x}
\item \label{e:3} Part 4, referencing part \ref{e:1}.
\end{enumerate}

\newpage
\section{A section}
\label{s:1}
Here is another reference to part \ref{e:1}.

\end{document}

-
I don't really have anything to add to this. I might suggest that, rather than building the spaces and the "and" directly into \backref, you write an independent macro/function that converts a general comma-separated list into one with these features. That is, a,b,c goes to a, b, and c. This separates the essential from the cosmetic. –  Ryan Reich Mar 13 '13 at 18:42
That's a good point. –  Steven B. Segletes Mar 13 '13 at 18:44