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}
  • you can define an /.is if – percusse Nov 17 '17 at 20:11
  • @percusse I did find that in the manual, but I couldn't work it out. – Geoff Nov 17 '17 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 Nov 17 '17 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 Nov 17 '17 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. – Andrew Nov 17 '17 at 21:53
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.