3

Why does the following code give me this error message?

Error

ERROR: Undefined control sequence.

--- TeX said --- \pgfmath@dimen@ ...men@@ #1=0.0pt\relax \pgfmath@

l.28 \draw (\getWickersonLeft{c},0) -- (\getWickersonRight{c},5);

Code

\documentclass{article}

\usepackage{tikz}

\pgfkeys{/wickersons/.cd,
  execute style/.style={#1},                           
  execute macro/.style={execute style/.expand once=#1}, 
  left/.code={\gdef\wickersonsleft{#1}},
  right/.code={\gdef\wickersonsright{#1}}
}

\def\getWickersonLeft#1{\csname wickerson#1left\endcsname}
\def\getWickersonRight#1{\csname wickerson#1right\endcsname}

\newcommand*\defWickersonMacros[3]{%
  \expandafter\edef\csname wickerson#1left\endcsname{#2}
  \expandafter\edef\csname wickerson#1right\endcsname{#3}
}

\begin{document}

\begin{tikzpicture}[x=1mm,y=-1mm]%
  \foreach \x/\xvalue in {c/{left=67,right=77}} { 
    \pgfkeys{/wickersons/.cd, execute macro=\xvalue} 
    \expandafter\defWickersonMacros{c}{\wickersonsleft}{\wickersonsright}
  }
  \draw (\getWickersonLeft{c},0) -- (\getWickersonRight{c},5);
\end{tikzpicture}

\end{document}
  • 1
    \defWickersonMacros needs \xdefs here … (by the way, \csname will expand everything it will encounter so you don't need to expand \x for it which I guess the lonely \expandafter in the loop is a remainder of). – Qrrbrbirlbel May 14 '13 at 20:01
  • 1
    also \expandafter\defWickersonMacros{ expands { which isn't expandable. – David Carlisle May 14 '13 at 20:08
3

I would instead use the \pgfkeysvalueof way of defining things. This is a very convoluted way of avoiding the real power of pgfkeys because instead of keys you are using dummy macros. Consider sending all your options to some keys belonging to a family.

Here the problem is that the argument of a macro is used inside another definition so # chars should be doubled.

\documentclass{article}

\usepackage{tikz}

\pgfkeys{/wickersons/.cd,
  execute style/.style={#1},                           
  execute macro/.style={execute style/.expand once=#1}, 
  left/.code={\xdef\wickersonsleft{#1}},
  right/.code={\xdef\wickersonsright{#1}}
}

\edef\getWickersonLeft#1{\csname wickerson#1left\endcsname}
\edef\getWickersonRight#1{\csname wickerson#1right\endcsname}

\newcommand*\defWickersonMacros[3]{%
  \expandafter\xdef\csname wickerson##1left\endcsname{#2}% Double ##
  \expandafter\xdef\csname wickerson##1right\endcsname{#3}% Double ##
}

\begin{document}

\begin{tikzpicture}[x=1mm,y=-1mm]%
  \foreach \x/\xvalue in {c/{left=67,right=77}} { 
    \pgfkeys{/wickersons/.cd, execute macro=\xvalue} 
    \defWickersonMacros{c}{\wickersonsleft}{\wickersonsright}
  }

\draw (\getWickersonLeft{c},0) -- (\getWickersonRight{c},5);
\end{tikzpicture}

\end{document}

The output :)

enter image description here

  • 1
    (Actually, he is re-creating PGF keys. The value of the key /wickersons/left would be stored in \pgfk@/wickersons/left/name and \pgfkeysvalueof doesn’t make anything else as \csname-ing that.) – Qrrbrbirlbel May 14 '13 at 23:30
  • Thank you very much for this @percusse. I don't understand why I need ##1 though. Why doesn't the same logic apply to my #2 and #3? I would say that none of them are inside the other definition; they are just used to create that other definition. – John Wickerson May 15 '13 at 13:51
  • @JohnWickerson There you go :) tex.stackexchange.com/questions/42463/… – percusse May 16 '13 at 7:41
  • Thanks @percusse, but I still think the double ## is wrong. Parameter 1 is not an argument to the command being defined. It's used to construct the name of the command being defined. For instance, \defWickersonMacros{percusse}{foo}{bar} should expand to \xdef\wickersonpercusseleft{foo}. – John Wickerson May 16 '13 at 8:49
  • @JohnWickerson When ##1 is expanded it becomes #1. – percusse May 16 '13 at 8:52
3

After percusse has answered your question, I want to give you an alternative on how to process your list with the abilities of PGF keys and TikZ.

Some of the code is inspired by another recent question of yours.

Code

\documentclass[tikz]{standalone}
\makeatletter
\pgfqkeys{/wickersons}{
  add path/.code args={#1}{%
    \begingroup% a group so the initial values don't need to be repeated but can be set in a scope above
      \pgfqkeys{/wickersons/path vars}{#1}% set only the keys that are given in '#1', other wise the current value will be used (probably the .initial one)
      % now expand everything (but the label which may contain unexpandable stuff, we only want to expand that once)
      \edef\pgf@tempa{{\pgfkeysvalueof{/wickersons/path vars/name}/.style={insert path={%
            (\pgfkeysvalueof{/wickersons/path vars/left},0) -- node [every wickersons label/.try] {\unexpanded\expandafter{\wickersons@pathvars@label}}
            (\pgfkeysvalueof{/wickersons/path vars/right},5)}}}}%
      % and get it out of this group
      \pgfmath@smuggleone\pgf@tempa
    \endgroup
    % the 'path vars' now contain all there values before 'add path' was used
    %
    % have you seen the extra pair of braces in \pgf@tempa? Those where necessary, otherwise I had to use
    % \expandafter\tikzset\expandafter{\pgf@tempa}
    % here
    \expandafter\tikzset\pgf@tempa
  },
  path vars/.cd,
   name/.initial=path,% if 'add path' has been used without the 'name' key the style would have been named 'path'
   left/.initial=0,   % if 'add path' has been used without the 'left' key the left point would have started at (0,0)
   right/.initial=0,  % ...
   label/.store in=\wickersons@pathvars@label,% or toks
   label=%            % ...
}
\makeatother
\begin{document}
\begin{tikzpicture}[
 x=1mm,
 y=-1mm,
 ->,
 thick,
 every wickersons label/.style={midway, above, sloped},
 /wickersons/add path/.list={%
   {name=foo, left= 2, right=23, label=horse},%
   {name=bar, left=25, right=29, label=sheep},%
   {name=baz, left=31,           label=\textbf{zebra}}%
 }]

  \draw [every wickersons label/.append style={pos=.2}] [foo];
  \draw [bar];
  \draw [every wickersons label/.append style={pos=.4}] [baz]; % uses right=0
\end{tikzpicture}
\end{document}

Output

enter image description here

  • All this expanding/unexpanding makes my head hurt! Thank you for your suggestions @Qrrbrbirlbel. I have posted another question here, where I clarify my use-case a bit more, which should make it easier to discuss the best way for me to do things. – John Wickerson May 15 '13 at 13:54
  • 1
    Why this is community wiki, by the way? – John Wickerson May 15 '13 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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