8

I try to write a command that accepts options, using pgfkeys. Unknown keys are collected in a style, that I try to use as global options for a tikzpicture environement. A minimal example would be:

\documentclass{article}
\usepackage{tikz}

\newif\ifsquare

\pgfqkeys{/test}{%
 square/.is if=square,
 square/.default=true,
% collect unknown keys in style 'remainingkeys':
 .unknown/.code={%
  \let\currname\pgfkeyscurrentname%
  \let\currval\pgfkeyscurrentvalue%
  \ifx#1\pgfkeysnovalue%
   \pgfqkeys{/tikz}{remainingkeys/.append style={\currname}}%
  \else%
   \pgfqkeys{/tikz}{remainingkeys/.append style={\currname=\currval}}%
  \fi%
 }%
}

\newcommand\myfigure[1][]{
% initialize:
 \pgfqkeys{/tikz}{remainingkeys/.style={}}
 \pgfqkeys{/test}{square}
% set user keys:
 \pgfqkeys{/test}{#1}
 \begin{tikzpicture}[/tikz/remainingkeys]
  \ifsquare
   \fill (0,0)rectangle(1,1);
  \else
   \fill (0,0)rectangle(1.2,.8);
  \fi
 \end{tikzpicture}
}

\begin{document}

 \myfigure[square,rotate=45]                % rotated 45 degs; ok
 \myfigure[square,fill=red]                 % red; ok
 \myfigure[square,rotate=45,fill=red]       % red, but doesn't rotate
 \myfigure[square=false]                    % not square
 \myfigure[square=false,fill=red,rotate=45] % not square, not red and rotated 90 degs!

\end{document} 

The command \myfigure simply draws a square or rectangle, depending on the value of the 'square'-key. This key is handled correctly. All other options are handled by the .unknown/.code handler and collected into the style 'remainingkeys', which eventually is passed to \begin{tikzpicture}. The first call of \myfigure indeed draws a square, and rotates it, but the third call doesn't! Somehow not all unknown keys are stored in 'remainingkeys'. In the fifth call even the rotation angle isn't right.

I tried a lot of things, but this is the best that I can come up with, at least without producing any TeX-errors. I'm doing something seriously wrong, but what? I'm dead in the water...

6

You need to expand the \currname and \currval values first. Otherwise you simply storing this macros which definitions will change. Therefore you loose all but the last option, which is repeated several times like seen in the double rotation in your example.

\documentclass{article}
\usepackage{tikz}

\newif\ifsquare

\pgfqkeys{/test}{%
 square/.is if=square,
 square/.default=true,
% collect unknown keys in style 'remainingkeys':
 .unknown/.code={%
  \let\currname\pgfkeyscurrentname%
  \let\currval\pgfkeyscurrentvalue%
  \ifx#1\pgfkeysnovalue%
   \pgfqkeys{/tikz}{remainingkeys/.append style/.expand once={\currname}}%
  \else%
   \pgfqkeys{/tikz}{remainingkeys/.append style/.expand twice={\expandafter\currname\expandafter=\currval}}%
  \fi%
 }%
}

\newcommand\myfigure[1][]{
% initialize:
 \pgfqkeys{/tikz}{remainingkeys/.style={}}
 \pgfqkeys{/test}{square}
% set user keys:
 \pgfqkeys{/test}{#1}
 \begin{tikzpicture}[/tikz/remainingkeys]
  \ifsquare
   \fill (0,0)rectangle(1,1);
  \else
   \fill (0,0)rectangle(1.2,.8);
  \fi
 \end{tikzpicture}
}

\begin{document}

 \myfigure[square,rotate=45]                % rotated 45 degs; ok
 \myfigure[square,fill=red]                 % red; ok
 \myfigure[square,rotate=45,fill=red]       % red, but doesn't rotate
 \myfigure[square=false]                    % not square
 \myfigure[square=false,fill=red,rotate=45] % not square, not red and rotated 90 degs!

\end{document} 

Result

| improve this answer | |
  • Aha, it's the \let's that are causing this. I changed my .unknown/.code into this: .unknown/.code={% \ifx#1\pgfkeysnovalue% \expandafter\appendtostyle\expandafter{\pgfkeyscurrentname}% \else% \expandafter\appendtostyle\expandafter{\pgfkeyscurrentname=#1}% \fi% }% where \appendostyle is defined as follows: \def\appendtostyle#1{\pgfqkeys{/tikz}{remainingkeys/.append style={#1}}} This works. Many thanks! – Mike Boldy Jul 13 '11 at 10:22
  • Your solution is better of course: no need to define an extra macro, that could get lost in the mess that my code usually is... Thank you, Martin – Mike Boldy Jul 13 '11 at 10:34
  • @Mike: storing the \pgfkeyscurrentname etc. macros in an own macro using \let is actually a good thing, if you can't expand them directly. They might be overwritten by TiKZ before you use them again. If this answer helped you please consider accepting it as the official solution by clicking the tick mark to the upper left of it. Thanks. – Martin Scharrer Jul 13 '11 at 10:56

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.