4

While working on a multivolume book, I use a smart cross-referencing method as suggested at Smart cross-references between 2 volumes using Zref package. The \sref and \seqref commands described there add to the link, which are printed by the usual \ref and \eqref commands, the chapter number as the prefix "No." if the target (for example, an equation) is located in a different chapter No. If the object is located in the current chapter, the chapter number is not printed.

Everything was fine until I added an appendix. The fact is that the \appendix declaration resets the chapter counter to zero. Therefore, the chapter counter in the first chapter of the main text and in the first appendix has the same value 1. Hence, the \seqref command, which in the Appendix A points to an equation in chapter 1, prints the equation number without prefix "1." Conversely, the \seqref command, which in the first chapter points to an equation in Appendix A, prints the equation number without the prefix "A."

A minimal working example below is slightly modified from the cited above post. Separation of the main text and the code on two files is preserved although this is not obligatory for illustrating the above described problem. Common code is written in 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

Main file just reads the code file:

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

I tried to modify the code file to solve the problem. First, I changed the declaration of the chatervalue property so that the current value of \thechapter command is written to the .aux file, and not the value of the chapter counter:

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

However, I have not been able to change the command \ifcurrentchapter so that it correctly compares the \thechapter value to the chaptervalue property. The following definition of the command \ifcurrentchapter always gives a false value.

\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%
}

How to modify its definition to make it working as desired?

2 Answers2

4

I would simply add another property, e.g. a new counter, that you can advance for the appendix. Then you can test it for equality. The alternative would be an "absolute chapter counter", that would work too, and make the test a bit shorter.

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

enter image description here

enter image description here

enter image description here

Ulrike Fischer
  • 327,261
  • Thank you but I want a more robust solution. – Igor Kotelnikov Aug 12 '20 at 08:47
  • what do you mean with more robust? Side question: I did sent you a mail a few weeks ago, did you get it? – Ulrike Fischer Aug 12 '20 at 08:52
  • Yes, I received your mail but decided not to change anything. To say trust I don't know what to change.

    By more robust I mean a solution which will not know a priori how the chapter number is formatted in appendix, \Roman{chapter} or, say, \Latin{chapter}.

    – Igor Kotelnikov Aug 12 '20 at 09:00
  • My code doesn't care how the chapters are formatted, I simply use a number which is 0 in the mainmatter, and 1 in the appendix and compare this number. That is much more robust than your idea to compare the formatted chapter number. – Ulrike Fischer Aug 12 '20 at 09:06
  • And regarding hyperref: I will remove the language patches in hyperref in the next days, and when this is uploaded it will lie in responsability of the language definition files to get correct bookmarks. If you need help to adapt russian you can ask me. – Ulrike Fischer Aug 12 '20 at 09:08
  • Why? You can simply use the standard \ref here can't you? I mean you can with zref store the number "1", the representation "A.", and the locationnumber "1"=appendix. Then you can use the number and the locationnumber for the tests, and the stored representation to print. Isn't that the main point to use zref? That you can store more than one data for a label? – Ulrike Fischer Aug 12 '20 at 09:15
  • However your code must know how to format chapter counter when it comes from equation in the appendix. I am mot strong with TeX core and don't know how to compare a character in chaptervalue with a character in \thesection – Igor Kotelnikov Aug 12 '20 at 09:16
  • I will add the code so that you can see that it is not needed, but please adapt russian as a thank. To be sure that I got it right: the equation reference should print as 1, 1.1 or A.1 right? – Ulrike Fischer Aug 12 '20 at 09:22
  • I edited the question along with screenshots of the three chapter. I used expl3 for the test as I'm feeling more comfortable with it - the logic is more readable, but it is not required, one could do it with plain tex conditionals too. – Ulrike Fischer Aug 12 '20 at 10:07
  • I don't understand definition of \IfCounterchapterTF. Perhaps instead pf \zref@extractdefault{#1}{counter}{0} there should be \zref@extractdefault{#1}{chaptervalue}{0}? – Igor Kotelnikov Aug 14 '20 at 23:08
  • no the test is there to get the correct output for \sref{ch:1}, you don't want the chapter prefix there, as it would lead to double values (A.A, 1.1), force the test to fail with e.g. \IfCounterchapterTF{x#1} then you can see what I mean. – Ulrike Fischer Aug 14 '20 at 23:12
  • I mean that there is no propery {counter}. I has changed {counter} to {chaptervalue} and also got correct result. \IfCounterchapterTF{x#1} also gave correct result. It seems that \IfCounterchapterTF{#1} always evaluates to false. – Igor Kotelnikov Aug 15 '20 at 02:32
  • The property counter is provided by the counter module of zref, I load it when loading zref. – Ulrike Fischer Aug 15 '20 at 06:39
3

It seams that I found a solution myself. Here it is:

% 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

Substituted strings just follow commented out old strings.

Update Ulrike Fischer noted that the above solution fails if chapter number is larger than 9. She proposed to add one or two more counters to achieve desired result using LaTeX3 syntax. My solution below avoids addition of new counters. It is more robust as there is no need to step up mattercnt counter at \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}

Code is concentrated in 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