4

What I wish to do is create a (hidden) label in which some text is stored, and retrieve the text by referencing to it, without getting an actual link. For example:

\customlabel{refname}{some text} \getcaption{refname}

should give

some text

but some text should not be clickable, it simply has to be text. In fact I need it in something like \ifstrequals{\getcaption{refname}}{foo}{\dothis}{\dothat} (provided etoolbox) so \getcaption should really return pure text.

In Defining custom labels it is shown how to define a hidden label with a custom link caption provided hyperref is not loaded: (see Ian Thompson's answer)

\documentclass{article}
\makeatletter
\newcommand{\customlabel}[2]{%
   \protected@write \@auxout {}{\string \newlabel {#1}{{#2}{}}}}
\makeatother
\begin{document}
\customlabel{refname}{some text} \ref{refname}
\end{document} 

which outputs some text, as desired.
But with hyperref loaded this doesn't work. Henrik Bøgelund Lavstsen suggests

\documentclass{article}
\usepackage{hyperref}
\makeatletter
\newcommand{\customlabel}[2]{%
   \protected@write \@auxout {}{\string \newlabel {#1}{{#2}{\thepage}{#2}{#1}{}} }%
   \hypertarget{#1}{#2}}
\makeatother
\begin{document}
\customlabel{refname}{some text} \ref{refname}
\end{document} 

but this gives some text some text, i.e. the label is not 'hidden'. And of course \ref (playing the role of \getcaption) does not simply return some text, meaning that \ifstrequal{\ref{refname}}{some text}{yes}{no} gives no.

If the caption is just a number one can use \getrefnumber (from refcount) as \getcaption-command, but I am not aware of an alternative of \getrefnumber where the stored text is an arbitrary string.

Note: The reason why I want to use labels (or more generally, store the text in an external file) is that the stored text has to be accessible in the document before the position where it is stored. I.e. the text has to be stored in an external file and retrieved in a next LaTeX run. I do not want to create one file for each \customlabel call, since I have to use this a 1000 times and do not want 1000 auxiliary files. That's why I think using labels is the best option.

Bart Michels
  • 1,298
  • 2
  • 13
  • 24

3 Answers3

4

The following example uses the zref referencing system. It defines a new property custom, which is set to the desired contents. \customlabel then stores the contents in the .aux file. \customref extracts the value in an expandable way, thus it can be used in \ifstrequals. An expandable version cannot make warnings, if the reference is undefined, thus this part is put into macro \customused, which notifies LaTeX, that the reference is actually used. If the reference is undefined a warning is printed.

\documentclass{article}
\usepackage{zref-base}
\makeatletter
\zref@newprop{custom}{}
\newcommand*{\customlabel}[2]{%
  \@bsphack
  \zref@setcurrent{custom}{#2}%
  \zref@labelbyprops{#1}{custom}%
  \@esphack
}
\newcommand*{\customref}[1]{%
  \zref@extractdefault{#1}{custom}{}% last argument is default
}
\newcommand*{\customused}[1]{%
  \zref@refused{#1}%
}
\makeatletter

\begin{document}
\customlabel{refname}{some text} \customref{refname}\customused{refname}
\end{document}
Heiko Oberdiek
  • 271,626
  • What exactly is \customused for? Is it necessary for the code to work or is it an extra functionality? In fact \ifstrequal{\customref{refname}}{some text}{yes}{no} returns no... I'm very interested if this can be fixed because this would not only allow to compare the stored text (as in egreg's answer) but in fact do anything with it. – Bart Michels Feb 05 '15 at 11:17
  • @barto \customused is explained in the answer, see the last two sentences. If you mean \ifstrequal from package etoolbox, then you have to expand \customref before, of course. For example, \expandafter\expandafter\expandafter\ifstrequal\expandafter\expandafter\expandafter{\customref... – Heiko Oberdiek Feb 05 '15 at 11:24
3

Why not simply using the \ref-\label mechanism?

\documentclass{article}
\usepackage{hyperref}
\makeatletter
\newcommand{\customlabel}[2]{%
  \phantomsection
  \def\@currentlabel{\unexpanded{#2}}\label{#1}%
}
\makeatother
\begin{document}
\customlabel{refname}{som\'e text} \ref{refname}
\end{document}

The accent is just for showing that it doesn't make problems (because of \unexpanded).

If you don't want a link, then use \ref* instead of \ref.


A version that allows checking the saved text:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{refcount}
\usepackage{hyperref}
\makeatletter
\newcommand{\customlabel}[2]{%
  \csname phantomsection\endcsname
  \def\@currentlabel{%
    \bartodo{\unexpanded{#2}}%
  }%
  \label{#1}%
}
\protected\def\bartodo#1{#1}
\newcommand{\checklabel}[2]{%
  \begingroup
  \let\bartodo\detokenize
  \begingroup\edef\x{\endgroup
    \noexpand\ifstrequal{\getrefnumber{#1}}{\detokenize{#2}}}%
  \x{\aftergroup\@firstoftwo}{\aftergroup\@secondoftwo}%
  \endgroup
}
\makeatother


\begin{document}

\customlabel{refname}{som\'e text} \ref*{refname}

\customlabel{newname}{text}

\checklabel{newname}{text}{YES}{NO}

\checklabel{refname}{som\'e text}{YES}{NO}

\checklabel{refname}{some text}{YES}{NO}

\end{document}

enter image description here

If the saved text is just a number for a later numeric test, a much simpler approach can be used:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{refcount}
\usepackage{hyperref}

\makeatletter
\newcommand{\customlabel}[2]{%
  \def\@currentlabel{#2}%
  \label{#1}%
}
\newcommand{\checklabel}[4]{%
  \begingroup\edef\x{\endgroup
    \noexpand\ifnumequal{\getrefnumber{#1}}{#2}}%
  \x{#3}{#4}%
}
\makeatother


\begin{document}

\customlabel{refname}{22}

\customlabel{newname}{42}

\checklabel{newname}{42}{YES}{NO}

\checklabel{refname}{22}{YES}{NO}

\checklabel{refname}{42}{YES}{NO}

\end{document}

enter image description here

egreg
  • 1,121,712
  • Works fine, but \ifstrequal{\ref*{refname}}{text}{yes}{no} gives no even if I used \customlabel{refname}{text}. It seems like \ref* is still returning something else than just text. If the text to be stored is just a number one could solve this issue by using \ifnumequal{\getrefnumber{refname}}{22}{yes}{no} (in fact using numbers suffices for my purpose) but it would be interesting to have a method to extract a string too. – Bart Michels Feb 05 '15 at 10:14
  • @barto Done. ;-) – egreg Feb 05 '15 at 10:54
  • Perfect! Works also when I test the labels before the position they were created. – Bart Michels Feb 05 '15 at 10:59
2

Assuming that you're using e-TeX, you can tap into \pdfstrcmp for examining strings expandably:

This is some regular text. The stored caption is some text.
Do: that
Do: this

\documentclass{article}
\newcommand{\customlabel}[1]{\expandafter\gdef\csname#1\endcsname}
\newcommand{\getcaption}[1]{\expandafter\csname #1\endcsname}
\newcommand{\ifstrequal}[4]{% \ifstrequal{<stringA>}{<stringB>}{<true>}{<false>}
  \ifnum\pdfstrcmp{#1}{#2}=0
    #3% #1 = #2
  \else
    #4% #1 != #2
  \fi}
\begin{document}
\customlabel{refname}{some text}% Store some text in 'refname'

This is some regular text. The stored caption is \getcaption{refname}.

Do: \ifstrequal{\getcaption{refname}}{foo}{this}{that}

Do: \ifstrequal{\getcaption{refname}}{some text}{this}{that}

\end{document} 
Werner
  • 603,163