15

I have an article class document with a structure like this.

  • Part A
    • Section 1
    • Section 2
  • Part B
    • Section 1
    • Section 2

I want to reference Section 1 in part A from Section 2 in part B. When I reference a section in another part using \ref, \vref or \cref I get

As seen in Section 1.

Since that appears in Part B, the reader would assume I'm talking about section 1 in part B, but I mean section 1 in part A.

Desired output:

As seen in Section 1 in Part A.

Now comes the tricky part. Most of my references are for within the same section. If I'm in Part B and I'm referencing something in Part B, I just want to say

As seen in Section 1

Not

As seen in Section 1 in Part B

Is there some combination of varioref,hyperref, cleveref and whatever else which can do that with a single command? (Bonus points if it is hyperlinked and can include smart page numbers like \vref)

I suppose redefining section numbers to be of the form A.1 would work. Is there a way of doing it without that?

MWE

\documentclass[a4paper]{article}

\usepackage[english]{babel} %do I need this? Gummi throws an error if I leave it out. I dunno. \usepackage{varioref} \usepackage[hidelinks]{hyperref} \usepackage[nameinlink, capitalise, noabbrev]{cleveref}

\begin{document}

\part{First Part}\label{sec:first part}

\section{section in first part}\label{sec:in first part}

\part{Second Part}\label{sec:second part}

\section{section in second part}\label{sec:in second part}

\Cref{sec:in first part} is cool %desired output: Section 1 in Part A is cool.

\Cref{sec:in second part} is also cool. %desired output: Section 1 is also cool.

\end{document}

Edit: The penultimate line is supposed to say 'this part' not 'another part'. Disambiguated the reference sentences.

2 Answers2

6

Since there is no direct information about section of which part in the standard \LaTeX reference system the solution of such a 'context' aware referencing is involved with a lot of ugly hacks...

... if one uses the standard reference system ;-)

However, with Heiko Oberdiek's zref package and the help of cleveref this job can be done with less hacking.

The key is to write additional data as label - meta information such as counter name, part value, section value (called properties) etc with a \zref@labelbyprops to the .aux file and retrieving the relevant information with \zref@extract (which is expandable, fortunately!)

The cleveref package is not really needed here, but it's nice to exploit its \crefname features by using the macros \cref@<type>@name etc. macros once the counter type is known.

Please note that the new macro \zclabel is needed, instead of the traditional \label macro.

\documentclass{article}

\usepackage[counter,user,hyperref]{zref}

\makeatletter
\AtBeginDocument{%
\@ifpackageloaded{hyperref}{%
}{
  \providecommand{\phantomsection}{}
  \providecommand{\hyperlink}[2]{#2}
}

\zref@newlist{sectionprop}
\zref@newprop{partinfo}[-1]{\thepart}
\zref@newprop{sectioninfo}[-1]{\number\value{section}}

\newcommand{\zclabel}[1]{%
  \zref@labelbyprops{#1}{partinfo,sectioninfo,anchor,counter}%
}

% Wrapper macros that extract the reference counter type and the reference value -- this way, no additional \label is necessary

\newcommand{\countercref}[1]{%
  \expandafter\csname cref@\zref@extract{#1}{counter}@name\endcsname\ \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{sectioninfo}}%
}

\newcommand{\Countercref}[1]{%
  \expandafter\csname Cref@\zref@extract{#1}{counter}@name\endcsname\ \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{sectioninfo}}%
}


\newcommand{\secref}[1]{%
  % Check first whether the label is defined at all, otherwise \Countercref etc. would fail!
  \zref@ifrefundefined{#1}{}{% 
    % Preexpand some information
    \edef\@tmp@a{\zref@extract{#1}{partinfo}}%
    \edef\@tmp@b{\thepart}%
    \ifx\@tmp@b\@tmp@a\relax% Compare \thepart with the result of the zref - label - value for par
    \Countercref{#1} in this \partname%
    \else
    \Countercref{#1} in \partname\ \zref@extract{#1}{partinfo}%
    \fi
  }%
}

}
\makeatother


\usepackage{hyperref}
\usepackage{cleveref}

\renewcommand{\thepart}{\Alph{part}}

\begin{document}
\part{First Part}
\section{section in first part}\zclabel{sec:infirstpart}
\part{Second Part}
\section{section in second part}\zclabel{sec:insecondpart}
\secref{sec:infirstpart} is cool and \secref{sec:insecondpart} is cool too, but \secref{sec:inthirdpart} is even better!
\part{Third Part}
\section{section in third part}\zclabel{sec:inthirdpart}


\end{document}

enter image description here

1

If you are using Overleaf (maybe it works in other environment too) you can address to the official "Cross referencing sections, equations and floats > Referencing sections and chapters"

And use the following construction:

\section{section in first part}\label{sec:in_first_part}

Section \ref{sec:in_first_part} is cool

enter image description here

Nick Vee
  • 119