在章节/部分方案中,有时我希望能够引用某个部分,该部分通常以 cs 的形式出现,其中 c 是章节编号,s 是部分编号,仅以 s 的形式出现。
如何?
样本来源:
\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}
与创建两个目录发生冲突
使用的答案zref
与答案中所示的一样有效,但是当我将下面所示的代码添加到序言中以生成长目录和短目录时 - 使用命令\shorttableofcontents
和\longtableofcontents
之后\begin{document}
,我在使用的地方的行上收到错误\shorttableofcontents
。
错误是:
未定义控制序列
这是完整的源代码,包括zref
用于创建两个目录的代码(由 Christian Hupfer 提供)以及使用的额外代码。
\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}
更棘手的答案确实可以无冲突地工作
答案中的第二个“棘手”版本做工作时不会与两个目录的代码发生冲突。
答案1
这些信息可以通过多种方式获取,这里有一个功能强大的zref
软件包解决方案,可以利用它来在标签中提供大量附加信息。
首先使用\RegisterPostLabelHook
from 来提供在设置完常规后的xassoccnt
自动功能。\zlabel
\label
定义一个新的引用属性,例如section
,\zref@newprop
并将其添加到提供的标准属性保存列表中zref
。
为了仅提取部分属性,请使用特殊\secref
命令,该命令会自动设置超链接\zref@extract{#1}{anchor}
,这也是zref
使用该hyperref
模块的一个功能。
\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}
更棘手的版本几乎没有额外的包,除了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}
第三部分提供对缺失宏的修复——对于v1.5 及以上版本\LastRefSteppedCounter
来说它不是必需的。xassoccnt
\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}