1

I want to change the reference text of a label before the next page. This is can be done with multiply defining the label, but I want to get rid of the warnings.
Because labels are written to the .aux file at the end of each page, this is possible by taking a command as reference text and changing the command before the end of the page. (I use custom reference text, with a preamble given by egreg in Retrieve link caption of hidden label) :

\documentclass{article}
\usepackage{etoolbox}
\usepackage{refcount}
\usepackage{hyperref}
\makeatletter
\newcommand{\customlabel}[2]{% custom reference text
  \csname phantomsection\endcsname
  \def\@currentlabel{%
    \bartodo{\unexpanded{#2}}%
  }%
  \label{#1}%
}
\protected\def\bartodo#1{#1}
\newcommand{\checklabel}[2]{% macro not used in this example, no need to read it
  \begingroup
  \let\bartodo\detokenize
  \begingroup\edef\x{\endgroup
    \noexpand\ifstrequal{\getrefnumber{#1}}{\detokenize{#2}}}%
  \x{\aftergroup\@firstoftwo}{\aftergroup\@secondoftwo}%
  \endgroup
}
\makeatother

\begin{document}

\def\mycommand{A}%
\customlabel{mylabel}{\mycommand}%
\getrefnumber{mylabel}
\def\mycommand{B}%
\getrefnumber{mylabel}

\end{document}

which, after 2 LaTeX runs, returns B B, as desired. (I use \def instead of \(re)newcommand because eventually I will put this somewhere inside, with \global.)

Now say I want to do this two times (in reality, a 1000 times), and the label name and command name depend on some other macro, say a counter, so that the two reference texts can be edited separately:

%preamble as before
\begin{document}
\newcounter{mycounter}

\expandafter\def\csname mycommand\themycounter\endcsname{A}%
\customlabel{mylabel\themycounter}{\csname mycommand\themycounter\endcsname}%
\getrefnumber{mylabel\themycounter}
\expandafter\def\csname mycommand\themycounter\endcsname{B}%
\getrefnumber{mylabel\themycounter}
%
\stepcounter{mycounter}%
% the same:
\expandafter\def\csname mycommand\themycounter\endcsname{C}%
\customlabel{mylabel\themycounter}{\csname mycommand\themycounter\endcsname}%
\getrefnumber{mylabel\themycounter}
\expandafter\def\csname mycommand\themycounter\endcsname{D}%
\getrefnumber{mylabel\themycounter}
\end{document}

This gives D D D D while I'd expect B B D D.

What happens is that when the labels are written to the .aux file, the updated value of \themycounter is used, and not the value at the point where the label was defined.

So I'd like to expand the second \themycounter in \customlabel{mylabel\themycounter}{\csname mycommand\themycounter\endcsname} without expanding \mycommand0 (because the latter has yet to be changeable).

1 Answer 1

1

So we fix the number of \themycounter at the moment of the label definition in a macro \ctr and then use that (expanded).

\begin{document}

\newcounter{mycounter}
\newcommand{\ccclabel}[1]{\customlabel{mylabel#1}{\csname mycommand#1\endcsname}}%

\expandafter\def\csname mycommand\themycounter\endcsname{A}%
\edef\ctr{\themycounter}\expandafter\ccclabel\expandafter{\ctr}
\getrefnumber{mylabel\themycounter}
\expandafter\def\csname mycommand\themycounter\endcsname{B}%
\getrefnumber{mylabel\themycounter}
%
\stepcounter{mycounter}%
% the same:
\expandafter\def\csname mycommand\themycounter\endcsname{C}%
\edef\ctr{\themycounter}\expandafter\ccclabel\expandafter{\ctr}
\getrefnumber{mylabel\themycounter}
\expandafter\def\csname mycommand\themycounter\endcsname{D}%
\getrefnumber{mylabel\themycounter}
\end{document}
3
  • Works like a charm! Dec 22, 2016 at 21:41
  • Also tested in my actual problem where I put all that in an environment, after adding the necessary \global's. Dec 22, 2016 at 21:58
  • If you shuffle the order a bit (put the \edef{\ctr} first), it is even a bit cleaner to replace all other \themycounter occurrences to \ctr. That needs one level less expansion. Dec 22, 2016 at 22:52

You must log in to answer this question.

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