1

I'm trying to create a library for drawing various things, and I'd like to be able to set up PGF keys so that there is both a top-level family of settings and module-level settings. If a key name is present in both /my library and /my library/module, I'd like the module key to automatically inherit the values contained within the library key.

So, as an example, /my library/ contains a key called label properties, which sets the default styles for all labels. The value of /my library/module/label properties should be prepended with the (expanded?) value of /my library/label properties.

The MWE below is partway there, but because I can't make the module key inherit the value of the library key, it doesn't really do anything.

    % arara: lualatex: { shell: true }
\documentclass{article}
\usepackage{tikz}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{etoolbox}

% Sets various configuration parameters
% \strandlibset[module]{options as pgfkeys}
\NewDocumentCommand{\mylibraryset}{o m}{
    \IfNoValueTF{#1}{
        \pgfqkeys{/my library}{#2}
    }
    {
        \pgfqkeys{/my library/#1}{#2}
    }
}
\pgfkeys{
    /my library/.is family,
    my library,
    label properties/.style={node font=\bfseries},
    % ... Other top-level keys, some of which should set TikZ options
}

\pgfkeys{
    /my library/module/.is family,
    /my library/module,
    label properties/.initial=, % Inherits the value of /my library/label style/ and prepends that to the key-value list
    % ... Other keys specific to <module>
}

\begin{document}
\begin{tikzpicture}
    \path (0, 0) node[\pgfkeysvalueof{/my library/module/label properties}] {Test node with default options};
    \mylibraryset[module]{label properties={blue, draw=black, fill=black!10!white}}
    \path (0, -1) node[\pgfkeysvalueof{/my library/module/label properties}] {Test node with extra options};
\end{tikzpicture}
\end{document}

This rather contrived MWE doesn't compile at all if I set multiple options in the label style key because the key doesn't get automatically expanded on use. The manual goes into some detail about the various key handlers, but the examples provided are too basic to clearly indicate what exactly is going on. I think what I'm looking for are the .style, .add code handlers, but I'm not entirely sure.

Following Schrödinger's cat's answer, changing the definition of the keys seems to do the trick:

% arara: lualatex: { shell: true }
\documentclass{article}
\usepackage{tikz}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{etoolbox}

% Sets various configuration parameters
% \strandlibset[module]{options as pgfkeys}
\NewDocumentCommand{\mylibraryset}{o m}{
    \IfNoValueTF{#1}{
        \pgfqkeys{/my library}{#2}
    }
    {
        \pgfqkeys{/my library/#1}{#2}
    }
}
\pgfkeys{
    /my library/.is family,
    my library,
    label properties/.style={red, node font=\bfseries},
    % ... Other top-level keys, some of which should set TikZ options
}

\pgfkeys{
    /my library/module/.is family,
    /my library/module,
    label properties/.style=/my library/label properties, % Inherits the value of /my library/label properties/ and prepends that to the key-value list
    % ... Other keys specific to <module>
}

\begin{document}
\begin{tikzpicture}
    \path (0, 0) node[/my library/module/label properties] {Test node with default options};
    \mylibraryset[module]{label properties/.append style={blue, draw=black, fill=black!25!white}}
    \path (0, -1) node[/my library/module/label properties] {Test node with extra options};
\end{tikzpicture}
\end{document}

The workaround seems to be making some keys require a .style or .append style handler.

1 Answer 1

1

The reason why your code does not work is that you do not have the expanded value at the moment you need it. However, your code can be made work rather easily by inserting style/.expanded at the relevant places.

\documentclass{article}
\usepackage{tikz}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{etoolbox}

% Sets various configuration parameters
% \strandlibset[module]{options as pgfkeys}
\NewDocumentCommand{\mylibraryset}{o m}{
    \IfNoValueTF{#1}{
        \pgfqkeys{/my library}{#2}
    }
    {
        \pgfqkeys{/my library/#1}{#2}
    }
}
\pgfkeys{
    /my library/.is family,
    my library,
    label style/.style={node font=\bfseries},
    % ... Other top-level keys, some of which should set TikZ options
}

\pgfkeys{
    /my library/module/.is family,
    /my library/module,
    label style/.initial=, % Inherits the value of /my library/label style/ and prepends that to the key-value list
    % ... Other keys specific to <module>
}

\begin{document}
\begin{tikzpicture}
    \path (0, 0) node[style/.expanded=\pgfkeysvalueof{/my library/module/label style}] {Test node with default options};
    \mylibraryset[module]{label style={blue, draw=black, fill=black!10!white}}
    \path (0, -1) node[style/.expanded=\pgfkeysvalueof{/my library/module/label style}] {Test node with extra options};
\end{tikzpicture}
\end{document}

enter image description here

Whether or not this approach is strictly better than using the /.forward to key is something one may want to discuss separately.

Obviously you could just use a style.

\documentclass{article}
\usepackage{tikz}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{etoolbox}

% Sets various configuration parameters
% \strandlibset[module]{options as pgfkeys}
\NewDocumentCommand{\mylibraryset}{o m}{
    \IfNoValueTF{#1}{
        \pgfqkeys{/my library}{#2}
    }
    {
        \pgfqkeys{/my library/#1}{#2}
    }
}
\pgfkeys{
    /my library/.is family,
    my library,
    label style/.style={node font=\bfseries},
    % ... Other top-level keys, some of which should set TikZ options
}

\pgfkeys{
    /my library/module/.is family,
    /my library/module,
    label style/.style=, % Inherits the value of /my library/label style/ and prepends that to the key-value list
    % ... Other keys specific to <module>
}

\begin{document}
\begin{tikzpicture}
    \path (0, 0) node[/my library/module/label style] {Test node with default options};
    \mylibraryset[module]{label style/.style={blue, draw=black, fill=black!10!white}}
    \path (0, -1) node[/my library/module/label style] {Test node with extra options};
\end{tikzpicture}
\end{document}
2
  • /.forward to looks like it appends the values of key a after key b. If, as per my example above, I made /my library/module/label properties/.forward to=/my library/label properties, then I imaginge the top level properties would override those in the module, whereas what I want is the other way around. Can I set up a key so its value is automatically expanded when it is used?
    – Robbie
    Commented Feb 8, 2020 at 8:52
  • @Robbie You could just use \mylibraryset[module]{label style/.style={blue, draw=black, fill=black!10!white}} to expand it when it is needed, see the second part of the answer.
    – user194703
    Commented Feb 8, 2020 at 8:59

You must log in to answer this question.

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