2

I do want to put some source code entries and some figures/images in my appendix for more details see this question), and thus I would find it very useful to have a backlink there (just like you can have in the bibliography or acronym TOC with acro or so), because the part where it is referenced is very far away from where it is printed (i.e. in the appendix).

In short, this question basically assumes the "opposite" of the question „Keeping tables/figures close to where they are mentioned”, i.e. my images/listings are far away from where they are mentioned and thus I'd like a backref for them, so people can find the explanation for a code snippet or image I cite when they just look at the appendix.

I have used hyperref's commands for referencing the figure or listing created via minted, so e.g. \autoref, \nameref or \fullref.

Thus, is it possible somehow to add a backreference (backref/backlink) to the caption – or keeping my other idea in mind of using headlines instead of captions there somewhere else in the text?

I e.g. want a caption like this:

Source code snippet showing how A makes B. (mentioned on pages 5, 7-8.)

The exact style, i.e. whether it is compact and skips pages or what intro it uses ("mentioned on pages" could also just be replaced by "pp." or another abbreviation that is likely already defined in some biblatex or acro macro) so, does not matter, but I e.g. like the style acro uses.)

Edit: As it still does not seem to be clear, I want something like acro does:

I want these "S. 10, 14, 27" etc. backlinks to the page. The answer from @John Kormylo provides a nice example, but is not complete. But I do not want them for an acronym or reference list (biblatex can also do that, I know that), but for some figures/listings/captions in the appendix.

BTW it is enough if it backlinks to the page, it does not have to be the exact position.

There is no MWE I can give, because it does not work here.

Note: For obvious reasons that backref should possibly exclude a link in a TOC like \listoflistings or \listoffigures.

7
  • I would look at the cleverref package first. You might need to use a separate short caption (optional argument), but I believe \label is already disabled in the \addtocline. Aug 17 '20 at 14:39
  • Well, I've looked at it and found no options for backreferencing in cleverref.
    – rugk
    Aug 24 '20 at 10:45
  • 2
    If you have only one \ref, you can create a back reference using \hypertarget and \hyperlink. An Minimal Working Example would really be useful here. Aug 24 '20 at 13:25
  • 1
    @C.F.G No not at al. It's interesting, but I explicitly stated this is about backreferences for figures not the bibliography.
    – rugk
    Aug 26 '20 at 16:46
  • 1
    @C.F.G Ah, now I see why you came there. Yes, it would be a workaround to use the "back" button in your PDF viewer, but that is not really a solution, because I want it to state "This was referred to on page 3" (not in such an elaborate way, but I guess you get what I mean.)
    – rugk
    Aug 26 '20 at 17:13
3

Here is a little something based loosely on biblatex's backref approach.

With each call of \ref/\autoref we send a marker to the .aux file that the label was referenced on this particular page. At the beginning of each LaTeX run we can read the label-page combinations from the .aux file and compile for each label a list of pages where it was referenced. This list can then later be used for printing.

With this simple approach we only link back to pages, not to the exact place the label was referenced, we also do not issue LaTeX rerun warnings automatically.

\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage{etoolbox}
\usepackage{hyperref}

\makeatletter
% stolen from biblatex
% we need a way to check if printable text is in a list
\newrobustcmd{\rugk@ifprintableinlist}[2]{%
  \begingroup
    \def\rugk@tempa{\endgroup
      \@secondoftwo}%
    \renewcommand*{\do}[1]{%
      \ifstrequal{##1}{#1}
        {\def\rugk@tempa{\endgroup
           \@firstoftwo}%
         \listbreak}
        {}}%
    \dolistloop{#2}%
  \expandafter\rugk@tempa}

\newrobustcmd{\rugk@ifprintableinlistcs}[2]{%
  \expandafter\rugk@ifprintableinlistcs@i\csname #2\endcsname{#1}}
\long\def\rugk@ifprintableinlistcs@i#1#2{\rugk@ifprintableinlist{#2}{#1}}

% add <page> to the list of pages where <label> was referenced
% {<label>}{<page>}{<page int>}
\protected\def\rugk@ref@backref#1#2#3{%
  \ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
    {\global\cslet{rugk@ref@backreflist@\detokenize{#1}}\@empty}
    {}%
  \rugk@ifprintableinlistcs{#2}{rugk@ref@backreflist@\detokenize{#1}}
    {}
    {\listcsgadd{rugk@ref@backreflist@\detokenize{#1}}{#2}}}

% write label backref to aux file
% {<label>}
\def\rugk@write@ref@backref#1{%
  \if@filesw
    \protected@write\@mainaux{}{\string\rugk@ref@backref
      {#1}{\thepage}{\noexpand\the\c@page}}%
  \fi}

\newcommand{\backref}[1]{%
  \rugk@write@ref@backref{#1}%
  \ref{#1}%
}
\newcommand{\autobackref}[1]{%
  \rugk@write@ref@backref{#1}%
  \autoref{#1}%
}

\newcounter{backrefpages}
\newcounter{totalbackrefpages}

\newcommand*{\printbackrefpage}[1]{%
  \stepcounter{backrefpages}%
  \hyperlink{page.#1}{#1}%
  \ifnumless{\value{backrefpages}}{\value{totalbackrefpages}}
    {, }
    {}}

\newrobustcmd*{\printlabelbackrefs}[1]{%
  \setcounter{backrefpages}{0}%
  \setcounter{totalbackrefpages}{0}%
  \ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
    {Not referenced}
    {\def\do##1{\stepcounter{backrefpages}}%
     \dolistcsloop{rugk@ref@backreflist@\detokenize{#1}}%
     \setcounter{totalbackrefpages}{\value{backrefpages}}%
     \setcounter{backrefpages}{0}%
     \ifnumgreater{\value{totalbackrefpages}}{1}
       {pp.}
       {p.}~%
     \forlistcsloop{\printbackrefpage}{rugk@ref@backreflist@\detokenize{#1}}}}
\makeatother

\newrobustcmd{\backcaption}[3][]{%
  \if\relax\detokenize{#1}\relax
    \def\rugk@tmpcapt{\caption[#2]}%
  \else
    \def\rugk@tmpcapt{\caption[#1]}%
  \fi
  \rugk@tmpcapt{#2 (see \printlabelbackrefs{#3})}%
  \label{#3}}


\begin{document}
\section{Introduction}
\listoffigures

Here is a reference to \backref{test} and  \autobackref{test}

\clearpage

And here we talk about it again: \autobackref{test}

\clearpage 

\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}

\end{document}

Figure 1: This is a test. (see pp. 1, 2)


An alternative based on labels with a running counter. The backref output will only backref to one backref label per page and label, but that could be changed if you like (it might look weird since you'd get something like "pp. 1, 1").

\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage{etoolbox}
\usepackage{hyperref}

\makeatletter
\newcounter{backrefinst}

% stolen from biblatex
% we need a way to check if printable text is in a list
\newrobustcmd{\rugk@ifprintableinlist}[2]{%
  \begingroup
    \def\rugk@tempa{\endgroup
      \@secondoftwo}%
    \renewcommand*{\do}[1]{%
      \ifstrequal{##1}{#1}
        {\def\rugk@tempa{\endgroup
           \@firstoftwo}%
         \listbreak}
        {}}%
    \dolistloop{#2}%
  \expandafter\rugk@tempa}

\newrobustcmd{\rugk@ifprintableinlistcs}[2]{%
  \expandafter\rugk@ifprintableinlistcs@i\csname #2\endcsname{#1}}
\long\def\rugk@ifprintableinlistcs@i#1#2{\rugk@ifprintableinlist{#2}{#1}}

% add <page> to the list of pages where <label> was referenced
% remember the first instance counter for each label/page combination
% {<label>}{<backref instance counter>}{<page>}{<page int>}
\protected\def\rugk@ref@backref#1#2#3#4{%
  \ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
    {\global\cslet{rugk@ref@backreflist@\detokenize{#1}}\@empty}
    {}%
  \rugk@ifprintableinlistcs{#3}{rugk@ref@backreflist@\detokenize{#1}}
    {}
    {\listcsgadd{rugk@ref@backreflist@\detokenize{#1}}{#3}%
     \csgdef{rugk@ref@backrefinst@\detokenize{#1}@\detokenize{#3}}{#2}}}

% write label backref to aux file
% {<label>}
\def\rugk@write@ref@backref#1{%
  \if@filesw
    \protected@write\@mainaux{}{\string\rugk@ref@backref
      {#1}{\the\value{backrefinst}}{\thepage}{\noexpand\the\c@page}}%
  \fi}

\newcommand*{\rugk@create@backref@label}[1]{%
  \begingroup
    \refstepcounter{backrefinst}%
    \label{backref.\the\value{backrefinst}}%
    \rugk@write@ref@backref{#1}%
  \endgroup
}

\newcommand{\backref}[1]{%
  \ref{#1}%
  \rugk@create@backref@label{#1}%
}
\newcommand{\autobackref}[1]{%
  \autoref{#1}%
  \rugk@create@backref@label{#1}%
}

\newcounter{backrefpages}
\newcounter{totalbackrefpages}

% {<label>}{<page>}
\newcommand*{\printbackrefpage}[2]{%
  \stepcounter{backrefpages}%
  \pageref{backref.\csuse{rugk@ref@backrefinst@\detokenize{#1}@\detokenize{#2}}}%
  \ifnumless{\value{backrefpages}}{\value{totalbackrefpages}}
    {, }
    {}}

\newrobustcmd*{\printlabelbackrefs}[1]{%
  \setcounter{backrefpages}{0}%
  \setcounter{totalbackrefpages}{0}%
  \ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
    {Not referenced}
    {\def\do##1{\stepcounter{backrefpages}}%
     \dolistcsloop{rugk@ref@backreflist@\detokenize{#1}}%
     \setcounter{totalbackrefpages}{\value{backrefpages}}%
     \setcounter{backrefpages}{0}%
     \ifnumgreater{\value{totalbackrefpages}}{1}
       {pp.}
       {p.}~%
     \forlistcsloop{\printbackrefpage{#1}}{rugk@ref@backreflist@\detokenize{#1}}}}
\makeatother

\newrobustcmd{\backcaption}[3][]{%
  \if\relax\detokenize{#1}\relax
    \def\rugk@tmpcapt{\caption[#2]}%
  \else
    \def\rugk@tmpcapt{\caption[#1]}%
  \fi
  \rugk@tmpcapt{#2 (see \printlabelbackrefs{#3})}%
  \label{#3}}

\begin{document}
\section{Introduction}
\listoffigures

Here is a reference to \backref{test} and  \autobackref{test}

\clearpage

And here we talk about it again: \autobackref{test}

\clearpage 

\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}

\end{document}

If you wanted to print all backref occasions, this code could be streamlined a bit: One would only have to remember a list of backref instance counts for each label and not a list of pages for each label.

\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage{etoolbox}
\usepackage{hyperref}

\makeatletter
\newcounter{backrefinst}

% add <page> to the list of pages where <label> was referenced
% remember the first instance counter for each label/page combination
% {<label>}{<backref instance counter>}
\protected\def\rugk@ref@backref#1#2{%
  \ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
    {\global\cslet{rugk@ref@backreflist@\detokenize{#1}}\@empty}
    {}%
  \ifinlistcs{#2}{rugk@ref@backreflist@\detokenize{#1}}
    {}
    {\listcsgadd{rugk@ref@backreflist@\detokenize{#1}}{#2}}}

% write label backref to aux file
% {<label>}
\def\rugk@write@ref@backref#1{%
  \if@filesw
    \protected@write\@mainaux{}{\string\rugk@ref@backref
      {#1}{\the\value{backrefinst}}}%
  \fi}

\newcommand*{\rugk@create@backref@label}[1]{%
  \begingroup
    \refstepcounter{backrefinst}%
    \label{backref.\the\value{backrefinst}}%
    \rugk@write@ref@backref{#1}%
  \endgroup
}

\newcommand{\backref}[1]{%
  \ref{#1}%
  \rugk@create@backref@label{#1}%
}
\newcommand{\autobackref}[1]{%
  \autoref{#1}%
  \rugk@create@backref@label{#1}%
}

\newcounter{backrefpages}
\newcounter{totalbackrefpages}

% {<label>}{<page>}
\newcommand*{\printbackrefpage}[1]{%
  \stepcounter{backrefpages}%
  \pageref{backref.#1}%
  \ifnumless{\value{backrefpages}}{\value{totalbackrefpages}}
    {, }
    {}}

\newrobustcmd*{\printlabelbackrefs}[1]{%
  \setcounter{backrefpages}{0}%
  \setcounter{totalbackrefpages}{0}%
  \ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
    {Not referenced}
    {\def\do##1{\stepcounter{backrefpages}}%
     \dolistcsloop{rugk@ref@backreflist@\detokenize{#1}}%
     \setcounter{totalbackrefpages}{\value{backrefpages}}%
     \setcounter{backrefpages}{0}%
     \ifnumgreater{\value{totalbackrefpages}}{1}
       {pp.}
       {p.}~%
     \forlistcsloop{\printbackrefpage}{rugk@ref@backreflist@\detokenize{#1}}}}
\makeatother

\newrobustcmd{\backcaption}[3][]{%
  \if\relax\detokenize{#1}\relax
    \def\rugk@tmpcapt{\caption[#2]}%
  \else
    \def\rugk@tmpcapt{\caption[#1]}%
  \fi
  \rugk@tmpcapt{#2 (see \printlabelbackrefs{#3})}%
  \label{#3}}

\begin{document}
\section{Introduction}
\listoffigures

Here is a reference to \backref{test} and  \autobackref{test}

\clearpage

And here we talk about it again: \autobackref{test}

\clearpage 

\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}

\end{document}
2
+50

This solution uses \backcaption and \backref instead of \caption\label and \ref.

\documentclass{article}
\usepackage{hyperref}

\newcommand{\backref}[1]% #1 = label name
{\raisebox{\baselineskip}[\ht\strutbox]{\hypertarget{#1.back}{}}\ref{#1}}

\newcommand{\backcaption}[2]% #1 = caption, #2= label
{\caption[#1]{\hyperlink{#2.back}{#1}}\label{#2}}

\begin{document}
\listoffigures

\vspace{2in}
Here is a reference to \backref{test}.

\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}

\end{document}
1
  • 1
    Well, this is a start. Though it misses explciitly mentioning the page number. It just links the caption back to the item. Here is an example file: overleaf.com/read/psbjpnkvsdfb
    – rugk
    Aug 26 '20 at 16:52
1

Okay, thanks to the answer by @John Kormylo I got a partial solution, i.e. if we use a usual \label we can of course use \pageref to refer back to the page.

The only problem is: This also only works if we only have one ref.

Here is some code:

\documentclass{article}
\usepackage[utf8]{inputenc}

\title{test-backref}
\date{August 2020}

\usepackage{hyperref}

% thanks https://tex.stackexchange.com/a/559834/98645
\newcommand{\backref}[1]% #1 = label name
{
    \raisebox{\baselineskip}[\ht\strutbox]{\label{#1.back}{}}%
    \ref{#1}
}
\newcommand{\autobackref}[1]% #1 = label name
{
    \raisebox{\baselineskip}[\ht\strutbox]{\label{#1.back}{}}%
    \autoref{#1}
}

\newcommand{\backcaption}[2]% #1 = caption, #2= label
{\caption[#1]{#1 (see p.~\pageref{#2.back})}\label{#2}}
\newcommand{\backcaptionoptional}[3]% #1 optional label, 2 = caption, #3= label
{\caption[#1]{#2 (see p.~\pageref{#3.back})}\label{#3}}


\begin{document}

\maketitle

\section{Introduction}
\listoffigures

\vspace{2in}
Here is a reference to \backref{test} and  \autobackref{test}….

\newpage

And here we talk about it again: \autobackref{test}

\newpage 

\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}

\end{document}

Note that it also demonstrates the problem. LaTeX (rightfully) complains:

You have used the same label more than once. Check that each \label{...} labels only one item.

This happens, because I do have referred to that figure multiple times. In the end, the output just uses the last label as a reference.

So it's not quite finished, but I guess we would need to use counters or so to count labels for a full solution? Would not we? (If you have any idea, please feel free to submit and use this as your base.)

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.