2

I want to use all of the functionality of cleveref, but I would like to add one thing. I want that after the label comes a subscript with the page number, an arrow to the left if it is the preceding page or an arrow to the right if it is the subsequent page. For example, something like "Equation 5_1" or "Theorems 1_10 and 2_12".

I have tried to implement this by using both the varioref and the cleveref package, as in the following MWE.

\documentclass{article}

\usepackage{MnSymbol}

\usepackage{varioref}
\newcommand*{\reallythepageref}[1]{\pageref{#1}}
\renewcommand*{\reftextbefore}{\unskip\textsubscript{\(\lcurvearrowleft\)}}
\renewcommand*{\reftextfacebefore}{}
\renewcommand*{\reftextcurrent}{}
\renewcommand*{\reftextafter}{\unskip\textsubscript{\(\lcurvearrowright\)}}
\renewcommand*{\reftextfaceafter}{\unskip}
\renewcommand*{\reftextfaraway}[1]{\unskip\textsubscript{{\upshape\reallythepageref{#1}}}}
\renewcommand*{\reftextpagerange}[2]{\unskip\textsubscript{\upshape{\reallythepageref{#1}--\reallythepageref{#2}}}}
\renewcommand*{\reftextlabelrange}[2]{{\ref{#1}--\ref{#2}}}

\usepackage{cleveref}

\begin{document}

\vref{sec1} --- \vref{sec2} --- \vref{sec3}

\vref{sec1,sec2} --- \vref{sec1,sec2} --- \vref{sec1,sec3}

\vref{sec1,sec2,sec3}

\clearpage
\section{Section 1}
\label{sec1}

\clearpage
\section{Section 2}
\label{sec2}

\clearpage
\section{Section 3}
\label{sec3}

\end{document}

If I build this, I get some weird behaviour: compiled MWE Clearly, we get an undesired and... Any ideas on how to get rid of this?

1

I think the most elegant solution would be patching cleveref's \crefdefaultlabelformat-command etc to not only provide
#1 - formatted counter value
#2 - tokens that form the begin of nesting in a hyperlink
#3 - tokens that form the end of nesting in a hyperlink
but to also provide #4 or the like for obtaining the referenced referencing-label itself.

Then you could apply nested referencing-commands (that don't do hyperlinking) via the referencing-formatting-specifications.

I looked into the code of cleveref and found that patching cleveref would require a lot of work because all the internal commands for actually typesetting references would need to be patched, too, in order to take one more argument into account—not something that I can do off the cuff on a Sunday evening. ;-)

As a quick and dirty workaround—!!!no warranties of any kind!!!—I suggest the following:

As it is about referencing page-numbers as well and as varioref is about prettifying references to pages/page-numbers, I suggest not using the \vref-command but the \vpageref-command.

The underlying command \@@@setvpageref can be patched to make available not only the page-number (via \thevpagerefnum) but also the displayed value and the referencing-label itself (so that it can be used for nesting referencing-commands).

(You may wish to enhance further by applying the abspage-module of Heiko Oberdiek's zref-package for obtaining "absolute page-numbers" no matter if \thepage delivers arabic numerals denoting a positive integer or not. But this will require patching all routines for placing referencing-labels and all routines for extracting page-numbers from referencing-labels in order to calculate the refrencing-phrases, i.e., varioref's-label-placement- and page-number-extraction-routines.)

\documentclass{article}

\usepackage{MnSymbol}
\usepackage{refcount}
\usepackage{varioref}
\usepackage{hyperref}
\usepackage{cleveref}

\makeatletter

% Something that checks whether the label placed by the current varioref-command
% is somewhere before/behind/on the same page as the label that is to be referenced:

\DeclareRobustCommand\LabelBeforeOnAfterCurrentPage[5]{% Label, Before, On, After, Undefined
  \is@pos@number{\getrefbykeydefault{\the\c@vrcnt @vr}{page}{-1}}{%
    \is@pos@number{\getrefbykeydefault{#1}{page}{-1}}{%
      \ifnum\numexpr
              \getrefbykeydefault{\the\c@vrcnt @vr}{page}{-1}%
              -%
              \getrefbykeydefault{#1}{page}{-1}%
            \relax=0 %
      \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
      {#3}{%
        \ifnum\numexpr
                \getrefbykeydefault{\the\c@vrcnt @vr}{page}{-1}%
                -%
                \getrefbykeydefault{#1}{page}{-1}%
              \relax<0 %
        \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
        {#4}{#2}%
      }%
    }{#5}%
  }{#5}%
}%

%
% Patch the page-referencing-mechanism of varioref to also make the number of the counter
% and the name of the referencing-label available:
%
\newcommand\thevrefnum{}%
\newcommand\thevlabel{}%
\def\@@@setvpageref#1[#2]#3{%
  \leavevmode%\unskip  <<<
  \global\advance\c@vrcnt\@ne\relax%
  \vref@pagenum\@tempa{\the\c@vrcnt @vr}%
  \vref@pagenum\@tempb{\the\c@vrcnt @xvr}%
  %\vref@label{\the\c@vrcnt @xvr}%  <<<
  \ifx\@tempa\@tempb\else%
    \vref@err{\noexpand\vref or \noexpand\vpageref at page boundary
              \@tempb-\@tempa\space (may loop)%
              }%
  \fi%
  \vrefpagenum\thevpagerefnum{#3}%
  %%%%%%%%%%%%%%%
  \expandafter\expandafter\expandafter\def
  \expandafter\expandafter\expandafter\thevrefnum
  \expandafter\expandafter\expandafter{%
    \getrefbykeydefault{#3}{}{%
      \nfss@text{\reset@font\bfseries??}\refused{#3}%
    }%
  }%
  \def\thevlabel{#3}%
  %%%%%%%%%%%%%%%
  \vref@space%
  \ifx\@tempa\thevpagerefnum%
    \def\@tempc{#1}%
    \ifx\@tempc\@empty%
       \unskip%
    \else%
       #1%
    \fi%
  \else%
    #2%
    \is@pos@number\thevpagerefnum%
       {%
        \is@pos@number\@tempa%
         {\@tempcnta\@tempa%
          \advance\@tempcnta\@ne\relax%
         }%
         {\@tempcnta\maxdimen}%
        \ifnum \thevpagerefnum =\@tempcnta%
         \ifodd\@tempcnta%
           \if@twoside%
             \reftextfaceafter%
           \else%
             \reftextafter%
           \fi%
         \else%
           \reftextafter%
         \fi%
        \else%
          \advance\@tempcnta-2\relax%
          \ifnum \thevpagerefnum =\@tempcnta%
            \ifodd\@tempcnta%
              \reftextbefore%
            \else%
              \if@twoside%
                \reftextfacebefore%
              \else%
                \reftextbefore%
              \fi%
            \fi%
          \else%
            \reftextfaraway{#3}%
          \fi%
        \fi%
       }%
       {\reftextfaraway{#3}}%
  \fi%
  \vref@label{\the\c@vrcnt @xvr}%  <<<
  \vref@label{\the\c@vrcnt @vr}%
}%

\newcommand\MyVref@SwitchDefaults[1]{%
  \renewcommand*{\reftextbefore}{%
   #1{\hyperref[\thevlabel]}{%
    \autoref*{\thevlabel}%
    \textsubscript{%
      {\upshape\thevpagerefnum}\LabelBeforeOnAfterCurrentPage{\thevlabel}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
  \renewcommand*{\reftextfacebefore}{%
   #1{\hyperref[\thevlabel]}{%
    \autoref*{\thevlabel}%
    \textsubscript{%
      {\upshape\thevpagerefnum}\LabelBeforeOnAfterCurrentPage{\thevlabel}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
  \renewcommand*{\reftextcurrent}{%
   #1{\hyperref[\thevlabel]}{%
    \autoref*{\thevlabel}%
    \textsubscript{%
      {\upshape\thevpagerefnum}\LabelBeforeOnAfterCurrentPage{\thevlabel}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
  \renewcommand*{\reftextafter}{%
   #1{\hyperref[\thevlabel]}{%
    \autoref*{\thevlabel}%
    \textsubscript{%
      {\upshape\thevpagerefnum}\LabelBeforeOnAfterCurrentPage{\thevlabel}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
  \renewcommand*{\reftextfaceafter}{%
   #1{\hyperref[\thevlabel]}{%
    \autoref*{\thevlabel}%
    \textsubscript{%
      {\upshape\thevpagerefnum}\LabelBeforeOnAfterCurrentPage{\thevlabel}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
  \renewcommand*{\reftextfaraway}[1]{%
   #1{\hyperref[\thevlabel]}{%
    \autoref*{\thevlabel}%
    \textsubscript{%
      {\upshape\thevpagerefnum}\LabelBeforeOnAfterCurrentPage{\thevlabel}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
  \renewcommand*{\reftextpagerange}[2]{%
   #1{\hyperref[##1]}{%
    \autoref*{##1}%
    \textsubscript{%
      {\upshape\getrefbykeydefault{##1}{page}{\refused{##1}}}%
      \LabelBeforeOnAfterCurrentPage{##1}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
   ~to~%
   #1{\hyperref[##2]}{%
    \autoref*{##2}%
    \textsubscript{%
      {\upshape\getrefbykeydefault{##2}{page}{refused{##2}}}%
      \LabelBeforeOnAfterCurrentPage{##2}{\(\lcurvearrowleft\)}{}{\(\lcurvearrowright\)}{}%
    }%
   }%
  }%
}%

\DeclareRobustCommand\MyVref{\@ifstar{\@MyVref{\@secondoftwo}{*}}{\@MyVref{\@firstofone}{}}}%
\newcommand\@MyVref[2]{\@ifnextchar[{\@@MyVref{#1}{#2}}{\@@@@MyVref{#1}{#2}}}%
\@ifdefinable\@@MyVref{%
  \long\def\@@MyVref#1#2[#3]{%
     \@ifnextchar[{\@@@MyVref{#1}{#2[{#3}]}}{\@@@@MyVref{#1}{#2[{#3}]}}%
  }%
}%
\@ifdefinable\@@@MyVref{\long\def\@@@MyVref#1#2[#3]{\@@@@MyVref{#1}{#2[{#3}]}}}%
\newcommand\@@@@MyVref[3]{%
  \begingroup
  \MyVref@SwitchDefaults{#1}%
  \vpageref#2{#3}%
  \endgroup
}%

\makeatother

% \errorcontextlines=1000

\begin{document}

\MyVref{sec1} --- \MyVref{sec2} --- \MyVref{sec3}

\MyVref{sec1,sec2} --- \MyVref{sec1,sec2} --- \MyVref{sec1,sec3}

\MyVref{sec1,sec2,sec3}

\MyVref{sec1,sec2,sec3,sec4}

\MyVref{sec1,sec2,sec3,sec5}

\MyVref{sec1,sec2,sec3,sec4,sec5}

\clearpage
\section{Section 1}
\label{sec1}

\MyVref{sec1} --- \MyVref{sec2} --- \MyVref{sec3}

\MyVref{sec1,sec2} --- \MyVref{sec1,sec2} --- \MyVref{sec1,sec3}

\MyVref{sec1,sec2,sec3}

\MyVref{sec1,sec2,sec3,sec4}

\MyVref{sec1,sec2,sec3,sec5}

\MyVref{sec1,sec2,sec3,sec4,sec5}

\clearpage
\section{Section 2}
\label{sec2}

\MyVref{sec1} --- \MyVref{sec2} --- \MyVref{sec3}

\MyVref{sec1,sec2} --- \MyVref{sec1,sec2} --- \MyVref{sec1,sec3}

\MyVref{sec1,sec2,sec3}

\MyVref{sec1,sec2,sec3,sec4}

\MyVref{sec1,sec2,sec3,sec5}

\MyVref{sec1,sec2,sec3,sec4,sec5}

\clearpage
\section{Section 3}
\label{sec3}

\MyVref{sec1} --- \MyVref{sec2} --- \MyVref{sec3}

\MyVref{sec1,sec2} --- \MyVref{sec1,sec2} --- \MyVref{sec1,sec3}

\MyVref{sec1,sec2,sec3}

\MyVref{sec1,sec2,sec3,sec4}

\MyVref{sec1,sec2,sec3,sec5}

\MyVref{sec1,sec2,sec3,sec4,sec5}

\clearpage
\section{Section 4}
\label{sec4}

\MyVref{sec1} --- \MyVref{sec2} --- \MyVref{sec3}

\MyVref{sec1,sec2} --- \MyVref{sec1,sec2} --- \MyVref{sec1,sec3}

\MyVref{sec1,sec2,sec3}

\MyVref{sec1,sec2,sec3,sec4}

\MyVref{sec1,sec2,sec3,sec5}

\MyVref{sec1,sec2,sec3,sec4,sec5}

\clearpage
\section{Section 5}
\label{sec5}

\MyVref{sec1} --- \MyVref{sec2} --- \MyVref{sec3}

\MyVref{sec1,sec2} --- \MyVref{sec1,sec2} --- \MyVref{sec1,sec3}

\MyVref{sec1,sec2,sec3}

\MyVref{sec1,sec2,sec3,sec4}

\MyVref{sec1,sec2,sec3,sec5}

\MyVref{sec1,sec2,sec3,sec4,sec5}

\end{document}

About package-versions:

There has been a lot of updating on CTAN in the last months.

The .log-file on my system says:

This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2019/dev/Debian) (preloaded format=pdflatex 2020.2.13)  
LaTeX2e <2018-12-01>
Document Class: article 2018/09/03 v1.4i Standard LaTeX document class
Package: MnSymbol 2007/01/21 v1.4 support for the MnSymbol font
Package: amsmath 2018/12/01 v2.17b AMS math features
Package: amstext 2000/06/29 v2.01 AMS text
Package: amsbsy 1999/11/29 v1.2d Bold Symbols
Package: amsopn 2016/03/08 v2.02 operator names
Package: textcomp 2018/08/11 v2.0j Standard LaTeX package
Package: eufrak 2009/06/22 v3.00 Euler Fraktur fonts
Package: refcount 2016/05/16 v3.5 Data extraction from label references (HO)
Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO)
Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO)
Package: varioref 2016/02/16 v1.5c package for extended references (FMi)
Package: hyperref 2018/11/30 v6.88e Hypertext links for LaTeX
Package: hobsub-hyperref 2016/05/16 v1.14 Bundle oberdiek, subset hyperref (HO)
Package: hobsub-generic 2016/05/16 v1.14 Bundle oberdiek, subset generic (HO)
Package: hobsub 2016/05/16 v1.14 Construct package bundles (HO)
Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO)
Package: ifvtex 2016/05/16 v1.6 Detect VTeX and its facilities (HO)
Package: intcalc 2016/05/16 v1.2 Expandable calculations with integers (HO)
Package: ifpdf 2018/09/07 v3.3 Provides the ifpdf switch
Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO)
Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO)
Package: kvdefinekeys 2016/05/16 v1.4 Define keys (HO)
Package: pdftexcmds 2018/09/10 v0.29 Utility functions of pdfTeX for LuaTeX (HO)
Package: pdfescape 2016/05/16 v1.14 Implements pdfTeX's escape features (HO)
Package: bigintcalc 2016/05/16 v1.4 Expandable calculations on big integers (HO)
Package: bitset 2016/05/16 v1.2 Handle bit-vector datatype (HO)
Package: uniquecounter 2016/05/16 v1.3 Provide unlimited unique counter (HO)
Package: letltxmacro 2016/05/16 v1.5 Let assignment for LaTeX macros (HO)
Package: hopatch 2016/05/16 v1.3 Wrapper for package hooks (HO)
Package: xcolor-patch 2016/05/16 xcolor patch
Package: atveryend 2016/05/16 v1.9 Hooks at the very end of document (HO)
Package: atbegshi 2016/06/09 v1.18 At begin shipout hook (HO)
Package: hycolor 2016/05/16 v1.8 Color options for hyperref/bookmark (HO)
Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
Package: auxhook 2016/05/16 v1.4 Hooks for auxiliary files (HO)
Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO)
Package: url 2013/09/16  ver 3.4  Verb mode for urls, etc.
Package: cleveref 2018/03/27 v0.21.4 Intelligent cross-referencing
Package: nameref 2016/05/21 v2.44 Cross-referencing by name of section
Package: gettitlestring 2016/05/16 v1.5 Cleanup title references (HO)

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here


By the way:

The definition of the varioref-macro \@@vpageref is with slight modifications copied to the macro \cref@old@@vpageref and let equal to \@@@setvpageref by the package cleveref. The slightly modified definition-text of the modified \cref@old@@vpageref/\@@@setvpageref variant contains this:

\vref@label{\the\c@vrcnt @xvr}%  <<<
\vref@label{\the\c@vrcnt @vr}%

This yields something of the pattern:

\@bsphack
⟨Things done by the 1st \vref@label that do not yield visible material⟩
\@ephack
\@bsphack
⟨Things done by the 2nd \vref@label that do not yield visible material⟩
\@ephack

Other modifications to varioref done by cleveref yield the same.

Consecutive \@bsphack..\@esphack may disturb horizontal spacing and therefore are not good practice.
Perhaps better would be:

\@bsphack
\begingroup
\def\@bsphack{}%
\def\@esphack{}%
\vref@label{\the\c@vrcnt @xvr}%  <<<
\vref@label{\the\c@vrcnt @vr}%
\endgroup
\@esphack

Is this worth a bug-report?

1
  • This seems to work fine, thanks a lot! – Alexander Mar 9 '20 at 12:16

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.