0

I'm trying to create a key which has two choice keys nested within it, like so:

engagement={target designation=hostile target, stage=engage}

Here's the MWE I have so far:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
  \makeatletter
  \newcommand*{\testengagement}[1]{
    \tikzset{
    /MilSymb/.cd,
    engagement/.value required,
    /MilSymb/engagement/.cd,
    engagement symb/.store in=\MilSymb@EngagementSymb,
    stage text/.store in=\MilSymb@StageText,
    engagement style/.store in=\MilSymb@EngagementStyle,
    target designation/.is choice,
    target designation/none/.style={/MilSymb/engagement/.cd, engagement style/.style={/tikz/.cd, fill=blue}},
    target designation/hostile target/.style={/MilSymb/engagement/.cd, engagement style/.style={/tikz/.cd, fill=red}},
    stage/.is choice,
    stage/assign or cover/.style={/MilSymb/engagement/.cd, stage text=ASN},
    stage/engage/.style={/MilSymb/engagement/.cd, stage text=ENG},
    stage=assign or cover,
    target designation=none,
    /MilSymb/.cd,
    engagement/.style={/MilSymb/engagement/.cd, engagement symb={\fontsize{6}{0}\selectfont \draw[\MilSymb@EngagementStyle]($(M.north west) + (0,0.05)$) rectangle ($(M.north east) + (0,0.25)$) node [pos=.5] {\MilSymb@StageText};}},
    #1,
    }%
    \draw[local bounding box=M] (0,0) rectangle (1,1);
    \MilSymb@EngagementSymb
    }
    \makeatother
\begin{document}
  \begin{tikzpicture}
  \testengagement{engagement={target designation=hostile target, stage=engage}}
  \end{tikzpicture}
  \begin{tikzpicture}
  \draw[local bounding box=M] (0,0) rectangle (1,1);
  \fontsize{6}{0}\selectfont \draw[fill=red]($(M.north west) + (0,0.05)$) rectangle ($(M.north east) + (0,0.25)$) node [pos=.5] {ENG};
  \end{tikzpicture}
\end{document}

Both images should be identical, but the first image is not displaying the correct colour or text.

comparison image

I'm also getting the following error message:

\pgfkeyscurrentkey ->\MilSymb@EngagementStyle 
                                              
l.32 ...t designation=hostile target, stage=engage}}
                                                  
The control sequence at the end of the top line
of your error message was never \def'ed. If you have
misspelled it (e.g., `\hobx'), type `I' and the correct
spelling (e.g., `I\hbox'). Otherwise just continue,
and I'll forget about whatever was undefined.
4
  • 1
    You shouldn't redefine your entire key list on each usage of your macro!
    – Skillmon
    May 28, 2023 at 14:36
  • @Skillmon I have to in the full implementation of my project as many of the commands I have use the same choice keys with different choices depending on the command. May 28, 2023 at 14:41
  • 1
    Then define different paths for the different macros. This is a pretty unclean setup and bound to have unwanted side effects, if different things share the same name.
    – Skillmon
    May 28, 2023 at 14:53
  • @Skillmon It's fine for the package at the moment since nothing is altered outside of the commands. I'll look at doing it in future but it works for the moment so it's not a high priority. The end user needs to use the same keys for each command for consistency. May 28, 2023 at 15:37

1 Answer 1

2

The issue with your engagement style is, that it doesn't use the value passed to it but just gobbles it. So your engagement = {...} is just setting the stuff defined in the style (so sets engagement symb), but your target destination and stage are completely ignored.

Also, changing the path inside of a style is rather dangerous, as the path is not reset after the style so all following keys after your style will be interpreted as that path. The following fixes that by using .code = \pgfqkeys... instead of a .style (\pgfqkeys will use the given path, and restore the earlier path aftwerwards). I've also removed many of your other .cd usages and instead simply used complete key paths in the problematic spots.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys
  {
    /MilSymb/.cd,
    engagement/.code=
      \pgfqkeys{/MilSymb/engagement}
        {%
          engagement symb =
            {%
              \fontsize{6}{0}\selectfont
              % we need to expand the style
              \expandafter\draw\expandafter[\MilSymb@EngagementStyle]
                ($(M.north west) + (0,0.05)$)
                  rectangle
                ($(M.north east) + (0,0.25)$)
                  node [pos=.5] {\MilSymb@StageText};%
            },
          #1%
        },
    engagement/.value required,
    %
    /MilSymb/engagement/.cd,
    engagement symb/.store in=\MilSymb@EngagementSymb,
    stage text/.store in=\MilSymb@StageText,
    engagement style/.store in=\MilSymb@EngagementStyle,
    target designation/.is choice,
    target designation/none/.style=
      {/MilSymb/engagement/engagement style={fill=blue}},
    target designation/hostile target/.style=
      {/MilSymb/engagement/engagement style={fill=red}},
    stage/.is choice,
    stage/assign or cover/.style={/MilSymb/engagement/stage text=ASN},
    stage/engage/.style={/MilSymb/engagement/stage text=ENG},
    stage=assign or cover,
    target designation=none,
    % initial values (so that the macros are defined)
    engagement symb = {},
    stage text = {},
    engagement style = {},
  }

\newcommand*{\testengagement}[1]
  {%
    \pgfqkeys{/MilSymb}{#1}%
    \draw[local bounding box=M] (0,0) rectangle (1,1);
    \MilSymb@EngagementSymb
  }
\makeatother

\begin{document}
  \begin{tikzpicture}
  \testengagement{engagement={target designation=hostile target, stage=engage}}
  \end{tikzpicture}
  \begin{tikzpicture}
  \draw[local bounding box=M] (0,0) rectangle (1,1);
  \fontsize{6}{0}\selectfont \draw[fill=red]($(M.north west) + (0,0.05)$) rectangle ($(M.north east) + (0,0.25)$) node [pos=.5] {ENG};
  \end{tikzpicture}
\end{document}

enter image description here


Variant that redefines all the keys on each usage:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter

\newcommand*{\testengagement}[1]
  {%
    \pgfkeys
      {
        /MilSymb/engagement/.cd,
        engagement symb/.store in=\MilSymb@EngagementSymb,
        stage text/.store in=\MilSymb@StageText,
        engagement style/.store in=\MilSymb@EngagementStyle,
        target designation/.is choice,
        target designation/none/.style=
          {/MilSymb/engagement/engagement style={fill=blue}},
        target designation/hostile target/.style=
          {/MilSymb/engagement/engagement style={fill=red}},
        stage/.is choice,
        stage/assign or cover/.style={/MilSymb/engagement/stage text=ASN},
        stage/engage/.style={/MilSymb/engagement/stage text=ENG},
        stage=assign or cover,
        target designation=none,
        % initial values (so that the macros are defined)
        engagement symb = {},
        stage text = {},
        engagement style = {},
        %
        /MilSymb/.cd,
        engagement/.code=
          \pgfqkeys{/MilSymb/engagement}
            {%
              engagement symb =
                {%
                  \fontsize{6}{0}\selectfont
                  % we need to expand the style
                  \expandafter\draw\expandafter[\MilSymb@EngagementStyle]
                    ($(M.north west) + (0,0.05)$)
                      rectangle
                    ($(M.north east) + (0,0.25)$)
                      node [pos=.5] {\MilSymb@StageText};%
                },
              ##1%
            },
        engagement/.value required,
        %
        #1%
      }
    \draw[local bounding box=M] (0,0) rectangle (1,1);
    \MilSymb@EngagementSymb
  }
\makeatother

\begin{document}
  \begin{tikzpicture}
  \testengagement{engagement={target designation=hostile target, stage=engage}}
  \end{tikzpicture}
  \begin{tikzpicture}
  \draw[local bounding box=M] (0,0) rectangle (1,1);
  \fontsize{6}{0}\selectfont \draw[fill=red]($(M.north west) + (0,0.05)$) rectangle ($(M.north east) + (0,0.25)$) node [pos=.5] {ENG};
  \end{tikzpicture}
\end{document}

Output as above.

3
  • Thanks for your help! I notice you moved the key definition outside of the command/macro. I appreciate you think this is best practice, but as mentioned previously I want to keep them defined within the command for now, as changing involves rewriting a lot of lines on a rather large style file, basically the entire package needs to be rewritten. Could you please show an example with the "unclean" setup as you describe it? I can't seem to get it to work. Thankyou. May 28, 2023 at 16:38
  • 1
    You're most likely just missing the doubled # in the .style, but I'll update nonetheless.
    – Skillmon
    May 28, 2023 at 17:28
  • Ah yes, that makes sense, thankyou! May 28, 2023 at 17:31

You must log in to answer this question.

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