# How do I use \ifcommandkey , or how do I check if a key was given?

I'm trying to create a keycommand with optional arguments, but I can't get it to work. I looked at Comparing an argument to a string when argument is a result of a command with etoolbox and although the example there works, I can't get it to work for use with keycommand, nor can I get ifcommandkey to work as expected. I recently upgraded from Tex Live 2009 to Tex Live 2011 and in 2009, ifcommandkey was working.

In Tex Live 2011, how do I check whether a key was given or not?

Below is an example where I try different things. None have the desired effect; in the third call, I want the result to be something like "No spam. No eggs. No paper. No Salt", but I get "Has spam" in every run. Why?

\documentclass{minimal}
\usepackage{keycommand}
\usepackage{etoolbox}
\begin{document}
\newcommand\myifstrempty{\expandafter\ifstrempty\expandafter}
\newkeycommand{\testkc}[spam,eggs,paper,salt][][0]{
\ifcommandkey{spam}{Spam: \commandkey{spam}''}{No spam}.
\ifcommandkey{eggs}{Eggs: \commandkey{eggs}''}{No eggs}.
\ifcommandkey{paper}{Paper: \commandkey{paper}''}{No paper}.
\ifcommandkey{salt}{Salt: \commandkey{salt}''}{No Salt}.
\ifcommandkey\expandafter{salt}{Salt: \commandkey{salt}''}{No Salt}.
\myifstrempty{\commandkey{spam}}{Not has spam}{Has spam}
\expandafter\ifstrempty{\expandafter{\commandkey{spam}}}{Not has spam}{Has spam}
}

\testkc[spam=bad, eggs=good, salt=horrid]

\testkc[paper=gold]

\testkc

\newcommand{\aORb}[1]{%
\expandafter\ifstrequal\expandafter{#1}{a}{"a" was given}{not a}, %
\expandafter\ifstrequal\expandafter{#1}{b}{"b" was given}{not b}%
}

\aORb{a}

\aORb{b}

\end{document}


The result looks like this:

-
If you find the time, try the key commands and key environments of 'ltxkeys' package. If you encounter difficulties there, first email the package author. –  Ahmed Musa Nov 22 '11 at 16:57

# The \ifcommandkey approach

There is a bug in the definition of \ifcommandkey (2010/04/27 v3.1415). It is missing out one stage of expansion of the \commandkey (see the analysis in the section below), and as a result does not test the value of the key. (You will get TRUE even with an undefined key.) Try the following definition in the preamble after loading keycommand:

\begingroup
\makeatletter
\catcode\/=8 %
\@firstofone
{
\endgroup
\renewcommand{\ifcommandkey}[1]{%
\csname @\expandafter \expandafter \expandafter
\expandafter \expandafter \expandafter  \expandafter
\kcmd@nbk \commandkey {#1}//{first}{second}//oftwo\endcsname
}
}


# The \ifstrempty approach

The issue here is that you are not doing enough expansion for the \ifstrempty test. What you need to ensure it that the argument this receives is the value passed to the key, and not some intermediate form. Thus you need to expand \commandkey to the content it represents. Now, there are a three approaches for this type of thing. First, we could use \edef:

\newcommand\myifstrempty[1]{%
\begingroup
\edef\x{%
\endgroup
\noexpand\ifstrempty{#1}%
}%
\x
}


The problem with this is that you don't know what might be given for the key value, so the \edef may go wrong.

A more controlled approach is to use the correct number of \expandafters. If you do

\show\commandkey


you'll find it expands to

\csname keycmd->testkc@#1\endcsname


inside your key-using macro. So to expand to the value of the key requires three expansions: the first to expand \commandkey, the second to expand the \csname primitive and the third to expand the resulting control sequence. Due to the way TeX expansion works, this leads to

\newcommand\myifstrempty{%
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\ifstrempty
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
}


The third approach is to use the peculiar nature of \romannumeral to do what LaTeX3 would call a 'full' expansion. This is similar to doing an \edef but will halt cleanly on anything which cannot be expanded:

\newcommand\myifstrempty[1]%
{\expandafter\ifstrempty\expandafter{\romannumeral -0#1 }}


The later is useful in the current case as it cuts down on the number of \expandafter primitives required.

-
I've reported the issue to the package author –  Joseph Wright Nov 22 '11 at 19:04
Thanks! This \expandafter stuff looks pretty complicated, makes me happy there are so many useful packages around that I don't feel the need to roll my own package (yet) :) –  gerrit Nov 22 '11 at 20:45
@gerrit Expansion is a tricky area, hence for example the LaTeX3 Project's work on a programming layer which deals with a lot of this. –  Joseph Wright Nov 22 '11 at 20:51