4

In order to prevent conflicts with labels when gathering exercices from a database, I need to redefine the commands \label, \ref and \pageref to add a local prefix to labels. Unfortunately, the package varioref does not work anymore.

Here is a MWE.

\documentclass{article}
\usepackage{varioref}

\newcommand*{\globallabel}[1]{global:#1}

\AtBeginDocument{%
  \let\origref\ref
  \renewcommand*{\ref}[1]{%
    \origref{\globallabel{#1}}%
  }
  \let\origpageref\pageref
  \renewcommand*{\pageref}[1]{%
    \origpageref{\globallabel{#1}}%
  }
  \let\origlabel\label%
  \renewcommand*{\label}[1]{%
    \origlabel{\globallabel{#1}}
  }
}
\makeatother

\begin{document}

Example 1: figure~\vref{fig:example1}.

Example 2: figure~\vpageref{fig:example2}.

\begin{figure}
  \caption{Example 1}
  \label{fig:example1}
\end{figure}

\clearpage

\begin{figure}
  \caption{Example 2}
  \label{fig:example2}
\end{figure}

\end{document}

I get

Example 1: figure 1 on page 1.
Example 2: figure on page 2.

instead of

Example 1: figure 1.
Example 2: figure on the next page.

In the log file, I found

LaTeX Warning: Reference `fig:example1' on page 1 undefined on input line 31.
LaTeX Warning: Reference `fig:example2' on page 1 undefined on input line 33.

I've tried to redefine the commands \vref and \pagreref in the same way ; without success.

4

enter image description here

It's a bit harder to redefine the names as you need to redefine both \vref and \ref to catch top level use but \vref uses \ref internally and things get double-prefixed. It would be possible to open up the sources just to add the prefixes in the right place but easier is to use new top level names to add the prefix, then things work as expected as the prefix is just added once and the internal use of \ref uses the already prefixed key without prefixing it again.

\documentclass{article}
\usepackage{varioref}

\newcommand*{\globallabel}[1]{global:#1}

  \newcommand*{\myref}[1]{%
    \ref{\globallabel{#1}}%
  }
  \newcommand*{\myvref}[1]{%
    \vref{\globallabel{#1}}%
  }
  \newcommand*{\myvpageref}[1]{%
    \vpageref{\globallabel{#1}}%
  }
  \newcommand*{\mypageref}[1]{%
    \pageref{\globallabel{#1}}%
  }
  \newcommand*{\mylabel}[1]{%
    \label{\globallabel{#1}}%
  }



\begin{document}

Example 1: figure~\myvref{fig:example1}.

Example 2: figure~\myvpageref{fig:example2}.

\begin{figure}
  \caption{Example 1}
  \mylabel{fig:example1}
\end{figure}

\clearpage

\begin{figure}
  \caption{Example 2}
  \mylabel{fig:example2}
\end{figure}

\end{document}
10

Also some internals of package varioref need to be redefined, e.g.:

\documentclass{article}
\usepackage{varioref}

\newcommand*{\globallabel}[1]{global:#1}

\makeatletter
\AtBeginDocument{%  
  \let\origref\ref
  \renewcommand*{\ref}[1]{%
    \origref{\globallabel{#1}}%
  }%
  \let\origpageref\pageref
  \renewcommand*{\pageref}[1]{%
    \origpageref{\globallabel{#1}}%
  }%
  \let\origlabel\label%
  \renewcommand*{\label}[1]{%
    \origlabel{\globallabel{#1}}%
  }%
  \let\orig@@vpageref\@@vpageref
  \def\@@vpageref#1[#2]#3{%
    \begingroup
      \let\pageref\origpageref
      \orig@@vpageref{#1}[{#2}]{\globallabel{#3}}%
    \endgroup
  }%
  \let\origvr@f\vr@f
  \renewcommand*{\vr@f}[1]{%
    \begingroup
      \let\ref\origref
      \let\@@vpageref\orig@@vpageref
      \origvr@f{\globallabel{#1}}%
    \endgroup
  }%
}
\makeatother  

\begin{document}

Example 1: figure~\vref{fig:example1}.

Example 2: figure~\vpageref{fig:example2}.

\begin{figure}
  \caption{Example 1}
  \label{fig:example1}
\end{figure}
\clearpage

\begin{figure}
  \caption{Example 2}
  \label{fig:example2}
\end{figure}   

\end{document}

Result:

Example 1: figure 1.
Example 2: figure on the next page.

Remarks:

  • Using the internals rather than \vref or \vpageref makes it easier to support the various syntax forms (star, optional arguments) of \vref and \vpageref.
  • In the redefinition of \vref/\vpageref, some original referencing commands are enabled to avoid double prefixes.

Patch for hyperref

  • A nested \globallabel is avoided in \vref by disabling it locally.

Example:

\documentclass{article}
\usepackage{nameref}
\usepackage{varioref}
\usepackage{hyperref}
\usepackage{letltxmacro}

\newcommand*{\globallabel}[1]{global:#1}

\makeatletter
\AtBeginDocument{%
  \LetLtxMacro\origref\ref
  \renewcommand*{\ref}[1]{%
    \origref{\globallabel{#1}}%
  }%
  \LetLtxMacro\origpageref\pageref
  \renewcommand*{\pageref}[1]{%
    \origpageref{\globallabel{#1}}%
  }%
  \LetLtxMacro\origlabel\label%
  \renewcommand*{\label}[1]{%
    \origlabel{\globallabel{#1}}%
  }%
  \let\orig@@vpageref\@@vpageref
  \def\@@vpageref#1[#2]#3{%
    \begingroup
      \let\pageref\origpageref
      \orig@@vpageref{#1}[{#2}]{\globallabel{#3}}%
    \endgroup
  }%
  \let\origvr@f\vr@f
  \renewcommand*{\vr@f}[1]{%
    \begingroup
      \let\ref\origref
      \let\@@vpageref\orig@@vpageref
      \expandafter\let\expandafter\globallabel\expandafter\@firstofone
      \expandafter\origvr@f\expandafter{\globallabel{#1}}%
    \endgroup
  }%
}
\makeatother

\begin{document}

Example 1: figure~\vref{fig:example1}.

Example 2: figure~\vpageref{fig:example2}.
\documentclass{article}
\usepackage{varioref}

\newcommand*{\globallabel}[1]{global:#1}

\makeatletter
\AtBeginDocument{%  
  \let\origref\ref
  \renewcommand*{\ref}[1]{%
    \origref{\globallabel{#1}}%
  }%
  \let\origpageref\pageref
  \renewcommand*{\pageref}[1]{%
    \origpageref{\globallabel{#1}}%
  }%
  \let\origlabel\label%
  \renewcommand*{\label}[1]{%
    \origlabel{\globallabel{#1}}%
  }%
  \let\orig@@vpageref\@@vpageref
  \def\@@vpageref#1[#2]#3{%
    \begingroup
      \let\pageref\origpageref
      \orig@@vpageref{#1}[{#2}]{\globallabel{#3}}%
    \endgroup
  }%
  \let\origvr@f\vr@f
  \renewcommand*{\vr@f}[1]{%
    \begingroup
      \let\ref\origref
      \let\@@vpageref\orig@@vpageref
      \origvr@f{\globallabel{#1}}%
    \endgroup
  }%
}
\makeatother  

\begin{document}

Example 1: figure~\vref{fig:example1}.

Example 2: figure~\vpageref{fig:example2}.

\begin{figure}
  \caption{Example 1}
  \label{fig:example1}
\end{figure}
\clearpage

\begin{figure}
  \caption{Example 2}
  \label{fig:example2}
\end{figure}   

\end{document}
  • +1 I thought it a bit late at night for changing vref internals:-) – David Carlisle Jun 14 '13 at 23:47
  • Thanks, but :-) the MWE does not compile with hyperref package. I replaced \let by \LetLtxMacro as you said here. But at compile time, I get: TeX Warning: Reference 'global:global:fig:example1' on page 1 undefined on in put line 44. – Éric Guirbal Jun 15 '13 at 19:00
  • There is problem too with babel for french language. Replacing the active character ':' in labels with '-', or \usepackage[babel,kerning=true]{microtype} solve the problem. – Éric Guirbal Jun 15 '13 at 19:09
  • @EricGuirbal: I can't reproduce the problem, if I add \usepackage[french]{babel} to both examples. – Heiko Oberdiek Jun 15 '13 at 19:21
  • @Heiko Oberdiek: I get Missing \endcsname inserted. <to be read again> :. According to egreg: "The problem is that varioref and cref don't like babel shorthands in the labels." Putting \shorthandoff{:} in \AtBeginDocument is another solution. – Éric Guirbal Jun 15 '13 at 20:35

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.