5

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.

  • 1
    Related: tex.stackexchange.com/a/373769/31729 and tex.stackexchange.com/a/353536/31729 – user31729 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 – user31729 Jul 28 '17 at 9: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. – user31729 Jul 28 '17 at 10:19
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 :) – user36296 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 – user31729 Jul 27 '17 at 21:52
  • 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. – user36296 Jul 27 '17 at 22:01
  • 1
    Being a wizard in everything would be too boring :) – user36296 Jul 27 '17 at 22:05
  • 1
    I drew a picture of you in \mode<wizard> :) tex.stackexchange.com/a/347458/36296 – user36296 Jul 27 '17 at 22:40

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.