2

In tikz/pgfkeys, how could I copy (like /styleA/*/.cp) all keys or a single key (like /styleA/colorA/.cp) inside a given path, say styleB in the current path, exactly like if I had copied all the keys manually?

Notably, this implies that if I type:

\node[styleA, styleB, styleC, colorA] {};

then:

  1. if styleC/colorA exists, then colorA is taken from styleC, otherwise from styleB, otherwise styleA
  2. if styleC calls a style, we check if styleB defines it, if not styleA… And of course I don't want to hardcode this list in styleD since the order could be changed in a latter call, like \node[styleA, styleC, styleB, colorA] {};.
  3. the styles contained into styleA, styleB… should be easily changeable without redefining all the other styles that they define. For instance I would like to redefine styleA/colorA/.style={} without redefining also styleA/colorB/.style.
  4. I'd like an easy way to pick a single color from a given style, for instance to include it in a new style myNewStyle/.style={styleA/colorA} without taking the rest of the keys defined in styleA.

What I tried: For now I tried two approaches, neither is perfect:

  • Nested styles: they are great to solve problems 1 and 2, it's possible to obtain 3, but not very elegant (especially on deeply nested styles), and I can't find how to obtain 4.
  • .cd and .family, the point 3 and 4 are trivial to get, but I can't find a way to obtain 1 and 2: once I .cd somewhere, all the keys previously defined are lost. Even when using .search also, the order of the search path is hardcoded, and since I can't know the order that will be used later, I can't obtain point 3.

MWE

enter image description here

\documentclass[]{article}

\usepackage{tikz}

\begin{document}

% Method 1: nested styles. Great to use, but hard to redefine style later.
\tikzset{
  styleA/.style={
    colorA/.style={fill=orange},
    colorB/.style={fill=red},
    colorC/.style={fill=yellow},
    colorD/.style={fill=pink},
    nice label/.style={label={\tiny I'm a label from style A}},
  },
  styleB/.style={
    colorA/.style={%
      fill=green,
      nice label % to check point 2
    },
    colorB/.style={fill=blue},
  },
}

\def\example#1{\tikz \node[#1, colorA] {A}; \tikz \node[#1, colorD] {D};}

\verb|styleA|: \example{styleA}

\verb|styleA, styleB|: \example{styleA, styleB}

Point 3: not very elegant to redefine \verb|styleB/colorA|?

\tikzset{
  styleB/.append style={ % Would prefer: styleB/colorA/.style={fill=gray}
    colorA/.style={
      fill=gray
    },
  },
}

\verb|styleA, styleB|: \example{styleA, styleB}

Problem 4:

\tikzset{
  myNewStyle/.style={
    styleA %<---- I'd like to get only styleA/colorA, but can't find how to do
  }
}
\tikz \node[styleB, myNewStyle, colorA] {A, should be orange}; \tikz \node[styleB, myNewStyle, colorB] {B, should be blue!!!};

\end{document}
7
  • styleB/colorA/.style={fill=gray} would work if you were using nested keys instead of nested styles. Commented Oct 21, 2021 at 19:19
  • @HenriMenke Thanks for your answer, but what do you mean? I tried to replace styleA/.style= with styleA={...} and it tells me that styleA does not exist (of course), and with styleA/.initial={...}, typing styleA later does not load the styles contained inside. And if you mean that I should .cd into styleA, then I will have all the issues mentioned above with points 1 and 2.
    – tobiasBora
    Commented Oct 22, 2021 at 6:49
  • To be quite honest, I also don't have the slightest idea what you mean with your question. All your recent questions are just a wall of text with a super complicated problem which looks just like you have an XY problem. Commented Oct 22, 2021 at 7:19
  • @HenriMenke Concerning the XY problem around my recent questions, they all boil down to "how to add more reliable styles in my zx-calculus library". Now, I converge to a solution that I quite like, except that the "ui" mode is too slow to be used in practice (I also would like to implement externalization at some points).
    – tobiasBora
    Commented Oct 22, 2021 at 18:14
  • @HenriMenke Concerning this specific question, it was also link to this library: I ended up having multiple levels of nested styles, making it hard for the user to overwrite them, or to use part of the existing style to create a new style (for instance, how would you take the phase in label style in /zx/styles/rounded style without taking the rest of the style?). But outside my library, it is quite an elementary task, and I'd say it could be useful elsewhere. I guess you use "copy" every day on your laptop, why not in tikz?
    – tobiasBora
    Commented Oct 22, 2021 at 18:18

1 Answer 1

1

With this method A will be orange and B will be blue. Nothing more, nothing less.

However, I must say that in general this code is really bad design. Why does colorA produce different colors depending on ordering of keys? That's very confusing for the user and will be perceived as unpredictable.

\documentclass[]{article}

\usepackage{tikz}

\begin{document}

% Method 1: nested styles. Great to use, but hard to redefine style later.
\tikzset{
  styleA/.style={
    colorA/.style={fill=orange},
    colorB/.style={fill=red},
    colorC/.style={fill=yellow},
    colorD/.style={fill=pink},
    nice label/.style={label={\tiny I'm a label from style A}},
  },
  styleB/.style={
    colorA/.style={%
      fill=green,
      nice label % to check point 2
    },
    colorB/.style={fill=blue},
  },
}

\def\example#1{\tikz \node[#1, colorA] {A}; \tikz \node[#1, colorD] {D};}

\verb|styleA|: \example{styleA}

\verb|styleA, styleB|: \example{styleA, styleB}

Point 3: not very elegant to redefine \verb|styleB/colorA|?

\tikzset{
  styleB/.append style={ % Would prefer: styleB/colorA/.style={fill=gray}
    colorA/.style={
      fill=gray
    },
  },
}

\verb|styleA, styleB|: \example{styleA, styleB}

Problem 4:

\tikzset{
  myNewStyle/.style={
    colorA/.code=\tikzset{styleA,colorA},
  }
}
\tikz \node[styleB, myNewStyle, colorA] {A, should be orange}; \tikz \node[styleB, myNewStyle, colorB] {B, should be blue!!!};

\end{document}

enter image description here

You must log in to answer this question.

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