15

I'm aware of the cleveref package \cref which adds the correct reference name (see: Automatically inserting "Section", "Subsection", etc). I have a few references which refer to the very next section and some find it odd to give the number in this case rather than just say "in the next section". Sometimes I've moved sections around and these references suddenly become quite broken. To have the best of both worlds, is there a way to automate this change?

E.g.: replace "this is discussed further in section 1.4" with "this is discussed further in the next section"

4
  • So you would basically like a command that outputs in the next section when the referenced section is immediately following the current section, and other wise output section 3.4?
    – Karalga
    Jun 9, 2015 at 19:40
  • @Karalga exactly (or whatever number the reference would normally be :P).
    – jozxyqk
    Jun 9, 2015 at 20:42
  • @jozxyqk: There is some related content on this site. Did you find a solution?
    – krlmlr
    Aug 18, 2015 at 18:45

3 Answers 3

10
+200

Here is a solution based on cleveref package. If the hyperref package is loaded, the word "section" (or chapter/subsection/...) is a clickable hyperlink.

\documentclass{article}

%\usepackage{hyperref}
\usepackage{cleveref}
\crefname{subsection}{subsection}{subsections}

\providecommand\hyperref[2][]{#2}

\makeatletter
\newcommand{\mt@ref}[1]{%
\cref@gettype{#1}{\@temptype}%
\cref@getcounter{#1}{\@tempctr}%
\def\mtt{\the\csname c@\@temptype\endcsname}%
\ifnum\mtt=\numexpr\@tempctr-1\relax \mtcase the next \hyperref[#1]{\@temptype}\else%
\ifnum\mtt=\numexpr\@tempctr+1\relax \mtcase the previous \hyperref[#1]{\@temptype}\else%
\cref{#1}\fi\fi}

\newcommand{\mtref}{\let\mtcase\relax\mt@ref}
\newcommand{\Mtref}{\let\mtcase\MakeUppercase\mt@ref}
\makeatother


\begin{document}
\section{Foo}\label{sec:foo}
this is \Mtref{sec:bar} and this is \mtref{sec:baz}
\subsection{Sub foo}\label{ss:sfoo}
this is \mtref{sec:baz} and this is \mtref{sec:bar}
and \mtref{ss:sfbla} and \mtref{ss:sfbaz}
\subsection{Bla foo}\label{ss:sfbla}
bla bla bla
\subsection{Bar foo}\label{ss:sfbar}
bla bla bla
\subsection{Baz foo}\label{ss:sfbaz}
bla bla bla
\section{Bar}\label{sec:bar}
bla bla bla
\section{Baz}\label{sec:baz}
bla bla bla

\end{document}

The result looks approximately like this (compiled with a previous version of the code):

Result of compilation

7
  • I didn't mention it explicitly in my question, but hyperref and cleveref are two packages I'm using too. I like your solution, and I'll try it soon.
    – krlmlr
    Aug 22, 2015 at 19:06
  • This works like a charm, also the hyperref links -- thanks a lot! I changed two things in my local copy: 1. I write "the next" instead of "next", because "in the next subsection" should be substituted with "in subsection x.y". 2. I extended the code to include the case "previous section". I can edit your answer if you like.
    – krlmlr
    Aug 22, 2015 at 19:17
  • @krlmlr please feel free.
    – touhami
    Aug 22, 2015 at 19:27
  • A command \Mtref (in the same spirit as \Cref) seems to be necessary, too. I copy-pasted the definition, but perhaps there's a nicer solution?
    – krlmlr
    Aug 24, 2015 at 14:40
  • @ what do you want to uppercase The next section? or the next Section?
    – touhami
    Aug 24, 2015 at 15:03
9

Revised Attempt

In addition to \Unitref{<label>} which provides the unit name along with the ref, as in "section 2" or "subsection 1.1", etc. (see original attempt), I now also introduce \Ref{<unit>}{<label>}, where <unit> is what is to be compared, "section", "subsection", or "subsubsection". If \ref{<label>} is, in fact, the next increment of the unit, it will output "the next ". If \ref{<label>} is not the next increment of the unit, it will output " \ref{<label>}".

\documentclass{article}
\usepackage{ifthen}
\let\svsection\section
\let\svsubsection\subsection
\let\svsubsubsection\subsubsection

\def\section{\xdef\Unit{section}\svsection}
\def\subsection{\xdef\Unit{subsection}\svsubsection}
\def\subsubsection{\xdef\Unit{subsubsection}\svsubsubsection}

\let\svlabel\label
\def\label#1{\expandafter\xdef\csname Unit-#1\endcsname{\Unit}\svlabel{#1}}

\def\Unitref#1{\csname Unit-#1\endcsname~\ref{#1}}

\def\thenextsection{\the\numexpr\thesection+1\relax}
\def\thenextsubsection{\thesection.\the\numexpr\arabic{subsection}+1\relax}
\def\thenextsubsubsection{\thesection.\arabic{subsection}%
  .\the\numexpr\arabic{subsubsection}+1\relax}

\def\Ref#1#2{%
  \ifthenelse{\equal{\ref{#2}}{\csname thenext#1\endcsname}}%
  {the next #1}{#1~\ref{#2}}
}
\begin{document}

\section{The First Section\label{s:first}}

``The First Subsection'' is \Ref{subsection}{ss:first},
whereas ``The Second Subsection'' is \Ref{subsection}{ss:second}.

\subsection{The First Subsection\label{ss:first}}

In the prior unit, \Unitref{s:first}, not to be confused with the 
current unit, \Unitref{ss:first}, we have successfully captured the data

``A Subsubsection'' is \Ref{subsubsection}{sss:first},
whereas ``Second Subsubsection'' is \Ref{subsubsection}{sss:second}.

\subsubsection{A subsubsection\label{sss:first}}

``The First Section'' is \Ref{section}{s:first},
whereas ``The Second Section'' is \Ref{section}{s:second}.

\section{The Second Section\label{s:second}}

\subsection{The Section Subsection\label{ss:second}}

The prior unit, \Unitref{s:second} is not to be confused with the 
way back references to either \Unitref{s:first}, \Unitref{ss:first},
or \Unitref{sss:first}. But the current unit is \Unitref{ss:second}.
We have successfully captured the data.

\subsubsection{Second subsubsection\label{sss:second}}

\end{document}

enter image description here

Areas that need improvement include optional capitalization of the "unit" name, if appearing at the beginning of a sentence, for example. Also, \Ref can only compare "apples and apples". That is, if the label is that of a subsection, \Ref can only be used to see if it is the next subsection, which is why argument #1 of \Ref has to currently be specified explicitly.

Original (misguided) attempt

Here I just played around a little in the preamble and created \Unitref{} to get "section 2" or "subsection 1.1", etc.

What I do is save the name "section", "subsection", etc. in a macro \Unit whenever I enter such a unit. Then, when invoking \label, I use the current value of \Unit as the value of a new macro \csname Unit-<label>\endcsname.

Finally, when invoking \Unitref{<label>}, it calls upon \csname Unit-<label>\endcsname and follows up with a hard space and a call to \ref{<label>}

\documentclass{article}
\let\svsection\section
\let\svsubsection\subsection
\let\svsubsubsection\subsubsection

\def\section{\xdef\Unit{section}\svsection}
\def\subsection{\xdef\Unit{subsection}\svsubsection}
\def\subsubsection{\xdef\Unit{subsubsection}\svsubsubsection}

\let\svlabel\label
\def\label#1{\expandafter\xdef\csname Unit-#1\endcsname{\Unit}\svlabel{#1}}

\def\Unitref#1{\csname Unit-#1\endcsname~\ref{#1}}
\begin{document}

\section{The First Section\label{s:first}}

\subsection{First Subsection\label{ss:first}}

In the prior unit, \Unitref{s:first}, not to be confused with the 
current unit, \Unitref{ss:first}, we have successfully captured the data

\subsubsection{A subsubsection\label{sss:first}}

Blah-Blah

\section{The Next Section\label{s:second}}

\subsection{Next Subsection\label{ss:second}}

The prior unit, \Unitref{s:second} is not to be confused with the 
way back references to either \Unitref{s:first}, \Unitref{ss:first},
or \Unitref{sss:first}. But the current unit is \Unitref{ss:second}.
We have successfully captured the data.

\end{document}

enter image description here

6
  • This doesn't seem to answer the question, in my opinion...
    – Werner
    Aug 18, 2015 at 19:58
  • @Werner What was I thinking? I'll delete in a bit. Aug 18, 2015 at 20:00
  • @StevenB.Segletes: No, please don't! I think this can be a key step to solving the issue -- the only remaining bit is to detect that 2.2.3 is the section after 2.2.2 and before 2.2.4, but not related to 2.3.x or 1.2.y. (Or am I mistaken? Can you use \Unitref to produce the number of the current section?)
    – krlmlr
    Aug 18, 2015 at 21:05
  • @krlmlr Please see my revision. It is much closer to what you seek. Aug 18, 2015 at 22:25
  • If for some reason you want to change the section numbering to something else than a arabic number, e.g. \renewcommand*\thesection{\Roman{section}}, the code can't process the comparisons properly anymore. The OP does not give a clue about that and thinking of future readers you could (possibly) robustify this alredy good solution by comparing \c@...'s rather than \the...'s.
    – Ruben
    Aug 20, 2015 at 21:39
2

(Too long for a comment, hence posted as an answer.)

The basic LaTeX \label mechanism, which the cleveref package uses to generate its output, stores only two characteristics associated with an "item" (such as a section, equation, theorem, etc): the item's number -- more precisely, the value of whatever counter value was most recently incremented via a \refstepcounter instruction -- and the number of the page on which the item's number is output.

Unfortunately, because \label doesn't capture other item characteristics -- such as the chapter, section, or subsection number -- you can't use \cref to create a call-out of the type "in the next section" (instead of "in section 1.4") if the cross-referencing call-out happens to occur in section 1.3.

You may want to look into the zref package to build an enhanced cross-referencing functionality of the type you describe.

1
  • But the full section number is stored at least in the .aux file. Is there no way to access it from there? I don't really see why the desired functionality is impossible, or how zref can help here.
    – krlmlr
    Aug 18, 2015 at 16:07

You must log in to answer this question.

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