5

I'm trying to create some TikZ commands that use key value options. Using the following link: How to create a command with key values? I was able to declare some commands, but now I'm stuck.

As a MWE consider:

\documentclass{article}
\usepackage{keyval}
\usepackage{tikz}
\usepackage{pgfkeys}

\makeatletter

% using keyval package
\define@key{cutkv}{label}{\def\cutkv@label{#1}}
\define@key{cutkv}{bend}{\def\cutkv@bend{#1}}
\setkeys{cutkv}{label={},bend={}}
\newcommand{\cutkv}[3][]{
  \begingroup
  \setkeys{cutkv}{#1}
  \draw[->] (#2) to[\cutkv@bend] node{\cutkv@label} (#3);
  \endgroup
}

% using pgfkeys package
\pgfkeys{
  /cutpgf/.is family, /cutpgf,
  default/.style =
  {label = ,
   bend = },
  label/.estore in = \cutpgf@label,
  bend/.estore in = \cutpgf@bend,
}
\newcommand{\cutpgf}[3][]{
  \pgfkeys{/cutpgf, default, #1}
  \draw[->] (#2) to[\cutpgf@bend] node{\cutpgf@label} (#3);
}
\makeatother

\begin{document}
\begin{tikzpicture}
  \cutkv[label=1]{0,0}{3,5}
  \cutkv[label=2,bend={bend right}]{1,4}{7,2}
  \cutkv[label=3,bend={bend right=10}]{6,0}{5,4}
\end{tikzpicture}

\begin{tikzpicture}
  \cutpgf[label=1]{0,0}{3,5}
  \cutpgf[label=2,bend={bend right}]{1,4}{7,2}
  \cutpgf[label=3,bend={bend right=10}]{6,0}{5,4}
\end{tikzpicture}
\end{document}

The first and the second call of the \cut command work fine, but in the third call the option bend right=10 is not passed correctly. At least, I don't understand the problem there.

I also tried the approach with pgfkeys, as mentioned in the first answer of the above post, but that didn't change anything.

edit: I added the version with pgfkeys to the MWE.

Any help is very much appreciated. Thanks.

  • 2
    The pgfkeys approach is different to keyval or xkeyval package, they do not co-operate, unfortunately. – user31729 Feb 26 '14 at 14:50
  • As I said, I also tried it with pgfkeys instead of keyval, but ended up with the same problem. – stephan boehme Feb 26 '14 at 14:53
  • I tried your approaches, they fail too. I believe, the problem is quite similar to the one I posed in a question some weeks ago, perhaps the solution Joseph gave there is the key (sic!) to the problem: <tex.stackexchange.com/questions/152020/…> -- in my point of view the source of the error lies in the double '=' characters, one as the outer key assignment, the other one as the inner key assignment of the pgfkeys – user31729 Feb 26 '14 at 15:43
  • I thought {...} would take care of that, but you might be right, adding a list of options like opt={thick,dashed} is not working neither. – stephan boehme Feb 26 '14 at 16:06
  • 1
    @Christian Yes, same issue but here \expandafter is tricky so I've used \edef in an answer – Joseph Wright Feb 26 '14 at 16:52
8

As suggested in a comment, this is nothing to do with the choice of keyval method but is instead due to the fact that keyval processors do not expand their input (in general). You need to force expansion, here probably easiest to do using \edef:

\documentclass{article}
\usepackage{keyval}
\usepackage{tikz}
\usepackage{pgfkeys}

\makeatletter

% using keyval package
\define@key{cutkv}{label}{\def\cutkv@label{#1}}
\define@key{cutkv}{bend}{\def\cutkv@bend{#1}}
\setkeys{cutkv}{label={},bend={}}
\newcommand{\cutkv}[3][]{
  \begingroup
  \setkeys{cutkv}{#1}
  \begingroup
    \edef\x
    {%
      \endgroup
      \noexpand\draw[->] (#2) to[\cutkv@bend] node{\cutkv@label} (#3);
    }\x
  \endgroup
}

% using pgfkeys package
\pgfkeys{
  /cutpgf/.is family, /cutpgf,
  default/.style =
  {label = ,
   bend = },
  label/.estore in = \cutpgf@label,
  bend/.estore in = \cutpgf@bend,
}
\newcommand{\cutpgf}[3][]{%
  \pgfkeys{/cutpgf, default, #1}%
  \begingroup
    \edef\x{%
      \endgroup
      \noexpand\draw[->] (#2) to[\cutpgf@bend] node{\cutpgf@label} (#3);
    }\x
}
\makeatother

\begin{document}
\begin{tikzpicture}
  \cutkv[label=1]{0,0}{3,5}
  \cutkv[label=2,bend={bend right}]{1,4}{7,2}
  \cutkv[label=3,bend={bend right=10}]{6,0}{5,4}
\end{tikzpicture}

\begin{tikzpicture}
  \cutpgf[label=1]{0,0}{3,5}
  \cutpgf[label=2,bend={bend right}]{1,4}{7,2}
  \cutpgf[label=3,bend={bend right=10}]{6,0}{5,4}
\end{tikzpicture}
\end{document}

In both cases, the idea is that the \draw line needs to have the full expansion of your variables: by using \edef I don't have to worry about carefully counting tokens for \expandafter.

  • Thank you very much. I tried your solution and extended it a bit to my needs and it works perfectly. – stephan boehme Feb 27 '14 at 9:21
  • Now, I found some unwanted side effects with \noexpand. If I change the drawcommand to \noexpand\draw[->] (#2) to[\cutkv@bend] node{\tiny \cutkv@label} (#3); I get errors, I can't solve. – stephan boehme Feb 27 '14 at 15:07
  • @stephanboehme Expansion is tricky: most LaTeX2e commands cannot be safely used inside \edef. Here, you'll need a \noexpand before \tiny to make it work. – Joseph Wright Feb 27 '14 at 16:22
  • Thanks again, it's working nicely now. And even with not completely understanding the expansion-\edef-\noexpand-issue, I get a feeling for it :) – stephan boehme Feb 27 '14 at 16:54

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.