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.

3
  • 1
    Related: tex.stackexchange.com/a/373769/31729 and tex.stackexchange.com/a/353536/31729
    – user31729
    Jul 27, 2017 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, 2017 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, 2017 at 10:19

1 Answer 1

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}
18

You must log in to answer this question.

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