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.

1 Answers1

9

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.

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • 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 09: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