5

Recently, in choose from a list with xstring, Geoff was asking about defining the command \variation that does the following:

\variation{1}{aaa;bbb;ccc} ----> aaa
\variation{2}{aaa;bbb;ccc} ----> bbb
\variation{3}{aaa;bbb;ccc} ----> ccc

There are a number of nice answers on this question. However, I have found that all of them have the same disadvantage: when I am trying to use the result of \variation in \ref or \getrefnumber from the package refcount, I get an error message.

To be more specific, consider the not-working example based on Heiko Oberdiek solution,

\documentclass{article}
\usepackage{xstring}

 \newcommand*{\variation}[2]{%
  \edef\variationNext{%
    \noexpand\StrBetween[%
      \the\numexpr(#1)\relax,%
      \the\numexpr(#1)+1\relax
    ]%
  }%
  \variationNext{;#2;}{;}{;}\relax
}


\begin{document}

\begin{equation}
2+2=4 \label{aaa}
\end{equation}

\begin{equation}
 3+3=6 \label{bbb}
\end{equation}

I can refer to these equations as equation~\ref{aaa} and
equation~\ref{bbb}.

Now I have the string ``aaa;bbb''. If I refer to these equations as
equation~\ref{\variation{1}{aaa;bbb}} and
equation~\ref{\variation{2}{aaa;bbb}}, I get an error message.

\end{document}

I have the same error message with all other proposed solutions. Is it possible to redefine the command \variation in such a way to it works correctly with \ref and with \getrefnumber?

0

2 Answers 2

4

Package xstring's \StrBetween knows a final optional argument, that expects a command token to store the result. Thus \variation can be given an optional argument (at the beginning to avoid dropping spaces at the end). With optional argument the result is stored in the macro given there instead.

\documentclass{article}
\usepackage{xstring}

\newcommand*{\variation}[3][]{%
  \edef\variationNext{%
    \noexpand\StrBetween[%
      \the\numexpr(#2)\relax,%
      \the\numexpr(#2)+1\relax
    ]%
  }%
  \variationNext{;#3;}{;}{;}[#1]\relax
}
\newcommand*{\variationref}[2]{%
  \variation[\tmp]{#1}{#2}\ref{\tmp}%
}

\begin{document}

\begin{equation} 
2+2=4 \label{aaa}
\end{equation}

\begin{equation}  
 3+3=6 \label{bbb}
\end{equation}

I can refer to these equations as equation~\ref{aaa} and
equation~\ref{bbb}.

Now I have the string ``aaa;bbb''. If I refer to these equations as
equation~\variation[\tmp]{1}{aaa;bbb}\ref{\tmp} and
equation~\variationref{2}{aaa;bbb}.                

\end{document}

Result

2
  • Thank you. It seems that it works correctly also with replacing \ref by \getrefnumber.
    – Andrew
    Oct 22, 2012 at 8:22
  • Your solution is really nice but unfortunately it does not work for my final task even with \getrefnumber. I have formulated this task in my new question in tex.stackexchange.com/questions/78653/…. I would be very appreciate if you look it.
    – Andrew
    Oct 22, 2012 at 12:01
3

The problem with \ref is that it needs its argument to be a string, not the set of instructions to produce that string.

The best is to use a different command for such references, for instance

\varref{1}{aaa;bbb}

An almost straightforward modification of my answer does what you want:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\NewDocumentCommand{\variation}{ s O{;} m m }
 {
  \IfBooleanTF{#1}
   {
    \geoff_variation_check:nnn { #2 } { #3 } { #4 }
   }
   {
    \geoff_variation_nocheck:nnn { #2 } { #3 } { #4 }
   }
   \tl_use:N \l__geoff_item_tl
 }
\NewDocumentCommand{\varref}{s O{;} m m }
 {
  \IfBooleanTF{#1}
   {
    \geoff_variation_check:nnn { #2 } { #3 } { #4 }
   }
   {
    \geoff_variation_nocheck:nnn { #2 } { #3 } { #4 }
   }
   \exp_args:NV \ref \l__geoff_item_tl
 }

\msg_new:nnn { variation }
 { index~out~of~bounds }
 { You~have~requested~an~item~that~doesn't~exist }
\seq_new:N \l__geoff_item_list_seq
\tl_new:N \l__geoff_item_tl

\cs_new_protected:Npn \geoff_variation_nocheck:nnn #1 #2 #3
 {
  \seq_set_split:Nnn \l__geoff_item_list_seq { #1 } { #3 }
  \tl_set:Nx \l__geoff_item_tl { \seq_item:Nn \l__geoff_item_list_seq { #2 } }
 }

\cs_new_protected:Npn \geoff_variation_check:nnn #1 #2 #3
 {
  \seq_set_split:Nnn \l__geoff_item_list_seq { #1 } { #3 }
  \int_compare:nTF { #2 > \seq_count:N \l__geoff_item_list_seq }
   {
    \msg_warning:nn { variation }{ index~out~of~bounds }
    \tl_set:Nn \l__geoff_item_tl { --inexistentitem-- }
   }
   {
    \tl_set:Nx \l__geoff_item_tl { \seq_item:Nn \l__geoff_item_list_seq { #2 } }
   }
 }

\ExplSyntaxOff

\begin{document}

\variation{3}{aaa;bbb;ccc;ddd;eee}

\variation[,]{3}{aaa,bbb,ccc,ddd,eee}

\variation{1}{aaa}

\variation{2}{aaa}

\variation*{2}{aaa}

\begin{equation}
2+2=4 \label{aaa}
\end{equation}

\begin{equation}
 3+3=6 \label{bbb}
\end{equation}

I can refer to these equations as equation~\ref{aaa} and
equation~\ref{bbb}.

If I refer to these equations as equation~\varref{1}{aaa;bbb} and
equation~\varref{2}{aaa;bbb}, I get correct numbers.

\end{document}

I left the original \variation command, though it appears not to be really needed.

The difference is that now \geoff_variation_nocheck:nnn stores the result in a token list variable and \varref calls it (or the check variant) and then does

\exp_args:NV \ref \l__geoff_item_tl

The behavior of \varref and \varref* are the same if there is no overflow; with \varref*{3}{aaa;bbb} you'd get a warning and \ref{--inexistentitem--} would be produced; with \varref{3}{aaa;bbb} you'd simply get \ref{}.

3
  • Thank you very much. It works. For me it is also important to \varref would work as suggested by you in tex.stackexchange.com/questions/73349/… command \getrefnumber. I will check it tomorrow.
    – Andrew
    Oct 21, 2012 at 21:25
  • @Andrew No, it wouldn't work. It can be done quite easily if you accept a syntax such as \vargetrefnumber{2}{{aaa}{bbb}}, otherwise a substantial change is needed. But it mostly depends on your real needs.
    – egreg
    Oct 21, 2012 at 21:38
  • I was trying to play a bit with your code. There is a strange problem but most probably it is only related to my system. Yesterday evening I was compiling your code with a Windows PC (MiKTeX) and everything was working. Today I am doing the same with Linux and I am getting the error message about undefined control sequence \variation... I will try to fix the problem later. At the moment I have found that the solution of Heiko Oberdiek works even with \getrefnumber.
    – Andrew
    Oct 22, 2012 at 8:20

You must log in to answer this question.

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