6

Is there some package providing a simple user interface to return the counter value (numeric, not the formatted cross-reference, as \ref does) of a label? It seems neither zref, not refcount, nor cleveref, among others, provide it. cleveref saves the counter value to the aux file, but I couldn't find in the docs a macro to retrieve it (something like, say, \numbercref), even if internally there is a \cref@getcounter for that.

Please, note I'm not asking how to do it, just if there is a package with a simple user interface.

  • For more complex problems, zref is the better way to go, I think – user31729 Dec 29 '18 at 10:56
  • One 'disadvantage' with zref is that it is necessary to use \zlabel -- i.e. zref does not hook into \label as cleveref does -- the \zlabel must be specified in addition to \label – user31729 Dec 29 '18 at 11:50
  • I don't understand why you say refcount doesn't provide this. Can you explain and/or provide an example as to why you say this? – Werner Dec 31 '18 at 19:21
  • 1
    Because its manual states "If the reference does not contain a number, assignments to a counter will fail of course" :-). And references can be anything, like "(m)", "V.b.6" or "Second". – Javier Bezos Jan 2 at 8:20
8

I have written crossreftools about one year ago, this package extracts information from cleveref labels with \crtcrefnumber, this holds the number of the counter, using the special way how cleveref stores the information in its labels.

Traditional labels do not support this, since those labels apply \thefoo, meaning that something like \renewcommand{\thefoo}{\arabic{chapter}.\Roman{section}.\Alph{foo}} will store 4.II.C, for example. This way \crtrefnumber will report the usual reference value but not the counter value of foo, 3 in the above example.

Most \crt... macros are expandable.

The zref package is very sophisticated, but it does not provide means to store the counter value -- the counter name is quite easy to catch, by loading the counter module of zref, see a possible solution with zref at the end, however.

In order to achieve this a new property must be defined, with \zref@newprop and later added to the main property list with \zref@addprop.

In total, crossreftools is not invasive as it just reevaluates the already stored label macros, whereas the second solution changes \refstepcounter (marginally, however). If more information is to be stored with within labels, zref is most likely the better way to pursue.

enter image description here

\documentclass{book}


\usepackage{cleveref}
\usepackage{crossreftools}

\begin{document}

See \crtrefnumber{foosec} or \crtcrefnumber{foosec}

\chapter{Foo}

\setcounter{section}{99}

\section{A foo section} \label{foosec}

\end{document}

Update

Here is version with zref, that stores the name of the last counter being used in \refstepcounter and extracts the value with \zlabels then.

\documentclass{book}

\usepackage[user,counter]{zref}

\setcounter{secnumdepth}{4}

\makeatletter
\AtBeginDocument{%
  \let\originalrefstepcounter\refstepcounter%
  \renewcommand{\refstepcounter}[1]{%
    \xdef\@@lastrefsteppedcounter{#1}%
    \originalrefstepcounter{#1}%
  }
}

\zref@newprop{value}[-100000]{\number\value{\@@lastrefsteppedcounter}}
\zref@addprop{main}{value}
\newcommand{\counterref}[1]{%
  \zref@extract{#1}{value}%
}
\makeatother

\usepackage{cleveref}
\usepackage{crossreftools}

\counterwithin{equation}{chapter}

% some helper macros in order to simplify demonstration of counter values

\newcommand{\foosectionnumber}{100}
\newcommand{\foosubsectionnumber}{20}
\newcommand{\foosubsubsectionnumber}{44}
\newcommand{\einsteinnumber}{1905}

\newcommand{\foofigurenumber}{2018}


\begin{document}

\newcommand{\tableentryline}[2]{%
  \tabularnewline
  #1 & #2 & \crtrefnumber{#1} & \crtcrefnumber{#1} & \counterref{#1} \tabularnewline
  \tabularnewline
  \hline
} 

\begin{tabular}{lllll}
label & Expected value & \verb!\crtrefnumber! & \verb!\crtcrefnumber! & \verb!\counterref! \tabularnewline
  \hline
  \tableentryline{foosec}{\foosectionnumber} 
  \tableentryline{foosubsec}{\foosubsectionnumber} 
  \tableentryline{foosubsubsec}{\foosubsubsectionnumber} 
  \tableentryline{einstein}{\einsteinnumber}
  \tableentryline{foofigure}{\foofigurenumber}
\end{tabular}


\chapter{Foo}

\setcounter{equation}{\numexpr\einsteinnumber-1}

\setcounter{section}{\numexpr\foosectionnumber-1}

\setcounter{figure}{\numexpr\foofigurenumber-1}


\section{A foo section} \label{foosec}\zlabel{foosec}

\setcounter{subsection}{\numexpr\foosubsectionnumber-1}
\subsection{A foo subsection} \label{foosubsec} \zlabel{foosubsec}

\setcounter{subsubsection}{\numexpr\foosubsubsectionnumber-1}

\subsubsection{A foo subsubsection} \label{foosubsubsec} \zlabel{foosubsubsec}

\begin{equation}
  E= mc^{2} \label{einstein} \zlabel{einstein}
\end{equation}

\begin{figure}
  \caption{foofigure} \label{foofigure} \zlabel{foofigure}
\end{figure}

\end{document}

enter image description here

Update again

Something like (see Javier Bezos' comment below)

\setcounter{foo}{\crtcrefnumber{foostuff}}

will fail since \crtcrefnumber reports [UNDEFINED] in the beginning, i.e. the first run. This breaks \setcounter of course

Therefore I have added a new macro that is designed for a 'safe' counter value, i.e. \crtcrefcountervalue that reports the content of \crtcrefundefinedcountervalue, being 1977 (the year TeX was invented ;-)).

I added this code to the package (without the \makeatletter...\makeatother pair of course) and will uploaded a new version of crossreftools to CTAN.

\makeatletter
\newcommand{\crt@crefundefinedcountervalue}{1977}
\newcommand{\crtrefundefinedcountervalue}[1]{\renewcommand{\crt@refundefinedcountervalue}{#1}}


\newcommand{\crtcrefcountervalue}[1]{%
  \crtcrefifundefinedlabel{#1}{%
    \crt@crefundefinedcountervalue%
  }{%
    \crtcrefnumber{#1}%
  }%
}
\makeatother

Update 2019/01/06 21:04 (CET)

crossreftools v0.9 is available on TeXLive (and most likely on MikTeX as well...)

  • See also xassoccnt and \RegisterPreLabelHook{zlabel} such that \label produces both the orginal label and does call \zlabel as well – user31729 Dec 29 '18 at 11:54
  • \crtcrefnumber is (almost) what I was looking for (no @'s at all), but it fails with something like \setcounter{subsection}{\crtcrefnumber{foosec}} (the first run). Fortunately, with \crtrefundefinedtext{0} everything is fine. – Javier Bezos Dec 29 '18 at 13:10
  • 2
    @JavierBezos: Ah yes, I remember there was an issue with \setcounter and \crt... macros. I forgot to pursue. I will investigate and upload a new version. Thanks for keeping me informed – user31729 Dec 29 '18 at 14:11
  • @JavierBezos: I tracked the issue down to \crtcrefextract that reports [UNDEFINED] during the first run of LaTeX etc. This is not really a bug, but by design. Therefore, in order to provide a calculable return value for counters, I added \crtcrefcountervalue that yields 1977 in case of undefined references... That value can be change, of course. I will upload crossreftools v.0.8 in a few minutes. In the mean time, you can grab the few lines at the end of my answer – user31729 Dec 29 '18 at 15:04
  • 1
    Thank you. Actually, \crtrefundefinedtext{0} worked for me, but an out-of-the-box solution (so that it "just works") is better. – Javier Bezos Dec 29 '18 at 18:03

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.