1

I was wondering if anyone could help me with this:

I've got this report for which I show the paragraph numbers. The paragraph number is then used as part of the label so I can extract it later on, and I have standard label names e.g. sci1, sci2, clin1, etc.

I need to produce a list of the paragraph and page numbers at which each of the labels appear separately (see image). I could do it manually but my report is quite big so was wondering if I could write a macro to do it "automatically" since I've standardised the labels.

I've browsed the internet for solution and tried working with and modifying the code from List of all labels with hyperlinks with no luck unfortunately.

I am fairly new to Latex so would welcome any suggestions, corrections or what not :)

MWE:

\documentclass{article}

\usepackage{hyperref}
\usepackage{xstring}
\usepackage{blindtext}

\newcounter{par}
\newenvironment{pns}{\everypar={\refstepcounter{par}\makebox[0pt]{\makebox[15ex][l]{\arabic{par}}}}}

\long\def\findlabel#1#2\findlabel{\ifx\newlabel#1\complist\expandafter{\the\complist\showlabel#2}\fi}

\def\showlabel#1#2{\S\texttt{\ref{#1}~(p.\pageref{#1})}}

\newtoks\complist
\newread\zz
\immediate\openin\zz=\jobname.aux
\loop
\ifeof\zz\else
\read\zz to \tmp
\expandafter\findlabel\tmp\relax\findlabel
\repeat

\begin{document}

\section{Text}
\begin{pns}
\blindtext\label{sci1:1}

\blindtext\label{sci2:1}
\end{pns}

\subsection{other}
\begin{pns}
\blindtext[2]\label{sci1:2}

\blindtext

\blindtext\label{clin1:1}

\end{pns}

\section*{Labels}

This is the list of all labels:

\the\complist
\vspace{12pt}

And this is what I would like it to look like:

\vspace{12pt}

\begin{tabular}{r|l}
Sci1 & \S\ref{sci1:1} (p.\pageref{sci1:1}), \S\ref{sci1:2} (p.\pageref{sci1:2}) \\
Sci2 & \S\ref{sci2:1} (p.\pageref{sci2:1})\\
Clin1 & \S\ref{clin1:1} (p.\pageref{clin1:1})\\

\end{tabular}

\end{document}

enter image description here

  • If you look at the aux file, you will see that every label creates a \newlabel macro (note, the number of arguments varies depending on packages like hyperref). \newlabel in turn creates macros named \r@foo where foo is the label name. So you could search for all names using your naming convention using \@ifundefined. – John Kormylo May 31 '18 at 14:36
  • Or you could modify \newlabel to create the list automatically. – John Kormylo May 31 '18 at 14:43
  • Hi John. Thank you for your reply! Do you mean something like: \makeatletter \newcommand{\mylabel}[1]{ \@ifundefined{r@#1}{X}{\S\ref{#1} (p.\pageref{#1})} } \makeatother – Bee Girard May 31 '18 at 14:48
  • Also would you be able to expand on what you mean by modifying \newlabel? – Bee Girard May 31 '18 at 14:49
1

This does part of what your want. I didn't try to convert sci1:1 into Sci1 nor combine sci1:1 and sci1:2 into a list. The xstring package can do that sort of thing.

It occurred to me that all you really need is a list of all the label names. Once you have that, you can search and formal almost anything.

You can construct lists as macros, tokens or even saveboxes. The problem with macros is that you need to use \edef or \xdef to add new items to the list, and \ref and \pageref are not expandable. A savebox uses \unvbox or \unhbox and is completely formatted ahead of time (no tabular).

\documentclass{article}

\usepackage{hyperref}
\usepackage{xstring}
\usepackage{blindtext}

\newcounter{par}
\newenvironment{pns}{\everypar={\refstepcounter{par}\makebox[0pt]{\makebox[15ex][l]{\arabic{par}}}}}

\newcommand{\showlabel}[1]{#1&\S\texttt{\ref{#1}}&\texttt{(p.\pageref{#1})}\\}

\newtoks\complist
\let\XXXnewlabel=\newlabel% \oldlabel and \oldnewlabel already used
\renewcommand{\newlabel}[2]{% #1=label, #2=\r@label arguments
  \XXXnewlabel{#1}{#2}%
  \global\complist\expandafter{\the\complist\expandafter\showlabel{#1}}
}

\begin{document}

\section{Text}
\begin{pns}
\blindtext\label{sci1:1}

\blindtext\label{sci2:1}
\end{pns}

\subsection{other}
\begin{pns}
\blindtext[2]\label{sci1:2}

\blindtext

\blindtext\label{clin1:1}

\end{pns}

\section*{Labels}

This is the list of all labels:

\begin{tabular}{r|rl}
  \the\complist
\end{tabular}
\vspace{12pt}

And this is what I would like it to look like:

\vspace{12pt}

\begin{tabular}{r|l}
Sci1 & \S\ref{sci1:1} (p.\pageref{sci1:1}), \S\ref{sci1:2} (p.\pageref{sci1:2}) \\
Sci2 & \S\ref{sci2:1} (p.\pageref{sci2:1})\\
Clin1 & \S\ref{clin1:1} (p.\pageref{clin1:1})\\

\end{tabular}

\end{document}

demo

  • Thank you SO much John! Makes perfect sense and solves my problem! – Bee Girard May 31 '18 at 16:51

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.