0

I want to make a reference to a fragment of my text by giving its page numbers. I am looking for a method that is flexible: sometimes this will be a single page and sometimes a page-range, so using just labels and \pageref is not sufficient. I have found that there are two packages that might be used to deal with this: varioref and cleveref. However, I would like the output to contain only the numbers of pages and nothing more. And I do not know how to achieve this with these packages (or in some other way). For example, here we can see that \vpagerefrange gives as an output "on pages 1-2". Instead, I want to have only the numbers, i.e., only "1-2" without "on pages". Similarly, here we can see that \cpagerefrange yields "pages 1 to 3", where I would like to have just "1-3".

Alternatively, I would like to be able to customize the text that is shown, e.g., to have "pp." (if these are multiple pages) or "p." (if this is a single page) instead of "on pages/on page".

Here is a MWE:

\documentclass{article}
\usepackage{varioref}
\usepackage[english]{babel} 
\begin{document}

\label{text1start}some text

\newpage

more text \label{text1stop}

\newpage

See \vpagerefrange{text1start}{text1stop} \end{document}

It generates ''See on pages 1-2'' on page 3; I would like to customize this outcome, so as to have e.g. ''See on pp. 1-2''.

  • Did you check https://ctan.org/topic/label-ref , perhaps zref and its sibblings? Or refstyle? (<<< refstyle <<<) // BTW: A basic MWE would be nice, even if it doesn't work at the moment ... – MS-SPO Feb 18 '23 at 12:05
  • I think cleveref would be more appropriate for this purpose (or zref-clever), since varioref's task is different (you'd get different output depending on whether the reference is on the same page or a contiguous page to the labels). Untested, but I think all you need is something like \crefname{page}{p.}{pp.} and \Crefname{page}{p.}{pp.}. And, if you want to typeset just the pages, there's \labelcpageref. – gusbrs Feb 19 '23 at 11:57

1 Answers1

2

Among the packages you have already found related to your problem, I think cleveref is clearly the more appropriate one. varioref can produce ranges too, but it's purpose is different, which is to produce contextual page references depending on the relative position of the label(s) and the reference.

cleveref can handle ranges either with \cpagerefrange or with \cpageref. However, \cpagerefrange will always produce a range, even if the pages are the same (like "1-1"). And \cpageref will only produce a range if there are more than two labels. You can trick cleveref a little, by setting a label in duplicity. (You also have to take care of a longstanding bug related to page reference ranges, see https://tex.stackexchange.com/a/620066/105447).

\documentclass{article}
\usepackage[english]{babel}
\usepackage{cleveref}
\crefname{page}{p.}{pp.}
\Crefname{page}{p.}{pp.}
\crefrangeformat{page}{pp.~#3#1#4--#5#2#6}
\Crefrangeformat{page}{pp.~#3#1#4--#5#2#6}

% Fix for pending bug: https://tex.stackexchange.com/a/620066/105447 \makeatletter \newcommand{@setcpagerefrange}[3]{% @@setcpagerefrange{#1}{#2}{cref}{#3}} \newcommand{@setCpagerefrange}[3]{% @@setcpagerefrange{#1}{#2}{Cref}{#3}} \newcommand*{@setlabelcpagerefrange}[3]{% @@setcpagerefrange{#1}{#2}{labelcref}{#3}} \makeatother

\begin{document}

\label{text1start}\label{text1startb}some text

\newpage

more text \label{text1stop}

\newpage

See \cpageref{text1start,text1startb,text1stop}

\end{document}

But that attempt to abuse \cpageref is also problematic, since it would fail if there was a gap between the pages in which the labels are, since \cref and \cpageref only builds ranges when the intermediate values are present. So, for example, if your labels were in pages 1 and 3, you'd get "See pp. 1 and 3".

That given, perhaps zref-clever is an appropriate alternative. It has an overall similar concept to references as cleveref (as the name entails), but it has a somewhat different approach to ranges. Instead of having a dedicated command for ranges, like \crefrange and \cpagerefrange, ranges are built with the range option passed to \zcref, from where we can benefit from sorting, compressing, arbitrary number of labels, etc., and it will build a range from the extremes (but not so if it is a single one, in which case you get a warning but expected output, and depending on configuration, it can also distinguish a "pair"). In practice:

\documentclass{article}
\usepackage[english]{babel}
\usepackage{zref-clever}
\zcLanguageSetup{english}{
  type=page,
    name-sg=p.,
    Name-sg=p.,
    name-pl=pp.,
    Name-pl=pp.,
    % these are defaults for page, but being explicit about your requirements.
    rangesep = {\textendash} ,
    rangetopair = false ,
}

\begin{document}

\section{Section 1}

\zlabel{text1start}some text

\newpage

more text \zlabel{text1stop}

\newpage

See \zcpageref[range]{text1start,text1stop} or \zcref[page,range]{text1start,text1stop}.

% You can also omit the name on demand with the 'noname' option. See \zcref[page,range,noname]{text1start,text1stop}.

\newpage

\section{Section 2} % It will also work for labels in the same page.

\zlabel{text2start}some text

more text \zlabel{text2stop}

\newpage

See \zcpageref[range]{text2start,text2stop}.

\newpage

\section{Section 3} % And also when the labels are not in contiguous pages.

\zlabel{text3start}some text

\newpage

mid page

\newpage

more text \zlabel{text3stop}

\newpage

See \zcpageref[range]{text3start,text3stop}.

\end{document}

A note on label placing. As you likely know, the labels set like that at arbitrary places in the text will retrieve the label information from the last document object which set it. Page references will work as expected, but if you need anything else from the label to "belong to the place where it was set", you can use hyperref's \phantomlabel preceding each label.

Edit: Bonus, it is also possible to handle the task with refcount and standard labels:

\documentclass{article}
\usepackage[english]{babel}
% 'refcount' is required by 'hyperref', if you are already using it, you don't
% need to load it.
\usepackage{refcount}

\ExplSyntaxOn \NewDocumentCommand{\mypagerange}{mm}{ \exp_args:Nee \tl_if_eq:nnTF { \getpagerefnumber {#1} } { \getpagerefnumber {#2} } { p.~\pageref{#1} } { pp.~\pageref{#1}--\pageref{#2} } } \ExplSyntaxOff

\begin{document}

\section{Section 1}

\label{text1start}some text

\newpage

more text \label{text1stop}

\newpage

See \mypagerange{text1start}{text1stop}.

\newpage

\section{Section 2} % It will also work for labels in the same page.

\label{text2start}some text

more text \label{text2stop}

\newpage

See \mypagerange{text2start}{text2stop}.

\newpage

\section{Section 3} % And also when the labels are not in contiguous pages.

\label{text3start}some text

\newpage

mid page

\newpage

more text \label{text3stop}

\newpage

See \mypagerange{text3start}{text3stop}.

\end{document}

gusbrs
  • 13,740