4

I have a huge LaTeX document with my lecture notes for a maths course; every now and then I change the order of the sections.

I want to make sure that all cross-references to, for instance, theorems are in "chronological order": referring in section 7 to stuff from section 5 is fine, but I don't want to use in a proof of section 5 references to results that won't be proved until section 7.

Is there a package that checks whether cross-references are to labels defined earlier or later in the document than that particular reference?

2
  • you could compare the current page with the the ref's one in \pageref
    – ebcontrol
    Sep 26, 2019 at 9:56
  • I thought about that, but it would involve changing numerous \refs and \eqrefs to \pagerefs and then, if all looks well, changing back again.
    – Mark
    Sep 26, 2019 at 11:47

2 Answers 2

3

A proof of concept (it would require extensive work if hyperref is involved):

\documentclass{article}

\makeatletter
\let\latex@label\label
\let\latex@ref\ref
\def\label#1{\global\@namedef{LABEL@#1@USED}{}\latex@label{#1}}
\def\ref#1{%
  \ifcsname LABEL@#1@USED\endcsname\else
    \@latex@warning{Forward Reference '#1'}%
  \fi
  \latex@ref{#1}%
}
\makeatother

\begin{document}

\section{A}\label{a}

This refers to \ref{a} and to \ref{b}.

\section{B}\label{b}

OK.

\end{document}

The log file would contain

LaTeX Warning: Forward Reference 'b' on input line 19.
1
  • I could temporarily comment out (%) hyperref! What is the problem with combining it with hypperref? That the latter redefines the labelling/referencing commands?
    – Mark
    Sep 29, 2019 at 13:30
2

Here a solution that seems to work, though not within subequations. It uses zref for absolute page numbers, see How to find absolute page number as an integer? and Refer to the current page number, but not \thepage, but the real absolute You will find warnings in the log file for all not wanted cross-references.

\documentclass{article}

\usepackage{amsmath}
\usepackage[user,abspage]{zref}
\usepackage{xassoccnt}

\makeatletter
\let\oldref\ref
\let\oldeqref\eqref
\let\oldlabel\label
\newcommand\mylabel[1]{%
  \oldlabel{#1}%
  \zlabel{#1}%
}
\renewcommand\label[1]{%
  \mylabel{#1}%
}

\renewcommand{\ref}[1]{%
  \zref{#1}%
  \ifnum\zref@extract{#1}{abspage}<\value{realpage}
    \GenericWarning{}{Warning: Backwards refence '#1' on page \thepage}%
  \fi%
}
\renewcommand{\eqref}[1]{%
  (\zref{#1})%
  \ifnum\zref@extract{#1}{abspage}<\value{realpage}
    \GenericWarning{}{Warning: Backwards refence '#1' on page \thepage}%
  \fi%
}

\def\label@in@display#1{%
      \ifx\df@label\@empty\else
      \@amsmath@err{Multiple \string\label's:
          label '\df@label' will be lost}\@eha
      \fi
      \mylabel{#1}
      \typeout{XXX #1 XXX}
}
\makeatother

\newcounter{realpage}
\DeclareAssociatedCounters{page}{realpage}
\AtBeginDocument{%
  \stepcounter{realpage}
}

\begin{document}
\pagenumbering{roman}
\section{Sec~1}
\begin{align}\label{eqR1}
    x &= 1
\end{align}

Text~R1\label{textR1}

\clearpage
\pagenumbering{arabic}
\section{Sec~2}

\begin{align}\label{eq1}
     x &= 1
\end{align}

\begin{subequations}
  \begin{align}
      x &= 1\label{eqS1} \\
    y &= 1\label{eqS2}
      \\
    z&=1
    \\
    z&=10
  \end{align}
\end{subequations}

Text~1\label{text1}

\newpage

\begin{itemize}
  \item Equation~R1: \eqref{eqR1}
  \item Equation~1: \eqref{eq1}
  \item Equation~S1: \eqref{eqS1}
  \item Equation~2: \eqref{eq2}  
  \item Text~R1: \ref{textR1}  
  \item Text~1: \ref{text1}
  \item Text~2: \ref{text2}
\end{itemize}

\newpage 

\section{Sec~3}

\begin{align}\label{eq2}
    x &= 2
\end{align}

Text~2\label{text2}
\newpage

\end{document}
1
  • 2
    The cross reference could be at the top of a page and the referenced object at the bottom of the same page.
    – egreg
    Sep 27, 2019 at 12:01

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.