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?

  • you could compare the current page with the the ref's one in \pageref – ebcontrol Sep 26 '19 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 '19 at 11:47
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.
|improve this answer|||||
  • 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 '19 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}
|improve this answer|||||
  • 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 '19 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.