3

I am trying to understand how to construct macros with pgfkeys and found the following solution very useful but there is something I would like to do

I have made a very minimal example below. What I would like is to have a key that doesn't take a value but something happens whether the key is there or not. In other words, I would like a syntax like the parts below that are commented out. I assume this is possible since in tikz we can create, for example, node[draw, circle, fill=red].

So how can we create keys that take no values?

(I suppose that even my example below can be even done without ifthen too)

\documentclass{article}

\usepackage{ifthen}
\usepackage{pgfkeys}

\pgfkeys{
 /display/.is family, /display,
 show/.estore in = \myShow,
 }

\newcommand\macroname[2][]{%
\pgfkeys{/display, #1}%

\ifthenelse{{\equal{\myShow}{once}}}{#2}

\ifthenelse{{\equal{\myShow}{twice}}}{#2#2}

}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



\begin{document}

\macroname[show=once]{input}

\macroname[show=twice]{input}

% \macroname[once]{input}
%
% \macroname[twice]{input}

\end{document}

PLAN B

Following from the comment of percusse I had another attempt at understanding the manual's Key handler /.is if. I got something to work, but not everything to how I expected. The MWE below shows three instances of the macro. Why when one uses the key once I still need to set it to true for it to work?

\documentclass{article}
\usepackage{pgfkeys}

\newif\ifdisplayonce
\pgfkeys{/once/.is if=displayonce} 
\pgfkeys{/once/.default=false} 

\newcommand\macronameb[2][]{%
\pgfkeys{/once, #1} 

\ifdisplayonce
#2
\else
#2#2
\fi
}

\begin{document}

\macronameb{input1}
\macronameb[once=true]{input2}
\macronameb[once]{input3}

\end{document}
6
  • you can define an /.is if
    – percusse
    Commented Nov 17, 2017 at 20:11
  • @percusse I did find that in the manual, but I couldn't work it out.
    – Geoff
    Commented Nov 17, 2017 at 20:14
  • Regarding your plan B and the question you asked in the ldescriptiion above the code: This happens because you set the default to ˋfalseˋ ;-)
    – Tobi
    Commented Nov 17, 2017 at 21:37
  • @Tobi But if I set the default to true, then the first case doesn't seem to give the else case. In other words all three outputs are singular, none are doubled.
    – Geoff
    Commented Nov 17, 2017 at 21:39
  • @Geoff You can 't use default (or initial, since these are often confiused with pgfkeys) to set a key with an .is if handler. Instead, you have to set it "by hand" using \displayoncetrue or \displayoncefalse.
    – user30471
    Commented Nov 17, 2017 at 21:53

1 Answer 1

4

There are many ways to have pgfkeys that don't need values (draw, btw the way can take a value: draw=blue, for example). I don't that I really understand what you are trying to do but here are a few different ways to use keys without values, some of which may be useful/interesting to you -- none of them use ifthenelse. In particular, the code does "solve" your problem by introducing a help macro, \macrohelper. I would not be surprised if there are more elegant ways to do this.

\documentclass{article}

\usepackage{ifthen}
\usepackage{pgfkeys}

\providecommand\macrohelper[1]{#1}% default set to "once"
\pgfkeys{
 /display/.is family, /display,
 unset/.initial=1,% can be used without setting
 unsettling/.code={not set to #1},% can be used without setting
 unsettling/.default=0,% default value
 once/.code = {\renewcommand\macrohelper[1]{Once: ##1}},% redefine \helpermacro
 twice/.code = {\renewcommand\macrohelper[1]{Twice: ##1+##1}},
 show/.code = {\pgfkeys{/display/#1}}% calling shows defers to once/twice/error
}

\newcommand\macroname[2][]{%
  \pgfkeys{/display, #1}%
  \macrohelper{#2}
}

\begin{document}

  \verb|\macroname[show=once]{input}| \macroname[show=once]{input}

  \verb|\macroname[show=twice]{input}| \macroname[show=twice]{input}

  \verb|\macroname[once]{input}| \macroname[once]{input}

  \verb|\macroname[twice]{input}| \macroname[twice]{input}

  \verb|\pgfkeys{/display/unset}| \pgfkeys{/display/unset}

  \verb|\pgfkeys{/display/unset=2} \pgfkeys{/display/unset}| \pgfkeys{/display/unset=2} \pgfkeys{/display/unset}

  \verb|\pgfkeys{/display/unsettling}| \pgfkeys{/display/unsettling}

  \verb|\pgfkeys{/display/unsettling=2}| \pgfkeys{/display/unsettling=2}
\end{document}

When you run this through LaTeX the following output is produced (the "input" is on the left in \texttt and the output is on the right):

enter image description here

Another option is to use the .is choice handler for the show key so that a more meaningful error message is printed for input like \macroname[show=thrice]{input}. That is, you could instead use:

\pgfkeys{
 /display/.is family, /display,
 unset/.initial=1,
 unsettling/.code={not set to #1},
 once/.code = {\renewcommand\macrohelper[1]{Once: ##1}},
 twice/.code = {\renewcommand\macrohelper[1]{Twice: ##1+##1}},
 show/.is choice = {\pgfkeys{/display/#1}},
 show/once/.code = {\pgfkeys{/display/once}},
 show/twice/.code = {\pgfkeys{/display/twice}},
}

Now if you try show=thrice you will get the error message:

! Package pgfkeys Error: Choice 'thrice' unknown in choice key '/display/show'. I am going to ignore this key.

Finally, to use the .is if handler you have to first define a boolean switch using \newif:

\documentclass{article}

\usepackage{pgfkeys}

\newif\ifshowonce\showoncefalse% twice by default

\providecommand\macrohelper[1]{#1}
\pgfkeys{
 /display/.is family, /display,
 show once/.is if=showonce
}

\newcommand\macrotwo[2][]{%
  \pgfkeys{/display, #1}%
  \ifshowonce #2\else #2+#2\fi
}

\begin{document}

    \macrotwo{input}

    \macrotwo[show once=true]{input}

    \macrotwo[show once=false]{input}
\end{document}

to produce:

enter image description here

You must log in to answer this question.

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