Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm using a macro that uses \StrBetween from xstring

It seems to be working great.

However, when I try to use a value that it returns as a coordinate in a tikz picture, I get a confusing error.

Consider this snippet:

\documentclass[letterpaper,12pt]{article}

\usepackage{xstring}
\usepackage{tikz}

% http://tex.stackexchange.com/a/21566/3068
\newcommand*\GetListMember[2]{\StrBetween[#2,\number\numexpr#2+1]{,#1,},,\par}%

\begin{document}
\pagestyle{empty}
\begin{tikzpicture}
\def\A{\GetListMember{1,2,3}{1}}

% This makes me think the value of \A is 1
\node [draw] at (1,0) {\A};

% Uncommenting the following gives an error that is very confusing to me
% \node [draw] at (\A,1) {\A};
\end{tikzpicture}
\end{document}

It works, but if I uncomment the last commented line, I get this error:

! Undefined control sequence.
<argument> \@@cls 

l.18 \node [draw] at (\A,1)
                            {\A};

I think I need to convert the value of \A to a number, or something, but I don't know how.

p.s. This happens a lot, where an error message contains text that's not in my input file. (In this case \@@cls) Is there a way for me to see the intermediate forms? I feel like I'm debugging Lisp code with no macroexpand-1.

Thanks, as ever. (:

share|improve this question

2 Answers 2

up vote 8 down vote accepted

You haven't defined \A to be 1 you've defined it to be \GetListMember{1,2,3}{1} (you get 1 when \A is expanded). TikZ has no idea what to do with \GetListMember when it encounters it in a coordinate. In this case you can use \pgfmathtruncatemacro. To see the difference consider the following (for clarity I've used \A and \B):

\documentclass{article}
\usepackage{xstring}
\usepackage{tikz}

\begin{document}
\def\A{\GetListMember{1,2,3}{1}}
\show\A
\pgfmathtruncatemacro\B{{1,2,3}[0]}
\show\B
\end{document}

When you look at the log file you should see:

> \A=macro:
->\GetListMember {1,2,3}{1}.
l.7 \show\A
> \B=macro:
->1.
l.9 \show\B 
share|improve this answer
    
Thanks for this answer, I always learn so much when I post a question here. I have a vague memory of learning about \show in the past, but it didn't occur to me that it might be useful for this type of debugging. –  Harold Mar 8 '13 at 13:39

Your problem is expansion. The line

\def\A{\GetListMember{1,2,3}{1}}

defines \A to be \GetListMember{1,2,3}{1}, which is clearly not a number. TeX tries to expand this as part of the internals of \node, but \StrBetween is not 'expandable. You can see that if you try to force expansion using \edef:

\edef\A{\GetListMember{1,2,3}{1}}

which will also give the same error.

What you need is an expandable comma-list item selector. The xstring package does not provide one, but expl3 does:

\documentclass[letterpaper,12pt]{article}

\usepackage{expl3}
\usepackage{tikz}

\begin{document}
\pagestyle{empty}
\begin{tikzpicture}
\ExplSyntaxOn
\edef\A{\clist_item:nn{1,2,3}{1}}
\ExplSyntaxOff

\node [draw] at (1,0) {\A};
\node [draw] at (\A,1) {\A};
\end{tikzpicture}
\end{document}

Probably you'll want to wrap up \clist_item:nn in a user-level macro.

share|improve this answer
    
I appreciate this answer, I was unaware of expl3 –  Harold Mar 8 '13 at 13:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.