7

I have to get value of a dynamical macro where the index is given by \ref{mymarker}. Is it possible to do? I define a set of macros with a predefined counter 'mycounter' as

\expandafter\newcommand\csname mymacro\the\value{mycounter} \endcsname{mytext} 

where 'mytext' depends on the value of counter.

After that I define a new command

\newcommand{\anotherref}[1]{\csname mymacro\ref{#1} \endcsname}

the code like

\anotherref{mymarker}

does not work. The idea is that this command should give not the counter value related to 'mymarker', like \ref{mymarker} gives, but rather the text 'mytext', which is also related to 'mymarker'.

4
  • 2
    Look at the package refcount and \getrefnumber
    – egreg
    Commented Sep 20, 2012 at 12:10
  • What should happen if the reference mymarker is undefined? How should \anotherref behave, if the macro to be used is not defined? Also you have a space at the end of the macro name (on purpose or accidentally). Commented Sep 20, 2012 at 12:49
  • Thank you very much for the answers and comments! Everything works with the package refcount.
    – Andrew
    Commented Sep 20, 2012 at 13:41
  • 1
    Since people have found the question interesting they will want to know the answer. Why not post yours, as a complete MWE? Commented Sep 20, 2012 at 14:45

2 Answers 2

5

The following example shows an implementation using package refcount.

  • \mymacrodef defines \mymacro<num> using the current counter value of mycounter for <num>. The definition starts with \newcommand{\mymacro<num>}.

  • \mymacroget{<num>} calls \mymacro<num>.

  • \mymacroundefined is used if \mymacroget could not find \mymacro<num>.

  • \mymacroref{<label>} extracts the number from the specified label and calls \mymacroget with the number. If the reference <label> is undefined, \mymacroundefined is used. The label name may contain babel shorthand characters.

  • \mymacrorefexp{<label>} behaves like \mymacroref with the following differences:

    • The macro can be used in expandable context, because it is expandable in exact two expansion steps, see example below.

    • Babel shorthand characters are not supported, because this requires an assignment that breaks expandability.

    • If the reference is undefined, then the user is not given a warning, because that breaks expandability. If possible, use \refused{<label>} outside the expandable context to get the warning in case of an undefined reference.

The example:

\documentclass{article}
\usepackage{refcount}[2010/12/01]
\usepackage{ltxcmds}

\newcounter{mycounter}

\makeatletter

% \mymacrodef defines a macro \mymacro<number> that gets
% the number from the current counter setting for `myounter`.
\newcommand*{\mymacrodef}{%
  \expandafter\newcommand
  \csname mymacro\the\value{mycounter}\endcsname
}

% \mymacroget{<number>} calls \mymacro<number>
% if the macro exists and \mymacroundefined otherwise.
% It is expandable in two expansion steps.
\newcommand*{\mymacroget}[1]{%
  \romannumeral-`\x
  \ltx@ifundefined{mymacro\number#1}{%
    \ltx@space
    \mymacroundefined
  }{%
    \expandafter\ltx@space
    \csname mymacro\number#1\endcsname
  }%
}   

\newcommand*{\mymacroundefined}{\textbf{??}}

% \mymacroref{<label>} is not expandable and gets the number
% from the reference <label>
\newcommand*{\mymacroref}[1]{%
  \refused{#1}%
  \IfRefUndefinedBabel{#1}{%
    \mymacroundefined
  }{%
    % with babel shorthand support
    \begingroup
      \csname @safe@actives@true\endcsname
    \expandafter\endgroup
    \expandafter\mymacroget\expandafter{%
      \number\getrefnumber{#1}%
    }%
  }%
}

\newcommand*{\mymacrorefexp}[1]{%
  \romannumeral-`\x
  \IfRefUndefinedExpandable{#1}{%
    \ltx@space
    \mymacroundefined
  }{%
    \expandafter\expandafter\expandafter\ltx@space
    \mymacroget{\getrefnumber{#1}}%
  }%
}   
\makeatother

\begin{document}

\mymacrodef{Text zero.}
\refstepcounter{mycounter}
\mymacrodef{Text one.}
\label{mylabel}
\refstepcounter{mycounter}
\mymacrodef{Text one again.}

\begin{itemize}
\item[0:] \mymacroget{0}
\item[1:] \mymacroget{1}
\item[42:] \mymacroget{42}
\item[mylabel:] \mymacroref{mylabel}
\item[undef:] \mymacroref{undef}

% Expandable stuff. Define macro \my that has the meaning
% of the macro \mymacro<number>, where <number> is stored
% in label `mylabel':

\refused{mylabel}
\expandafter\expandafter\expandafter\let
\expandafter\expandafter\expandafter\my 
\mymacrorefexp{mylabel}

\item[\texttt{\string\my}:] \texttt{\meaning\my}

\end{itemize}

\end{document}

Test output

1

Here is my toy example. I hope this can be useful for somebody. The problem is to define the command \editor and to use it for forming the title page. Each editor has his own original number and represents a certain country. In the main text names of editors, their numbers and the corresponding countries are also mentioned. The suggestion to use the package refcount allows me to resolve this problem in the following way:

\documentclass{article}
\usepackage{refcount}

\makeatletter

% Definition of the command \editor{name}{country}
\newcounter{editor@index}
\newcommand\editor[2]{\refstepcounter{editor@index}
\expandafter\newcommand\csname
 @editor@name\the\value{editor@index} \endcsname{#1}
\expandafter\newcommand\csname
 @editor@country\the\value{editor@index} \endcsname{#2}%
}

% Definition of the commands \nameref{marker} and \countryref{marker}
\newcommand{\nameref}[1]{\csname
@editor@name\getrefnumber{#1} \endcsname}
\newcommand{\countryref}[1]{\csname
@editor@country\getrefnumber{#1} \endcsname}

\makeatother

\begin{document}

% With the command \editor one can define the list of editors.
% It can also be used in the redefinition of \maketitle with 
% accessing to the name with 
% \csname @editor@name\the\value{editor@index} \endcsname and to the
% country with \csname @editor@country\getrefnumber{#1} \endcsname.
% One can also mark the editors with \label.

\editor{John Smith}{UK}\label{JS}
\editor{John Doe}{USA}\label{JD}

% Now one can change the order of \editor and always have the correct 
% referencing.

\nameref{JS} from~\countryref{JS} is referred as editor~\ref{JS}.
\nameref{JD} from~\countryref{JD} is referred as editor~\ref{JD}. 

\end{document}

Thank you very much again for the comments and suggestions!

You must log in to answer this question.

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