# Problem between pgfkeys, tikz and personal macro

The following minimal working example shows the problem. The mainmacro is an example of what I need; here I want to use my keys and keys from tikz (like draw,color,shape). The result is fine only if I use shape = circle. circle is not enough. Idem if I want the color red. color = red is obligatory. What is wrong in my code ? Do you know a better way to achieve what I want ?

\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys{/mykeys/.cd,
d/.code                     = {\def\macro@d{#1}},
a/.code                     = {\def\macro@a{#1}},
/mykeys/.unknown/.code      = {\let\searchname=\pgfkeyscurrentname
\pgfkeysalso{\searchname/.try=#1,
/tikz/\searchname/.retry=#1}
}
}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2)#3{%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 45}
\pgfqkeys{/mykeys}{#1}
\path (#2) --+(\macro@a:\macro@d) node[/mykeys/.cd,#1] {#3};
\endgroup
}
\makeatother

\begin{document}

\begin{tikzpicture}
\draw (0,0) --( 1,1) coordinate (a) ;
\mainmacro[a=0,d=12pt,draw,shape=circle](a){label 1}
\mainmacro[d=2cm,draw,circle](a){label 2}
\end{tikzpicture}

\end{document}


Update

\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys{/mykeys/.cd,
d/.store in                 = {\macro@d},
a/.store in                 = {\macro@a},
/mykeys/.unknown/.code      = {\let\searchname=\pgfkeyscurrentname
\pgfkeysalso{\searchname/.try=#1,
/tikz/\searchname/.retry=#1,
/tikz/.cd,#1}}}

\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2){%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 1}
\pgfqkeys{/mykeys}{#1}

\draw[/mykeys/.cd,#1] (\macro@a,\macro@a) circle (\macro@d) --++(1,1) node[#1] {label};%
\endgroup
}
\makeatother

\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (5,0) ;
\mainmacro[red,ultra thick](a)
\end{tikzpicture}

\end{document}


The trick works for the node but not with \draw perhaps I'm wrong somewhere in my code

• I think /.store in handler is better here. – percusse Mar 16 '16 at 9:36
• @percusse why do you think it's better ? there is a document about this ? I have some difficulties with the pgfmanual about this ... a complete example would be better – Alain Matthes Mar 16 '16 at 13:05
• I guess it handles the current scope better but I don't have any rigorous argument. It might be just a pschological preference. – percusse Mar 16 '16 at 13:07
• @percusse no psch. because with your code 1. I get an error if I use .code instead of .store in and I am not happy not understand why ! Perhaps it's a new question interesting ? – Alain Matthes Mar 16 '16 at 14:06
• I think I know why the order matters. I'll check at home. – percusse Mar 30 '16 at 14:54

This happens because shape, color names (and some other stuff) are not keys. In other words, when you write red or diamond it doesn't have a dedicated key for such things. Hence, it goes through the TikZ machinery of searchname/.retry but because no such key is there it fails. Instead /tikz/.unknown/.code is much more comprehensive and sophisticated. For example

{%
% Ok, second chance: This might be an arrow specification:
\expandafter\pgfutil@in@\expandafter-\expandafter{\tikz@key}%
\ifpgfutil@in@%
% Ah, an arrow spec!
\expandafter\tikz@processarrows\expandafter{\tikz@key}%
\else%
% Ok, third chance: A shape!
\expandafter\ifx\csname pgf@sh@s@\tikz@key\endcsname\relax%
\pgfkeys{/errors/unknown key/.expand
once=\expandafter{\expandafter/\expandafter t\expandafter
i\expandafter k\expandafter z\expandafter/\tikz@key}{##1}}%
\else%
\edef\tikz@shape{\tikz@key}%
\fi%
\fi%
}%


I can think of two ways to do this:

1. You can in the end of the key trial, pass to TikZ explicitly and let it decide what to do. Hence you add the following

\pgfkeys{/mykeys/.cd,
d/.store in            = {\macro@d},
a/.store in            = {\macro@a},
/mykeys/.unknown/.code = {\let\searchname=\pgfkeyscurrentname%
\pgfkeysalso{\searchname/.try=#1,
/tikz/\searchname/.retry=#1,
/tikz/.cd,#1}% <--- Now invoked under TikZ
}
}


Here, we explicitly trigger TikZ unknown machinery since the family is TikZ now. Hence goes through all the shape name checks and so on.

2. Write your own /.unknown/.code handler to account for known names. For example in Make a PGFkeys path take precedence over another path for a whole scope there are a few examples.

• I need to study your answer but I agree with you for the diagnostic about the keys. The two ways proposed are interesting. – Alain Matthes Mar 16 '16 at 12:23
• Your code works with a node but with my new code \draw ... – Alain Matthes Mar 30 '16 at 15:08

Here is two simple solutions.

## First solution (the better ?)

You may use the /.search also handler (see p.891 of pgfmanual, v3.0.1a):

\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys{
/mykeys/.cd,
d/.code                     = {\def\macro@d{#1}},
a/.code                     = {\def\macro@a{#1}},
/mykeys/.search also={/tikz},
}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2)#3{%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 45}
\pgfqkeys{/mykeys}{#1}
\path (#2) --+(\macro@a:\macro@d) node[/mykeys/.cd,#1] {#3};
\endgroup
}
\makeatother

\begin{document}

\begin{tikzpicture}
\draw (0,0) --( 1,1) coordinate (a) ;
\mainmacro[a=0,d=12pt,draw,red,shape=circle](a){label 1}
\mainmacro[d=2cm,draw,circle](a){label 2}
\end{tikzpicture}

\end{document}


## Second solution

You may use the /.forward to handler (see p.890 of pgfmanual, v3.0.1a):

\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys{
/mykeys/.cd,
d/.code                     = {\def\macro@d{#1}},
a/.code                     = {\def\macro@a{#1}},
/mykeys/.unknown/.forward to=/tikz/\pgfkeyscurrentname,
}
\def\mainmacro{\pgfutil@ifnextchar[{\main@macro}{\main@macro[]}}
\def\main@macro[#1](#2)#3{%
\begingroup
\pgfkeys{mykeys/.cd,
d = 1,
a = 45}
\pgfqkeys{/mykeys}{#1}
\path (#2) --+(\macro@a:\macro@d) node[/mykeys/.cd,#1] {#3};
\endgroup
}
\makeatother

\begin{document}
\begin{tikzpicture}
\draw (0,0) --( 1,1) coordinate (a) ;
\mainmacro[a=0,d=12pt,draw,red,shape=circle](a){label 1}
\mainmacro[d=2cm,draw,circle](a){label 2}
\end{tikzpicture}
\end{document}

• Thanks for the information but I update my question. Nothing works with the new code. – Alain Matthes Mar 30 '16 at 14:50
• @AlainMatthes /.search also works with your new example... – Paul Gaborit Mar 30 '16 at 14:56
• Yes great but do you have an explanation because now I'm lost ... – Alain Matthes Mar 30 '16 at 14:57
• The .search also handler more or less wraps/redirects/aliases the .unknown/.code handler. Paul's code is effectively the same at Percusse's. More strictly I think .search also will intercept arguments passed to a key first, if it is specified. if it doesn't catch the arguments pgf will degrade to .unkown/.code, if that exists (is specified), else pgf will error out. I'm not sure how .search also differs from .forward to. – Carel Jul 1 '16 at 23:18