再次使用 zref 包进行智能交叉引用

再次使用 zref 包进行智能交叉引用

在编写多卷书时,我使用了一种智能交叉引用方法,如使用 Zref 包在 2 个卷之间进行智能交叉引用。那里描述的\sref\seqref命令添加到链接中,这些链接由通常的\ref\eqref命令打印,章节号作为前缀“不。“如果目标(例如,一个方程式)位于不同的章节如果对象位于当前章节,则不打印章节号。

在我添加附录之前,一切都很好。事实是声明将计数器\appendix重置chapter为零。因此,chapter正文第一章和第一个附录中的计数器具有相同的值 1。因此,\seqref附录 A 中指向第 1 章中方程的命令将打印不带前缀“1”的方程编号。相反,\seqref第一章中指向附录 A 中方程的命令将打印不带前缀“A”的方程编号。

下面的一个最小工作示例与上面引用的帖子略有不同。主要文本和代码在两个文件中的分离被保留,尽管这对于说明上述问题来说不是必须的。通用代码写在test2-zref-common.tex

% Load packages and declare external docs.
\usepackage{xr-hyper}%                     <== load xr-hyper package
\usepackage[unicode,colorlinks]{hyperref}% <== load hyperref package
\usepackage[user]{zref}
\makeatletter
\zref@newprop{chaptervalue}[-1]{\the\value{chapter}}% <= note the default value [0]
%%\zref@newprop{chaptervalue}[0]{\thechapter}% <= note the default value [-1]
\zref@localaddprops{main}{chaptervalue}
\makeatother

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}

% Define \sref and \seqref macros for smart cross-references of equations
\makeatletter
\newcommand\ifcurrentchapter[3]{%
  \def\temp@a{\number\value{chapter}}%
  %%\def\temp@a{\thechapter}%
  \def\temp@b{\zref@extract{#1}{chaptervalue}}%
  \ifnum\temp@a=\temp@b%
  %%\if\temp@a\temp@b%
    #2%
  \else%
    \ifnum\temp@b<0
    %%\if\temp@b=0
      #2%
    \else
      #3%
    \fi%
  \fi%
}
\newcommand{\sref}[1]{\hyperref[#1]{\hbox{\ifcurrentchapter{#1}{}{\zref[chaptervalue]{#1}.}\zref{#1}}}}
\newcommand{\seqref}[1]{(\sref{#1})}
\makeatother

% Define a macro to print test text
\newcommand{\testtext}{
    Chapter \sref{ch:1}, Chapter \sref{ch:2}, Chapter \sref{ch:1A}.
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1}. Equal: \ifcurrentchapter{ch:1}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:2}. Equal: \ifcurrentchapter{ch:2}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1A}. Equal: \ifcurrentchapter{ch:1A}{Yes}{No}
    \par\noindent
    \seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}; \seqref{1A.1}, \seqref{1A.2}.
}

\endinput 

主文件只是读取代码文件:

\documentclass[oneside]{book}
\input{test2-zref-common}

\begin{document}
\chapter{1 in Volume 1}\label{ch:1}\zlabel{ch:1}
\testtext
\begin{equation}
  eq1.1
  \label{1.1}\zlabel{1.1}
\end{equation}
\begin{equation}
  eq1.2
  \label{1.2}\zlabel{1.2}
\end{equation}

\chapter{2  in Volume 2}\label{ch:2}\zlabel{ch:2}
\testtext
\begin{equation}
  eq2.1
  \label{2.1}\zlabel{2.1}
\end{equation}
\begin{equation}
  eq2.2
  \label{2.2}\zlabel{2.2}
\end{equation}

\appendix
\chapter{A in Volume 1}\label{ch:1A}\zlabel{ch:1A}
\testtext
\begin{equation}
  eq1A.1
  \label{1A.1}\zlabel{1A.1}
\end{equation}
\begin{equation}
  eq1A.2
  \label{1A.2}\zlabel{1A.2}
\end{equation}

\end{document} 

我尝试修改代码文件来解决这个问题。首先,我更改了属性的声明chatervalue,以便将\thechapter命令的当前值写入文件.aux,而不是计数器的值chapter

%%\zref@newprop{chaptervalue}[-1]{\the\value{chapter}}
\zref@newprop{chaptervalue}[0]{\thechapter}

但是,我无法更改命令,\ifcurrentchapter以便它正确地将\thechapter值与chaptervalue属性进行比较。该命令的以下定义\ifcurrentchapter总是给出错误值。

\newcommand\ifcurrentchapter[3]{%
  %%\def\temp@a{\number\value{chapter}}%
  \def\temp@a{\thechapter}%
  \def\temp@b{\zref@extract{#1}{chaptervalue}}%
  %%\ifnum\temp@a=\temp@b%
  \if\temp@a\temp@b%
    #2%
  \else%
    %%\ifnum\temp@b<0
    \if\temp@b=0
      #2%
    \else
      #3%
    \fi%
  \fi%
}

如何修改它的定义以使其按预期工作?

答案1

我只需添加另一个属性,例如一个新的计数器,您就可以将其推进到附录。然后您可以测试它是否相等。替代方案是“绝对章节计数器”,这也可以工作,并使测试更短一些。

\documentclass[oneside]{book}
\usepackage{xr-hyper}%                     <== load xr-hyper package
\usepackage[unicode,colorlinks]{hyperref}% <== load hyperref package
\usepackage[user,counter]{zref}
\makeatletter
\newcounter{mattercnt}
\zref@newprop{chaptervalue}[-1]{\the\value{chapter}}% 
\zref@newprop{mattervalue} [-1]{\the\value{mattercnt}}% 
\zref@newprop{chapterprint}{\thechapter}% 
\zref@localaddprops{main}{chaptervalue}
\zref@localaddprops{main}{mattervalue}
\zref@localaddprops{main}{chapterprint}
\makeatother

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}

% Define \sref and \seqref macros for smart cross-references of equations
\makeatletter
\ExplSyntaxOn
\newcommand\IfCurrentchapterTF[1]
 {
  \bool_if:nTF 
  {
    \int_compare_p:nNn { \value{chapter} }  =  { \zref@extract{#1}{chaptervalue} }
     &&
    \int_compare_p:nNn { \value{mattercnt} } = { \zref@extract{#1}{mattervalue} } 
  }  
 }

\newcommand\IfCounterchapterTF[1]
 {
   \str_if_eq:eeTF {chapter}{\zref@extractdefault{#1}{counter}{0}}
 }

\ExplSyntaxOff 


\newcommand{\sref}[1]{%
 \hyperref[#1]
  {%
    \hbox
     {%
      \IfCounterchapterTF{#1}
       {}%print only chapter number
       {%
        \IfCurrentchapterTF{#1}
         {}
         {\zref[chapterprint]{#1}.}%
       }%
     \zref{#1}%
    }%
  }%
 } 
\newcommand{\seqref}[1]{(\sref{#1})}
\makeatother

% Define a macro to print test text
\newcommand{\testtext}{
    Chapter \sref{ch:1}, Chapter \sref{ch:2}, Chapter \sref{ch:1A}.
    \par\noindent
    Compare \number\value{chapter} with \zref[chapterprint]{ch:1}. Equal: \IfCurrentchapterTF{ch:1}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chapterprint]{ch:2}. Equal: \IfCurrentchapterTF{ch:2}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chapterprint]{ch:1A}. Equal: \IfCurrentchapterTF{ch:1A}{Yes}{No}
    \par\noindent
    \seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}; \seqref{1A.1}, \seqref{1A.2}.
}

\begin{document}
\chapter{1 in Volume 1}\label{ch:1}\zlabel{ch:1}
\testtext
\begin{equation}
  eq1.1
  \label{1.1}\zlabel{1.1}
\end{equation}
\begin{equation}
  eq1.2
  \label{1.2}\zlabel{1.2}
\end{equation}

\chapter{2  in Volume 2}\label{ch:2}\zlabel{ch:2}
\testtext
\begin{equation}
  eq2.1
  \label{2.1}\zlabel{2.1}
\end{equation}
\begin{equation}
  eq2.2
  \label{2.2}\zlabel{2.2}
\end{equation}

\appendix\stepcounter{mattercnt}
\chapter{A in Volume 1}\label{ch:1A}\zlabel{ch:1A}
\testtext
\begin{equation}
  eq1A.1
  \label{1A.1}\zlabel{1A.1}
\end{equation}
\begin{equation}
  eq1A.2
  \label{1A.2}\zlabel{1A.2}
\end{equation}

\end{document} 

在此处输入图片描述

在此处输入图片描述

在此处输入图片描述

答案2

看来我自己找到了解决方案。如下:

% Load packages and declare external docs.
\usepackage{xr-hyper}%                     <== load xr-hyper package
\usepackage[unicode,colorlinks]{hyperref}% <== load hyperref package
\usepackage[user]{zref}
\makeatletter
%%\zref@newprop{chaptervalue}[-1]{\the\value{chapter}}% <= note the default value [0]
\zref@newprop{chaptervalue}[0]{\thechapter}% <= note the default value [-1]
\zref@localaddprops{main}{chaptervalue}
\makeatother

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}

% Define \sref and \seqref macros for smart cross-references of equations
\makeatletter
\newcommand\ifcurrentchapter[3]{%
  %%\def\temp@a{\number\value{chapter}}%
  \def\temp@a{\expandafter\thechapter}%
  \def\temp@b{\zref@extract{#1}{chaptervalue}}%
  \def\temp@c{0}%
  %%\ifnum\temp@a=\temp@b%
  %[\temp@a][\temp@b]
  \if\temp@a\temp@b%
    #2%
  \else%
    %%\ifnum\temp@b<0
    \if\temp@b\temp@c%
      #2%
    \else
      #3%
    \fi%
  \fi%
}
\newcommand{\sref}[1]{\hyperref[#1]{\hbox{\ifcurrentchapter{#1}{}{\zref[chaptervalue]{#1}.}\zref{#1}}}}
\newcommand{\seqref}[1]{(\sref{#1})}
\makeatother

% Define a macro to print test text
\newcommand{\testtext}{
    Chapter \sref{ch:1}, Chapter \sref{ch:2}, Chapter \sref{ch:1A}.
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1}. Equal: \ifcurrentchapter{ch:1}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:2}. Equal: \ifcurrentchapter{ch:2}{Yes}{No}
    \par\noindent
    Compare \number\value{chapter} with \zref[chaptervalue]{ch:1A}. Equal: \ifcurrentchapter{ch:1A}{Yes}{No}
    \par\noindent
    \seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2}; \seqref{1A.1}, \seqref{1A.2}.
}

\endinput 

替换的字符串仅跟随注释掉的旧字符串。

更新 Ulrike Fischer 指出,如果章节数大于 9,上述解决方案将失败。她建议使用 LaTeX3 语法添加一两个计数器来实现所需结果。我的以下解决方案避免添加新计数器。它更强大,因为无需增加mattercnt计数器\appendix

test2-zref-1.tex

\documentclass[oneside]{book}
\input{test2-zref-common}

\begin{document}
\chapter{1 in Volume 1}\label{ch:1}\zlabel{ch:1}

\testtext
\begin{equation}
  eq1.1
  \label{1.1}\zlabel{1.1}
\end{equation}
\begin{equation}
  eq1.2
  \label{1.2}\zlabel{1.2}
\end{equation}

\chapter{2  in Volume 1}\label{ch:2}\zlabel{ch:2}

\testtext
\begin{equation}
  eq2.1
  \label{2.1}\zlabel{2.1}
\end{equation}
\begin{equation}
  eq2.2
  \label{2.2}\zlabel{2.2}
\end{equation}

\setcounter{chapter}{15}
\chapter{16 in Volume 1}\label{ch:16}\zlabel{ch:16}

\testtext
\begin{equation}
  eq16.1
  \label{16.1}\zlabel{16.1}
\end{equation}
\begin{equation}
  eq16.2
  \label{16.2}\zlabel{16.2}
\end{equation}

\appendix
%\stepcounter{matter}
\chapter{A in Volume 1}\label{ch:1A}\zlabel{ch:1A}

\testtext
\begin{equation}
  eq1A.1
  \label{1A.1}\zlabel{1A.1}
\end{equation}
\begin{equation}
  eq1A.2
  \label{1A.2}\zlabel{1A.2}
\end{equation}

\end{document}

代码集中在test2-zref-common.tex

%
% Load packages and declare external docs.
%
\usepackage{xr-hyper}%                     <== load xr-hyper package
\usepackage[unicode,colorlinks]{hyperref}% <== load hyperref package
\usepackage[user]{zref}
%
% Define a macro that prints test text
%
\newcommand{\testtext}{
    Chapter \sref{ch:1}, Chapter \sref{ch:2}, Chapter \sref{ch:16}, Chapter \sref{ch:1A}.
    \par\noindent
    Compare \thechapter\ with \zref[thechapter]{ch:1}. Equal: \IfCurrentchapterTF{ch:1}{Yes}{No}
    \par\noindent
    Compare \thechapter\ with \zref[thechapter]{ch:2}. Equal: \IfCurrentchapterTF{ch:2}{Yes}{No}
    \par\noindent
    Compare \thechapter\ with \zref[thechapter]{ch:16}. Equal: \IfCurrentchapterTF{ch:16}{Yes}{No}
    \par\noindent
    Compare \thechapter\ with \zref[thechapter]{ch:1A}. Equal: \IfCurrentchapterTF{ch:1A}{Yes}{No}
    \par\noindent
    \seqref{1.1}, \seqref{1.2}; \seqref{2.1}, \seqref{2.2};
    \seqref{16.1}, \seqref{16.2}; \seqref{1A.1}, \seqref{1A.2}.
}

% Reset default equation numbering
\usepackage{amsmath}
\numberwithin{equation}{chapter}
\renewcommand{\theequation}{\arabic{equation}}
\newcounter{chaptertotal}

% 
% main code
%
\makeatletter
\newcounter{matter}
\zref@newprop{thechapter}[??]{\thechapter}%
\zref@localaddprops{main}{thechapter}
\makeatother

%%
%% Define \sref and \seqref macros for smart cross-references
%%
\makeatletter
\ExplSyntaxOn
\str_new:N \stra
\str_new:N \strb

\newcommand\IfCurrentchapterTF[1]
 {
    \str_set:Nx \stra { \thechapter }%
    \str_set:Nx \strb { \zref@extract{#1}{thechapter} }%
    %\stra=\strb \str_if_eq:NNTF \stra \strb {Y}{N}
    \str_if_eq:NNTF \stra \strb
 }

\ExplSyntaxOff

\newcommand{\sref}[1]{%
 \hyperref[#1]
  {%
    \hbox
     {%
        \IfCurrentchapterTF{#1}
         {}
         {\zref[thechapter]{#1}.}%
     \zref{#1}%
    }%
  }%
 }
\newcommand{\seqref}[1]{(\sref{#1})}

\makeatother

\endinput

相关内容