6

(This is inspired by Problem between keys, paths with two macros and pgfkeys)

The following code

\documentclass[tikz]{standalone}
\begin{document}
    \pgfkeys{
        %/foo/.search also={/bar,/tikz},
        %/foo/.search also={/bar},
        /bar/.search also={/tikz}
    }
    \tikz\draw[/foo/.cd,fill=red]circle(1);
\end{document}

produces error

Package pgfkeys Error: I do not know the key '/foo/fill', to which you passed 'red', and I am going to ignore it. Perhaps you misspelled it.

This is not surprising, because there is nothing under /foo.



The following code

\documentclass[tikz]{standalone}
\begin{document}
    \pgfkeys{
        /foo/.search also={/bar,/tikz},
        %/foo/.search also={/bar},
        /bar/.search also={/tikz}
    }
    \tikz\draw[/foo/.cd,fill=red]circle(1);
\end{document}

produces a picture successfully

This is not surprising either, because /foo tries to search fill under /bar and /tikz, and finds that /tikz/fill is defined.



The following code

\documentclass[tikz]{standalone}
\begin{document}
    \pgfkeys{
        %/foo/.search also={/bar,/tikz},
        /foo/.search also={/bar},
        /bar/.search also={/tikz}
    }
    \tikz\draw[/foo/.cd,fill=red]circle(1);
\end{document}

surprisingly, produces no error but a naïve picture.

It seems like /foo asks /bar to find fill under /tikz, and they success (hence no error). But for some reason the style failed to apply.



Why is this happening? Can I somehow make one of these happen:

  • raise an error; or
  • apply the style successfully; or even better
  • apply the style successfully and raise a warning?
5
  • Did you try without the =red part? It should give an unknown handler something error. I remember working with this at some point but don't remember what the issue was.
    – percusse
    Apr 28, 2017 at 14:27
  • @percusse Yes, indeed. If I try without the fill= part, it raises the same error. (I do not know the key '/handlers/.unknown/.@cmd') I highly suspect that it has something to do with the default treatment of TikZ that test whether an unknown key is actually a color (mixed or pure). In this sense, it is clear that fill=red is not a color so TikZ did not bother to test it. (This is purely guess, otherwise things just got more complicated.
    – Symbol 1
    Apr 28, 2017 at 15:17
  • It looks like something has changed since you asked the question, I get I do not know the key '/bar/fill', to which you passed 'red', and I am going to ignore it. The .unknown code installed by .search also seems to check only if /bar/fill exists but not if /bar would look somewhere else. It looks like you need to install your own .unknown code, I believe: unknown → try /bar/<key>, still unknown → Try /tikz/<key> (but for the last stime). There are .last retry and \ifpgfkeyssucess or similar. Oct 24, 2022 at 9:08
  • @Qrrbrbirlbel I get weird results even with an .unknown handler set to try & retry the various paths. However, I can't reproduce the problem in a small enough example to post.
    – cfr
    Sep 6, 2023 at 2:06
  • @cfr If I'm seeing this right, the check \ifpgfkeysaddeddefaultpath is toggled false when /foo/.unknown attempts \pgfqkeys{/bar}{fill=red} which makes the /bar/.unknown not try anything else. (Basically, that's the different between /bar/.cd, fill=red and /bar/fill=red where the latter is assumed correct and raises an error on purpose.) I don't have the patience to look why that is and where this happens and whether this is even a bug or intended but it seems easier to setup a custom .unknown handler … Sep 6, 2023 at 17:11

1 Answer 1

2

If I'm seeing this right, the check \ifpgfkeysaddeddefaultpath that is executed at the startof the .unknown code set up by .search also is toggled false when /foo/.unknown attempts

\pgfqkeys{/bar}{fill=red}

which makes the /bar/.unknown not try anything else.

(Basically, that's the different between /bar/.cd, fill=red and /bar/fill=red where the latter is assumed correct and raises an error on purpose despite a .search also alternative.)

I don't have the patience to look why that is and where this happens and whether this is even a bug or intended but it seems easier to setup a custom .unknown handler …

It just depends on how you want to handle some things.


Since /tikz/.unknown does not make the \ifpgfkeysaddeddefaultpath check it doesn't differentiate between /tikz/.cd, <key>=<value> and /tikz/<key>=<value>. (Internally, instead of .cd, oftentimes the quicker \pgfqkeys{/tikz}{<key>=<value>} is used but that's basically the same.)

However, sometimes a <key> is a style and then it depends on in which path we execute them. Doing

\pgfkeys{/abc/.cd, /tikz/thick}

will lead to an error about an unknown key /abc/line width since we're still in the /abc path (well, unless /abc/line width is defined, of course, than that will be used).

This leads me to an .unknown handler that is very close to the manual's example.

Unfortunately, /tikz/.unknown doesn't set \pgfkeyssuccesstrue when it finds a color, an arrow specification or a shape's name which makes it hard to figure out whether a /tikz/<key> was actually successfull which means the maintainer of /foo can't raise a proper error message without redefining /tikz/.unknown or doing the same spiel itself.

Code

\documentclass[tikz]{standalone}
\begin{document}
\pgfkeys{
  /bar/.search also=/tikz, % this can stay, I guess
  /foo/.unknown/.code=
    \ifpgfkeysaddeddefaultpath
      \let\unknownname\pgfkeyscurrentname
      \pgfkeysalso{
        /bar/\unknownname/.try={#1}, % only try /tikz if /bar failed
        /tikz/\unknownname/.lastretry={#1}}%
        % Ugh! /tikz/.unknown doesn't set \pgfkeyssuccesstrue
        % after it handles a color, an arrow specification or a shape's name
        % then this will be annoying:
        \unless\ifpgfkeyssuccess
          \errmessage{Well, I couldn't find /foo/\unknownname={#1},
                      /bar/\unknownname={#1} and /tikz/\unknownname={#1}.
                      I don't know what you want from me.}%
        \fi
    \else % someone tried to do /foo/<unknown key>, let's fail:
      \errmessage{myPackage: /foo/\pgfkeyscurrentname\space is an unknown key.}%
    \fi
}
\tikz[radius=1]{
  \draw[/bar/.cd, fill=red] circle[];
  \draw[/bar/fill=red]      (right:1) circle[];% will always fail
  \draw[/foo/.cd, fill=red] (right:2) circle[];
  \draw[/foo/fill=red]      (right:3) circle[];% will always fail
}

\tikz{
  \draw[/bar/.cd, inner xsep=0+0] node {\pgfkeysvalueof{/pgf/inner xsep}};
  \draw[/foo/.cd, ->]     (right:1) -- +(right:.5); % Ugh!
  \draw[/foo/.cd, red!50] (right:2) -- +(right:.5); % Ugh!
  \draw[/foo/.cd, circle] (right:3.5) node[draw]{}; % Ugh!
  \draw[/foo/.cd, thick]  (right:4) -- +(right:.5);% finds /tikz/thick but then
                                                   % has to try /foo/line width
                                                   % and then /bar/line width and
                                                   % then finally /tikz/line width
}
\pgfkeys{/tikz/.cd, abc}% → unknown /tikz/abc
\pgfkeys{/bar/.cd, abc} % → unknown /tikz/abc
\pgfkeys{/foo/.cd, abc} % → unknown /foo/abc, /bar/abc, /tikz/abc
\end{document}

Output

enter image description here

enter image description here

1
  • Thanks for this explanation. I think my problem is actually not the one I originally thought, so I need to think about how to handle it some more. I already had custom .unknown handler in place, though it fails silently which is probably bad, so this example is very useful as I wasn't altogether sure the best way to trigger the message. (I modified an example from the manual, but it didn't include error handling.)
    – cfr
    Sep 6, 2023 at 18:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .