TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm writing a long mathematics book. Sometimes after I move things around, an internal reference (\ref{...}) will refer to an item that occurs later in the text. For example, a proof may (unintentionally) require something proved later in the book. Is it possible to have LaTeX automatically warn of this?

share|improve this question
    
Welcome! Later at all or on a later page or in a later section or...? A minimal example which can be compiled to reproduce the situation would improve your chances of being well understood and getting useful help. – cfr Jan 16 at 1:06
up vote 7 down vote accepted

You could load the varioref package and use that package's \vref instruction instead of the more basic \ref command.

By default, \vref adds page-related information to cross-reference call-outs whenever they refer to items that occur on pages before or after the call-outs themselves. By adding the instructions

\renewcommand\reftextfacebefore{}
\renewcommand\reftextbefore{}

in the preamble, the output of \vref will differ from that of \ref only if the item being cross-referenced occurs after the call-out.

Strictly speaking, this method doesn't generate a warning if the call-out occurs before the item itself. However, in combination with a package such as hyperref, the extra information generated by \vref ("Theorem 5 on page 65") should create an easy-to-detect visual flag. Once you're satisfied that your document doesn't contain any undesired forward-pointing cross-references, you could change all \vref statements back to \ref.

A full MWE is given below. Observe that the \vref statements on the first page generate additional output relative to what \ref produces, whereas the \vref statement on the third page does not.

\documentclass{article}

\usepackage{varioref}
\renewcommand\reftextfacebefore{}
\renewcommand\reftextbefore{}

\usepackage[colorlinks]{hyperref} % cross-references marked in red

\begin{document}
A cross-reference to equation \vref{eq:pyth}.

A cross-reference to equation \vref{eq:euler}.
\clearpage
\begin{equation}\label{eq:pyth} a^2+b^2=c^2 \end{equation}
\clearpage
\begin{equation}\label{eq:euler} e^{i\pi}-1=0 \end{equation}
A cross-reference to equation \vref{eq:pyth}.
\end{document}
share|improve this answer
    
Thank you! Very nice solution. – zeno Jan 16 at 6:22

I do not claim that doing this is wise....

Caveat emptor...


You could use something like this:

\usepackage{expl3,etoolbox}
\ExplSyntaxOn
\seq_new:N \l_zeno_refs_seq
\msg_new:nnn { zeno } { Patch Failure } { Could~not~patch~#1~\msg_line_context:! }
\msg_new:nnn { zeno } { Patch OK } { Successfully~patched~#1~\msg_line_context:. }
\msg_new:nnn { zeno } { Prior Ref } { Cross-reference~before~label:~#1~\msg_line_context:. }
\apptocmd{ \label }
{
  \seq_put_left:Nn \l_zeno_refs_seq { #1 }
}
{
  \msg_info:nnn { zeno } { Patch OK } { \label }
}
{
  \msg_error:nnn { zeno } { Patch Failure } { \label }
}
\apptocmd{ \ref }
{
  \seq_if_in:NnTF \l_zeno_refs_seq { #1 } {} { \msg_warning:nnn { zeno } { Prior Ref } { #1 } }
}
{
  \msg_info:nnn { zeno } { Patch OK } { \ref }
}
{
  \msg_error:nnn { zeno } { Patch Failure } { \ref }
}
\ExplSyntaxOff

Basically, this keeps track of labels and checks if the reference is referring to an already issued label or not. If not, it says something like this:

*************************************************
* zeno warning: "PriorRef"
* 
* Cross-reference before label: fifth on line 77.
*************************************************

Complete code:

\documentclass{article}
\usepackage{expl3,etoolbox}
\ExplSyntaxOn
\seq_new:N \l_zeno_refs_seq
\msg_new:nnn { zeno } { Patch Failure } { Could~not~patch~#1~\msg_line_context:! }
\msg_new:nnn { zeno } { Patch OK } { Successfully~patched~#1~\msg_line_context:. }
\msg_new:nnn { zeno } { Prior Ref } { Cross-reference~before~label:~#1~\msg_line_context:. }
\apptocmd{ \label }
{
  \seq_put_left:Nn \l_zeno_refs_seq { #1 }
}
{
  \msg_info:nnn { zeno } { Patch OK } { \label }
}
{
  \msg_error:nnn { zeno } { Patch Failure } { \label }
}
\apptocmd{ \ref }
{
  \seq_if_in:NnTF \l_zeno_refs_seq { #1 } {} { \msg_warning:nnn { zeno } { Prior Ref } { #1 } }
}
{
  \msg_info:nnn { zeno } { Patch OK } { \ref }
}
{
  \msg_error:nnn { zeno } { Patch Failure } { \ref }
}
\ExplSyntaxOff
\begin{document}
\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\label{first}\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\label{second}\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\label{third}\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\label{fourth}\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\label{fifth}\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\ref{first}\ref{second}\ref{third}\ref{fourth}\ref{fifth}\newpage
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.