3

I thought I was pretty cool when I modified \ref to also print a page number when the referenced float was more than a few pages back. But I really want it to be a nice link using the hyperref package as well!

How can I modify my command so that it will cause the page number to also be a link?

\documentclass{report}

\usepackage{mwe}
% \usepackage[% Un-commenting this causes the page number not to appear
  % pagebackref=true,
  % ]{hyperref}

\usepackage{ifthen}
\usepackage{calc}
\usepackage{xspace}
\let\oldref\ref
\renewcommand\ref[1]{%
  \newcount\cnt
  \cnt=\thepage
  \advance\cnt by -2
  \ifthenelse{%
    \pageref{#1} < \cnt%
    }{%
    \oldref{#1}~p.\,\pageref{#1}\xspace%
    }{%
    \oldref{#1}%
    }%
  }


\begin{document}

\blindtext[1]
Figure~\ref{fig:example_image_a} 
%
\begin{figure}
  \centering
  \includegraphics[width=0.6\textwidth]{example-image-a}%
  \caption{
  example-image-a
  \label{fig:example_image_a}
  }
\end{figure}

\Blindtext[10][10]

Figure~\ref{fig:example_image_a}

\end{document}
  • 1
    Why don't you just use the varioref package? – daleif Nov 6 '15 at 17:52
  • @daleif Ignorance! But also, a bit of digging around in tex.se revealed this gem from tex.stackexchange.com/a/83051/45296 : "There are too many problems with varioref. Nobody has time to sort them out. Therefore this package is now unsupported." That said, it has been a while so I will take another look at cleveref – repurposer Nov 6 '15 at 18:03
  • 1
    I've not had too many problems with varioref, and it is AFAIK still supported. Only problem is when it hits at a page boundary – daleif Nov 6 '15 at 18:24
  • @daleif I would have to mess around with it too much, I think. I want all off the page refs to be "p. X" and not "previous page" or even typed out "page" – repurposer Nov 6 '15 at 18:26
  • 1
    There are some useful tools in varioref that can be used to determine if you are on the same page as a given label – daleif Nov 6 '15 at 18:36
4

hyperref overrules \ref, unless the new definition is in \AtBeginDocument

egreg will strike me down for keeping xspace ;-)

In addition: I doubt that \pageref{#1} will give a number at all, if it's inside the \ifthenelse expression.

I used \getpagerefnumber from refcount which provides a number which can be used in calculations.

Additionally, I shifted the allocation of \cnt outside of \ref -- otherwise there would be an allocation of a count register each time \ref is called!.

\documentclass{report}

\usepackage{mwe}

\usepackage[% Un-commenting this causes the page number not to appear
% pagebackref=true,
]{hyperref}


\usepackage{refcount}

\usepackage{calc}
\usepackage{xspace}
\let\oldref\ref

\newcount\cnt


\AtBeginDocument{%
   \renewcommand\ref[1]{%
     \cnt=\value{page}%
     \advance\cnt by -2
     \ifnum\cnt > \getpagerefnumber{#1}
     \oldref{#1}~p.\,\pageref{#1}\xspace%
     \else
     \oldref{#1}%
     \fi
    }
  }



\begin{document}

\blindtext[1]
Figure~\ref{fig:example_image_a} 
%
\begin{figure}
  \centering
  \includegraphics[width=0.6\textwidth]{example-image-a}%
  \caption{
  example-image-a
  \label{fig:example_image_a}
  }
\end{figure}

\Blindtext[10][10]

Figure~\ref{fig:example_image_a}

\end{document}
  • Beat me to it by 5 seconds! This question might be a helpful link as well. – Guho Nov 6 '15 at 18:35
  • Ok, and since \let\oldref\ref is not in \AtBeginDocument{}, \oldref works as normal \ref with \hyperref – repurposer Nov 6 '15 at 18:39
  • @Guho: Yes, but you should undelete your solution! – user31729 Nov 6 '15 at 18:41
  • @repurposer: Yes, that's true – user31729 Nov 6 '15 at 18:41
  • Works a treat! Watch the < should be > since the \cnt is before \getpagerefnumber{#1} – repurposer Nov 6 '15 at 18:52
3

Rather than redefine \ref, you may want to look into loading the varioref package and using that package's \vref and \fullref macros. They basically do what your modified \ref macro does.

If the hyperref package is loaded as well, with \fullref the figure number (e.g., "n") and the page number (e.g, "m") are separate hypertargets. With \vref, the entire string [Figure] "n on page m" is a single hypertarget.

\documentclass{report}
\usepackage{mwe}
\usepackage{varioref}
\usepackage[colorlinks]{hyperref}

\begin{document}
Figure \vref{fig:example_image_a} 

\blindtext[1]

\begin{figure}[h!]
  \centering
  \includegraphics[width=0.6\textwidth]{example-image-a}%
  \caption{example-image-a}\label{fig:example_image_a}
\end{figure}

\Blindtext[10]

Figure \fullref{fig:example_image_a}

Figure \vref{fig:example_image_a}
\end{document}
3

The following is a slightly different approach to Christian's. It creates an automated \label for each \ref in order to ensure that the page numbering will be accurate.

enter image description here

\documentclass{article}

\usepackage{lipsum}% Just for this example
\usepackage{refcount,hyperref,graphicx}

\newcounter{refcnt}

\AtBeginDocument{%
  \let\oldref\ref
  \renewcommand\ref[1]{%
    \oldref{#1}% Place reference...
    \stepcounter{refcnt}\label{mark-\therefcnt}% Mark current \ref
    \ifnum\getpagerefnumber{mark-\therefcnt} > \numexpr\getpagerefnumber{#1}+2\relax
      \nobreakspace p.\,\pageref{#1}% ...conditionally place page ref
    \fi
  }%
}

\begin{document}
\sloppy% Just for this example
\lipsum[1]

Figure~\ref{fig:example_image}.

\begin{figure}[ht]
  \centering
  \includegraphics[width=0.6\textwidth]{example-image}%
  \caption{example-image}\label{fig:example_image}
\end{figure}

\lipsum[2-15]

Figure~\ref{fig:example_image}.

\end{document}

The above approach only considers a reference backward of more than 2 pages. If the addition of a page number should be considered for a forward reference as well, that can be added.

  • Why is it important to mark the ref but not the float? – repurposer Nov 6 '15 at 19:41
  • @repurposer: I have marked the float. However, I also mark the \ref with an internal \label{mark-\therefcnt} because the processing of your \ref could happen around the pages being shipped out. This might be problematic when working with the page counter directly an in Christian's answer. Here is an example where the \ref is around the page break and it's not properly picked up using his approach. – Werner Nov 6 '15 at 19:46

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.