10

I want to make the hyperref package skip some \ref commands in my TeX file and not make them hyperlinks in the resulting pdf document.

Is there a simple way to achieve this?


Here is an example where I would like hyperref bypassed:

\documentclass[12pt,twoside]{article}

\usepackage{ifthen}
\usepackage{hyperref}

\makeatletter
\newcommand{\writeval}[2]{%
\@bsphack%
\protected@write\@auxout{}%
{\string\newlabel{#1}{{#2}{\thepage}}}%
\protected@write\@auxout{}%
\@esphack%
}
\makeatother

\newcounter{counter}


\begin{document}

\writeval{mylabel}{6}
mylabel = \protect\ref{mylabel}\\

\begin{tabular}{c}%
  \setcounter{counter}{1}%
  \whiledo{\thecounter<\ref{mylabel}}{%
    {\thecounter}\\ % 
    \stepcounter{counter}%
  }%
\end{tabular}%

\end{document}
4
  • 1
    hyperref provides the NoHyper environment for this. Nov 26, 2013 at 18:28
  • @StephanLehmke, can you give a link to a reference. I can't find it in hyperref manual.
    – Kaveh
    Nov 26, 2013 at 19:05
  • 2
    Your \writelabel macro appears to be patterned closely after the standard-LaTeX \label command. Do note that hyperref redefines both \label and \ref quite significantly. Thus, the version of \ref that's available once hyperref is loaded is rather unlikely to be able to retrieve what you wrote to the .aux file via a \writelabel command (since hyperref's \ref and \ref* macros expect a rather different label structure). You should probably define your own \readlabel command, likely patterned after the \ref macro defined in the file latex.ltx (the "LaTeX kernel").
    – Mico
    Nov 26, 2013 at 20:32
  • 1
    @Kaveh Unfortunately hyperref is famous for fragmentary documentation; it's much better to look into the source code :-) In the source doc, you'll find that environment in section "23 Localized nullifying of package". But as Mico already mentioned, you'll never be able to use \ref as long as you bake your own \writelabel incompatible with hyperrefs interpretation of labels. Nov 27, 2013 at 4:59

3 Answers 3

10

Yes: Use \ref* instead of \ref to create a cross-reference that's not also a hyperlink.

A simple example:

enter image description here

\documentclass{article}
\usepackage[colorlinks=true]{hyperref}
\begin{document}
\section{First section}\label{sec:1}
abc    
\section{Next section}\label{sec:2}
def    
\section{Final section}\label{sec:3}    
A hyperlinked cross-reference to Section \ref{sec:1}, 
and an ordinary cross-reference to Section \ref*{sec:2}.
\end{document}
3
  • I did try \ref* but it doesn't work for me. (I am writing some labels into the AUX and then using \ref to read their values. Hyperref tries to make them hyperlinks and causes errors, \ref* doesn't return the correct values.)
    – Kaveh
    Nov 26, 2013 at 16:43
  • @Kaveh - Please provide a bit more information about the errors you're getting. Please also provide more information on how you are writing labels to the .aux file and reading them back in using \ref.
    – Mico
    Nov 26, 2013 at 18:01
  • I added a small example.
    – Kaveh
    Nov 26, 2013 at 19:00
4

The default \label-\ref system stores/retrieves two things associated with a label. The first is a counter, and the second is a page number. Technically, the label is created using (from latex.ltx):

\def\label#1{\@bsphack
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
  \@esphack}

You'll see only \@currentlabel and \thepage being written to the .aux using \protected@write. When hyperref is loaded, it stores more than just two things. In fact, it stores (from nameref.dtx):

\def\label#1{%
  \@bsphack
  \begingroup
    \def\label@name{#1}%
    \label@hook
    \protected@write\@auxout{}{%
      \string\newlabel{#1}{%
        {\@currentlabel}%
        {\thepage}%
        {\@currentlabelname}%
        {\@currentHref}{}%
      }%
    }%
  \endgroup
  \@esphack
}%

To cope with this redefinition of \label (which now stores five entries), \ref is also updated to expect five things, not two as you had perhaps thought.

Below I've provided an updated version of your MWE that seem to do what you're after, using refcount's \getrefnumber as an intermediary expandable counter-calculation:

enter image description here

\documentclass{article}
\usepackage{xifthen,refcount,hyperref}% http://ctan.org/pkg/{xifthen,refcount,hyperref}

\makeatletter
\newcommand{\writeval}[2]{%
  \@bsphack%
  \setcounter{mycntr}{\numexpr\number#2-1}\refstepcounter{mycntr}%
  \label{#1}% Mark current label
  \@esphack%
}
\makeatother

\newcounter{mycntr}

\begin{document}

\writeval{mylabel}{6}
mylabel = \ref{mylabel}

\begin{tabular}{c}%
  \setcounter{mycntr}{1}%
  \whiledo{\value{mycntr}<\getrefnumber{mylabel}}{%
    {\themycntr}\\ % 
    \stepcounter{mycntr}%
  }%
\end{tabular}%

\end{document}

For ease-of-use, I've used a single counter and marked the reference using \refstepcounter. There are other ways of doing this (for example, copying the content from \label into your definition of \writeval, using only the important bits), but it was convenient in this case (assuming that you're only marking numbers).

4

This solution consists in providing a \hyperbypass macro that patches the hyperref driver locally (if you don't want to replace the relevant \refs with \ref*s) and a \hyperrestore macro to restore the previous settings:

\documentclass{article}
\usepackage{hyperref}

\makeatletter
%Store the hyperref driver setup
\let\HR@hyper@@anchor\hyper@@anchor
\let\HR@hyper@link\hyper@link%
\let\HR@hyper@linkurl\hyper@linkurl%
\let\HR@hyper@linkfile\hyper@linkfile%
\let\HR@hyper@anchorstart\hyper@anchorstart
\let\HR@hyper@anchorend\hyper@anchorend
\let\HR@hyper@linkstart\hyper@linkstart
\let\HR@hyper@linkend\hyper@linkend
%Bypass macro
\newcommand\hyperbypass{%
\let\hyper@@anchor\@gobble
\gdef\hyper@link##1##2##3{##3}%
\def\hyper@linkurl##1##2{##1}%
\def\hyper@linkfile##1##2##3{##1}%
\let\hyper@anchorstart\@gobble
\let\hyper@anchorend\@empty
\let\hyper@linkstart\@gobbletwo
\let\hyper@linkend\@empty
}
%Restore macro
\newcommand\hyperrestore{%
\let\hyper@@anchor\HR@hyper@@anchor
\let\hyper@link\HR@hyper@link%
\let\hyper@linkurl\HR@hyper@linkurl%
\let\hyper@linkfile\HR@hyper@linkfile%
\let\hyper@anchorstart\HR@hyper@anchorstart
\let\hyper@anchorend\HR@hyper@anchorend
\let\hyper@linkstart\HR@hyper@linkstart
\let\hyper@linkend\HR@hyper@linkend
}
\makeatother

\begin{document}
\section{Introduction}
\label{sec:intro}
This \verb+\ref+ will be linked regularly \ref{sec:intro}.\\
\hyperbypass
This one won't \ref{sec:intro}.\\
\hyperrestore
But, this one again \ref{sec:intro}.
\end{document}
4
  • 2
    Uh! And \ref*?
    – egreg
    Nov 26, 2013 at 9:57
  • Well. Yes... Let's say the document the OP is talking about contains to much \refs and replacing the relevant ones with \ref* is not an option or not desired.
    – Ruben
    Nov 26, 2013 at 10:06
  • 3
    This might indeed be a use case.
    – egreg
    Nov 26, 2013 at 10:07
  • Thanks Ruben, but it doesn't seem to work correctly for me. I am still getting errors related to hyperref in a part of the document that I am bypassing using these macros.
    – Kaveh
    Nov 26, 2013 at 17:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .