6

Within a chapter/section scheme, Sometimes I want to be able to have a reference to a section, which would normally appear in the form c.s, where c is the chapter number and s is the section number, to appear just in the form s.

How?

Sample source:

\documentclass[12pt]{memoir}
\usepackage{hyperref}
\usepackage{cleveref}  
\crefname{chapter}{Chapter}{Chapters}  

\begin{document}

In section \ref{sec:more} of \cref{chap:one} \dots .

And in \cref{sec:one} \dots .

\chapter{One}\label{chap:one}

\section{About one}\label{sec:one}

\section{More about one}\label{sec:more}

\chapter{Two}

In section \ref{sec:more}

\end{document}

Output: Initial page of outoput Additional page of output

Conflict with creating two tables of contents

The answer that uses zref works as shown in the answer, but when I add code, shown below, to the preamble in order to produce both a long and a short table of contents — with commands \shorttableofcontents and \longtableofcontents just after \begin{document}, I get an error on the line where I use \shorttableofcontents.

The error is:

Undefined control sequence

Here's the entire source, including the extra code for using zref along with the code (courtesy of Christian Hupfer) for creating the two tables of contents.

\documentclass[12pt]{memoir}
\usepackage[colorlinks]{hyperref}
\usepackage{cleveref}  
\usepackage{xparse}

\usepackage{xassoccnt}
\usepackage[user,hyperref]{zref}
\RegisterPostLabelHook{\zlabel}
\makeatletter
\zref@newprop{section}{\arabic{section}}% Change \arabic{section} by \Roman{section} etc. if needed
\zref@addprop{main}{section}
%
\newcommand{\secref}[1]{%
  \zref@ifrefundefined{#1}{%
    \ref{#1}% fall back to usual \ref if there's no such zref - specific label. 
  }{%
    \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{section}}%
  }%
}
\makeatother

\crefname{chapter}{Chapter}{Chapters}  
\crefname{section}{Section}{Sections}

%% SHORT & LONG TOCs
%% Code by Christian Hupfer 
\makeatletter
% Just in case we're not loading hyperref
\@ifpackageloaded{hyperref}{%
}{
  \providecommand{\@currentHref}{}
  \providecommand{\hyperlink}[2]{#2}
  \providecommand{\getrefnumber}[1]{}
  \providecommand{\phantomsection}{}
}

\AtBeginDocument{%
\newcommand{\shortcontentsstuff}{%
  \contentsline{chapter}{\hyperlink{\getrefnumber{toc::shorttoc::anchor}}{\shortcontentsname}}{\pageref{toc::shorttoc}}{\getrefnumber{toc::shorttoc::anchor}}
}
\newcommand{\longcontentsstuff}{%
  \contentsline{chapter}{\hyperlink{\getrefnumber{toc::longtoc::anchor}}{\longcontentsname}}{\pageref{toc::longtoc}}{\getrefnumber{toc::longtoc::anchor}}
}
}
\newif\if@shorttoc
%
\renewcommand{\tableofcontents}{%
  \if@twocolumn
  \@restonecoltrue\onecolumn
  \else
  \@restonecolfalse
  \fi
  \chapter*{\contentsname
   \@mkboth{%
     \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}
 % Addition
 \if@shorttoc
 \protected@edef\@currentlabel{shorttoc}% Rather unimportant
 \edef\@currentlabelname{\shortcontentsname}% For \nameref
 \label{toc::shorttoc}% 
 % Now let us fix the hyperanchor for the short toc
 \edef\@currentlabelname{}%
 \protected@edef\@currentlabel{\@currentHref}\label{toc::shorttoc::anchor}
 \else
 \protected@edef\@currentlabel{longtoc}% Rather unimportant
 \edef\@currentlabelname{\longcontentsname}
 \label{toc::longtoc}%
 % Now let us fix the hyperanchor for the long toc
 \edef\@currentlabelname{}%
 \protected@edef\@currentlabel{\@currentHref}\label{toc::longtoc::anchor} 
 \fi
 % End of additions
 \@starttoc{toc}%
 \if@restonecol\twocolumn\fi
}
\newcommand{\longcontentsname}{Detailed Contents}
\newcommand{\shortcontentsname}{Short Contents}
%
\newcommand{\shorttableofcontents}[1][1]{%
  \begingroup
  \@shorttoctrue
  \setcounter{tocdepth}{#1}
  \let\shortcontentsstuff\relax
  \phantomsection
  \write\@auxout{\string\@writefile{toc}{\protect\longcontentsstuff}}
  \let\contentsname\shortcontentsname% Disabling the \shortcontentsstuff in toc
  \tableofcontents
  \endgroup
  \@shorttocfalse% Disable the short toc
}
\newcommand{\longtableofcontents}[1][3]{%
  \begingroup
  \setcounter{tocdepth}{#1}
  \phantomsection
  \let\longcontentsstuff\relax% Disabling the \longcontentsstuff in toc
  \write\@auxout{\string\@writefile{toc}{\protect\shortcontentsstuff}}
  \let\contentsname\longcontentsname
  \tableofcontents
  \endgroup
}
\makeatother

\begin{document}

\shorttableofcontents\clearpage

In section \secref{sec:more} of \cref{chap:one} \dots .

And in \cref{sec:one} \dots .

\chapter{One}\label{chap:one}

\section{About one}\label{sec:one}

\section{More about one}\label{sec:more}

\chapter{Two}

In section \ref{sec:more}

\end{document}

Trickier answer does work conflict-free

The second, "Trickier" version in the answer does work without conflicting with the code for two tables of contents.

murray
  • 7,944
  • 1
    Related: https://tex.stackexchange.com/a/373769/31729 and https://tex.stackexchange.com/a/353536/31729 –  Jul 27 '17 at 22:05
  • Add \providecommand{\LastRefSteppedCounter}{} to the preamble preferably before \RegisterPostLabelHook. It was missing in xassoccnt v.1.4. I will fix this feature/bug and provide xassoccnt v.1.5. soon –  Jul 28 '17 at 09:55
  • I've just uploaded the fix, the \providecommand by-pass solution is not necessary after that, but can be kept, since it is ignored then. –  Jul 28 '17 at 10:19

1 Answers1

6

The information can be obtained by multiple ways, here is a solution with the powerful zref package, which can be exploited to provide a lot of additional information in labels.

First use \RegisterPostLabelHook from xassoccnt to provide an automatic \zlabel after the usual \label has been set.

Define a new reference property, say section, with \zref@newprop and add it to the standard property save list provided by zref.

In order to extract the section property only, use a special \secref command, that automatically sets the hyperlink with \zref@extract{#1}{anchor}, which is also a feature of zref by using the hyperref module.

\documentclass[12pt]{memoir}
\usepackage{hyperref}
\usepackage{cleveref}  
\usepackage{xassoccnt}

\usepackage[user,hyperref]{zref}

\RegisterPostLabelHook{\zlabel}

\makeatletter
\zref@newprop{section}{\arabic{section}}% Change \arabic{section} by \Roman{section} etc. if needed
\zref@addprop{main}{section}

\newcommand{\secref}[1]{%
  \zref@ifrefundefined{#1}{%
    \ref{#1}% fall back to usual \ref if there's no such zref - specific label. 
  }{%
    \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{section}}%
  }%
}
\makeatother
\crefname{chapter}{Chapter}{Chapters}  

\begin{document}

In section \secref{sec:more} of \cref{chap:one} \dots .

And in \cref{sec:one} \dots .

\chapter{One}\label{chap:one}

\section{About one}\label{sec:one}

\section{More about one}\label{sec:more}

\chapter{Two}

In section \ref{sec:more}

\end{document}

enter image description here

Trickier version almost without extra package other than refcount

\documentclass[12pt]{memoir}
\usepackage{hyperref}
\usepackage{cleveref}  

\makeatletter

\let\@xp\expandafter

% Stripping the dot from the 1.2 -like reference
\def\@@stripdot#1.#2\@nil{#2}

% Stripping the memoir stuff from the reference, i.e. \M@TitleReference {1.2}{FOO} and handing #1 (1.2) over to the \@@stripdot macro
\def\@stripdot\M@TitleReference #1#2\@nil{\@@stripdot#1\@nil}

%Macro, second level of expansion
\newcommand{\stripdot}[1]{%
  \@xp\@stripdot#1\@nil
}



\newcommand{\secref}[1]{%
  % Expand the argument first
  \IfRefUndefinedExpandable{#1}{%
    % Do nothing if #1 is not defined
  }{%
    \hyperlink{\getrefbykeydefault{#1}{anchor}{}}{\@xp\stripdot\@xp{\getrefnumber{#1}}}%
  }%
}

\makeatother
\crefname{chapter}{Chapter}{Chapters}  

\begin{document}

In section \secref{sec:more} of \cref{chap:one} \dots .

And in \cref{sec:one} \dots .

\chapter{One}\label{chap:one}

\section{About one}\label{sec:one}

\section{More about one}\label{sec:more}

\chapter{Two}

In section \ref{sec:more}

\end{document}

Third installment providing the fix for the missing \LastRefSteppedCounter macro -- it is not necessary for xassoccnt v1.5 and above.

\documentclass[12pt]{memoir}
\usepackage[colorlinks]{hyperref}
\usepackage{cleveref}  
\usepackage{xparse}

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

% xassoccnt v1.4 misses a predefined \LastRefSteppedCounter which expands to nothing, so use 
\providecommand{\LastRefSteppedCounter}{}

% It is fixed in xassoccnt v1.5 and the \providecommand{\LastRefSteppedCounter}{} above is not necessary then, so either remove it or keep it, it is ignored anyway then.


\RegisterPostLabelHook{\zlabel}


\makeatletter
\zref@newprop{section}{\arabic{section}}% Replace \arabic{section} by \Roman{section} etc. if needed 
\zref@addprop{main}{section}
%
\newcommand{\secref}[1]{%
  \zref@ifrefundefined{#1}{%
    \ref{#1}% fall back to usual \ref if there's no such zref - specific label. 
  }{%
    \hyperlink{\zref@extract{#1}{anchor}}{\zref@extract{#1}{section}}%
  }%
}
\makeatother

\crefname{chapter}{Chapter}{Chapters}  
\crefname{section}{Section}{Sections}

%% SHORT & LONG TOCs
%% Code by Christian Hupfer 
\makeatletter
% Just in case we're not loading hyperref
\@ifpackageloaded{hyperref}{%
}{
  \providecommand{\@currentHref}{}
  \providecommand{\hyperlink}[2]{#2}
  \providecommand{\getrefnumber}[1]{}
  \providecommand{\phantomsection}{}
}

\AtBeginDocument{%
\newcommand{\shortcontentsstuff}{%
  \contentsline{chapter}{\hyperlink{\getrefnumber{toc::shorttoc::anchor}}{\shortcontentsname}}{\pageref{toc::shorttoc}}{\getrefnumber{toc::shorttoc::anchor}}
}
\newcommand{\longcontentsstuff}{%
  \contentsline{chapter}{\hyperlink{\getrefnumber{toc::longtoc::anchor}}{\longcontentsname}}{\pageref{toc::longtoc}}{\getrefnumber{toc::longtoc::anchor}}
}
}
\newif\if@shorttoc
%
\renewcommand{\tableofcontents}{%
  \if@twocolumn
  \@restonecoltrue\onecolumn
  \else
  \@restonecolfalse
  \fi
  \chapter*{\contentsname
   \@mkboth{%
     \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}
 % Addition
 \if@shorttoc
 \protected@edef\@currentlabel{shorttoc}% Rather unimportant
 \edef\@currentlabelname{\shortcontentsname}% For \nameref
 \label{toc::shorttoc}% 
 % Now let us fix the hyperanchor for the short toc
 \edef\@currentlabelname{}%
 \protected@edef\@currentlabel{\@currentHref}\label{toc::shorttoc::anchor}
 \else
 \protected@edef\@currentlabel{longtoc}% Rather unimportant
 \edef\@currentlabelname{\longcontentsname}
 \label{toc::longtoc}%
 % Now let us fix the hyperanchor for the long toc
 \edef\@currentlabelname{}%
 \protected@edef\@currentlabel{\@currentHref}\label{toc::longtoc::anchor} 
 \fi
 % End of additions
 \@starttoc{toc}%
 \if@restonecol\twocolumn\fi
}
\newcommand{\longcontentsname}{Detailed Contents}
\newcommand{\shortcontentsname}{Short Contents}
%
\newcommand{\shorttableofcontents}[1][1]{%
  \begingroup
  \@shorttoctrue
  \setcounter{tocdepth}{#1}
  \let\shortcontentsstuff\relax
  \phantomsection
  \write\@auxout{\string\@writefile{toc}{\protect\longcontentsstuff}}
  \let\contentsname\shortcontentsname% Disabling the \shortcontentsstuff in toc
  \tableofcontents
  \endgroup
  \@shorttocfalse% Disable the short toc
}
\newcommand{\longtableofcontents}[1][3]{%
  \begingroup
  \setcounter{tocdepth}{#1}
  \phantomsection
  \let\longcontentsstuff\relax% Disabling the \longcontentsstuff in toc
  \write\@auxout{\string\@writefile{toc}{\protect\shortcontentsstuff}}
  \let\contentsname\longcontentsname
  \tableofcontents
  \endgroup
}
\makeatother


\providecommand{\LastRefSteppedCounter}{}

\begin{document}



\longtableofcontents\clearpage

\shorttableofcontents\clearpage

In section \secref{sec:more} of \cref{chap:one} \dots .

And in \cref{sec:one} \dots .

\chapter{One}\label{chap:one}

\section{About one}\label{sec:one}

\section{More about one}\label{sec:more}

\chapter{Two}

In section \ref{sec:more}

\end{document}
  • 1
    +1 I just wanted to leave a comment to point to a similar answer of yours, but the counter-wizard answers so fast :) – samcarter_is_at_topanswers.xyz Jul 27 '17 at 21:49
  • 1
    @samcarter: :D Perhaps there's a similar answer, but I was too lazy to look after it. ... counter-wizard :D :D :D –  Jul 27 '17 at 21:52
  • Should one of the links point to https://tex.stackexchange.com/questions/373767/get-section-number-if-referencing-a-subsection-instead-of-subsection-number/373769#373769 ? – samcarter_is_at_topanswers.xyz Jul 27 '17 at 21:59
  • @samcarter: Yes, I've added it (and shifted the comment to the question here) to make it easier to find –  Jul 27 '17 at 22:00
  • 1
    I guessed that - but it seems its the exact same link two times. That's why I am wondering what the second link should be. – samcarter_is_at_topanswers.xyz Jul 27 '17 at 22:01
  • @samcarter: Oh, you're right: Apparently the copy-and-paste-buffer wasn't updated correctly. I'll try again -- I am no providing-the-correct-link-wizard however :D –  Jul 27 '17 at 22:03
  • 1
    Being a wizard in everything would be too boring :) – samcarter_is_at_topanswers.xyz Jul 27 '17 at 22:05
  • @samcarter: Well, it's only one thing I have no profound wizardry knowledge (ok, this is a lie, of course :D) –  Jul 27 '17 at 22:06
  • 1
    I drew a picture of you in \mode<wizard> :) https://tex.stackexchange.com/a/347458/36296 – samcarter_is_at_topanswers.xyz Jul 27 '17 at 22:40
  • @samcarter: OMG .... the duck with the wand? So I am duck now? sob -- I can't upvote again, I've done so a long time ago .... –  Jul 27 '17 at 22:45
  • @Christian Hupfer: The answer using zrefconflicts with code (given by you in a different post) to create both a short and a long table of contents. – murray Jul 28 '17 at 00:28
  • @ChristianHupfer: but the "Trickier version almost without extra packages..." works perfectly even with the code for two tables of contents. – murray Jul 28 '17 at 00:43
  • In the "Trickier" version, I don't see explicit loading of refcount. – murray Jul 28 '17 at 00:47
  • The first version is theasy better one, however. I have no time right now to take a look why your changed (!!!!) question code does not work –  Jul 28 '17 at 04:33
  • @murray: hyperref loads refcount –  Jul 28 '17 at 04:34
  • "Third installment" works like a charm, not only with the two-tables-of-contents code, but also with all the other customizations I'm using. Thanks you. – murray Jul 28 '17 at 22:41
  • @murray: Yes, of course ;-) The zref way is the better and cleaner way, the only thing I forgot when updating to xassoccnt 1.4 was this \LastRefSteppedCounter macro –  Jul 29 '17 at 10:18
  • Unless I'm missing something, the "trickier" version is preferable in that it does not load xassoccnt and hence avoids any actual or potential clash with calc. – murray Nov 27 '18 at 15:06