2

I'm trying the use the xkeyval package to define a very simple command using keys. However, I'm utterly confused by its behavior, and the package documentation is not exactly helpful either. Here's a MWE with what I wanted to achieve (expected) and what I actually got. Why is this happening and what do I need to do to get the result I'm after? I've also consulted: How to create a command with key values? and: A package template using xkeyval? without any luck

\documentclass{article}

\usepackage{xkeyval}

\makeatletter
\define@key[]{fam}{foo}[XX]{#1}
\newcommand{\mycommand}[1][]{%
   \begingroup
   \setkeys[]{fam}{#1}
   ``Using the macro: \fam@foo ''
   \endgroup
}
\makeatother

\begin{document}

% Example where I hoped to get the default value (XX)
\mycommand % Expected: "Using the macro XX" - Got: "Using the macro"

% Example where I hoped to override the default value
\mycommand[foo=YY] % Expected: "Using the macro YY" - Got: YY "Using the macro"


\end{document}

1 Answer 1

4

When you do

\define@key[]{fam}{foo}[XX]{<code>}

you are essentially doing

\def\fam@foo#1{<code>}

In your case you have

\def\fam@foo#1{#1}

which is confirmed if I change the code into

\newcommand{\mycommand}[1][]{%
   \begingroup
   \setkeys[]{fam}{#1}
   \texttt{\meaning\fam@foo}\\
   ``Using the macro: \fam@foo ''
   \endgroup
}

getting

enter image description here

When you do \setkeys[]{fam}{foo} you're doing \fam@foo{YY} which, by definition, expands to YY. Later, you're doing \fam@foo' and this expands to '.

If you want to save a value, you have to say something like

\documentclass{article}

\usepackage{xkeyval}

\makeatletter
\define@key[]{fam}{foo}[XX]{\def\fam@foo@toks{#1}}
\setkeys[]{fam}{foo} % initialize
\newcommand{\mycommand}[1][]{%
   \begingroup
   \setkeys[]{fam}{#1}
   ``Using the macro: \fam@foo@toks ''
   \endgroup
}
\makeatother

\begin{document}

\mycommand

\mycommand[foo=YY]

\end{document}

enter image description here

The alternative is to use \define@cmdkey, that does the above using \cmdfam@foo as container.

\define@cmdkey[]{fam}{foo}{}
\setkeys[]{fam}{foo=XX} % initialize
\newcommand{\mycommand}[1][]{%
   \begingroup
   \setkeys[]{fam}{#1}
   ``Using the macro: \cmdfam@foo''
   \endgroup
}
5
  • Thanks for your help. However, I'm now even more confused. It appears that I simply don't understand how this package is even supposed to be used. In particular, why is not the method which is specified in the documentation of xkeyval (Sec 3.1) not working? And what does toks even mean? Is it just arbitrary? And why do I have to specify even more \def's? I thought that was supposed to be handled by the \define@key command? And why do I have to specify default values with an extra call to \setkeys when you are supposed to supply that in \define@key?
    – hakoja
    Apr 25, 2014 at 11:04
  • toks is just arbitrary; use \define@cmdkey if you want a “uniform” name. The default value is used when the key is called without a value.
    – egreg
    Apr 25, 2014 at 11:11
  • While the cmdkey example appeared cleaner, how do I specify functions of the input with it? I.e. if I want to take in the value of foo (#1) and make it bold (say). And what do you mean by called? I'm sorry for being so dense, but it seems that there is something really fundamental I'm not getting here...
    – hakoja
    Apr 25, 2014 at 11:16
  • @hakoja Using the macro: \textbf{\cmdfam@foo} with \define@cmdkey; or \define@key[]{fam}{foo}{\def\cmdfam@foo{\textbf{#1}}} and then Using the macro \cmdfam@foo
    – egreg
    Apr 25, 2014 at 11:19
  • Ok, thanks for your patience. I'm accepting your answer since it works, but unfortunately I don't really understand it at all. It's just so confusing that I don't see how this usage corresponds to the way it appears we are supposed to use this package in the documentation.
    – hakoja
    Apr 25, 2014 at 11:24

You must log in to answer this question.

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