# xkeyval and the 9 arguments

Recently I’ve been playing D&D with some friends. Tired of writing my small homebrew adventures in OpenOffice I turned into my old friend $\LaTeX$.

Seemed to me that a D&D adventure was specific enough to have its own document class, like article, book etc. And could not find it online, so right now I am writing one.html select jquery set selected

In this article I will explai how to write $\LaTeX$ commands accepting more than the 9 default parameters.

$\LaTeX$ as a user is easy and powerful, lets you use different classes without problem and produces clean documents. I love it and it is beautiful.

As a class developer, as I just discovered, is a pain in the ass.

I got a lot of problems while writing my class, and I had to throw away some ideas that just didn’t work. Now, we’ll see how to create commands with named parameters.

### Objective

\newcommand \newenvironment tags are nice and all, but are limited to 9 non-named arguments.

Being a D&D adventure document there are going to be monster tables, so I want to produce something like:

\begin{ddmonster}
[name=Hobgoblin,level=3,hp=50,xp=150,
role=Soldier,
keywords=natural humanoid,
initiative=7,Speed=5,
AC=20,Fort=18,Refl=16,Will=16]

%a lot more of stuff here. Powers, descriptions, stats

\end{monster}



I just want a basic definition as a set of named arguments, the rest of the monster will be defined with commands.

### Easy as pie

Creating a LaTeX command is quite easy, also the Wikibooks guide helps a lot with it. We just have to use the \newcommand macro and populate it
 \newcommand{name}[num]{definition} 

So for example,

\newcommand{\myprintname}[1]{
my name is #1
}
\myprintname{Jordi}


If I want my name and my surname,

\newcommand{\myprintname}[2]{
my name is #2 , #1 #2
}
\myprintname{James}{Bond}


And I could keep going and going with parameters.

NOTE from the future:
There was a Typo in this post. Discovered (and commented) by Hikari Boulders on the number of parameters.
This is now fixed 😀

• The bar closes at 9. No more arguments for you.
• More arguments would be ugly, so I agree with the limit.
• $\LaTeX$ errors will make you cry

### The good news

keyval, xkeyval and others come to the rescue. I will work with xkeyval. Why? there is no specific reason, I picked that up and worked with it.

While they are easy to use, the documentation does not include a nice example, just very detailed definitions of what each macro does. For examples google and stackoverflow are your friends.

### Using xkeyval

First we have to define all the keys that we want to use. There different types of keys: key, cmdkey, choicekey, booleankey and its variations. I am just working with basic keys, and won’t bother to use other types right now.

The xkeyval documentation states:

\define@key[prefix]{family}{key}          [default]{function}
\define@cmdkey[prefix]{family}[mp]{key}   [default]{function}


The  prefix, family, key  parameters are only an identifier for the key. The define key will create a macro of the form \prefix@family@key, the define cmkdkey something like \cmdprefix@family@key to be used later.

\define@cmdkey[DMK]{ddm}{name}{}
(...)
%I can use it when initialized as:
\cmdDMK@ddm@name


In this D&D monster example I want to define a lot of keys for the different possible attributes of the monster.

• name
• keywords
• role
• HP
• level
• HP
• etc

\define@cmdkey      [DMK] {ddm}     {name}      {}
\define@cmdkey      [DMK] {ddm}     {keywords}  {}
\define@cmdkey      [DMK] {ddm}     {role}      {}
\define@cmdkey      [DMK] {ddm}     {HP}        {}
\define@cmdkey      [DMK] {ddm}     {lvl}       {}
\define@cmdkey      [DMK] {ddm}     {xp}        {}
\define@cmdkey      [DMK] {ddm}     {initiative}{}
\define@cmdkey      [DMK] {ddm}     {perception}{}
\define@cmdkey      [DMK] {ddm}     {AC}        {}
\define@cmdkey      [DMK] {ddm}     {Fort}      {}
\define@cmdkey      [DMK] {ddm}     {Refl}      {}
\define@cmdkey      [DMK] {ddm}     {Will}      {}
\define@cmdkey      [DMK] {ddm}     {speed}     {}
\define@cmdkey      [DMK] {ddm}     {AP}        {}
\define@cmdkey      [DMK] {ddm}     {save}      {}
\define@cmdkey      [DMK] {ddm}     {vision}    {}
\define@cmdkey      [DMK] {ddm}     {immune}    {}
\define@cmdkey      [DMK] {ddm}     {resist}    {}
\define@cmdkey      [DMK] {ddm}     {vulnerable}{}



\newenvironment{ddmonster}[1][]{
\setkeys[DMK]{ddm}{#1}
}{}


### A simple full example

Finally, I post here what I missed when reading the xkeyval documentation, a full simple working example with basic keys.

\documentclass{article}

\usepackage{xkeyval}

%Two parameters command
\newcommand{\myprintname}[2]
{
The name is #2, #1 #2
}

%Maximum parameters command
\newcommand{\mymaxparams}[9]
{
I can't hold nothing more than #1 #2 #3 #4 #5 #6 #7 #8 #9
}

%This is needed for encapsulating.
%changes the catcode of @ so it
%can be used freely (not needed
%when writing a package)
\makeatletter

\define@cmdkey      [PRE] {fam}     {d}  {}
\define@cmdkey      [PRE] {fam}     {u}  {}
\define@cmdkey      [PRE] {fam}     {p}  {}
\define@cmdkey      [PRE] {fam}     {l}  {}
\define@cmdkey      [PRE] {fam}     {i}  {}
\define@cmdkey      [PRE] {fam}     {c}  {}
\define@cmdkey      [PRE] {fam}     {a}  {}
\define@cmdkey      [PRE] {fam}     {t}  {}
\define@cmdkey      [PRE] {fam}     {e}  {}
\define@cmdkey      [PRE] {fam}     {s} {}

\presetkeys         [PRE] {fam} {d = 1,
u = 2,
p = 3,
l = 4,
i = 5,
c = 6,
a = 7,
t = 8,
e = 9,
s = 10,}{}

\newcommand{\myxkeyval}[1]{
%First thing to do, Set the keys
%from the single parameter input
\setkeys[PRE]{fam}{#1}
\textbf{
\cmdPRE@fam@d
\cmdPRE@fam@u
\cmdPRE@fam@p
\cmdPRE@fam@l
\cmdPRE@fam@i
\cmdPRE@fam@c
\cmdPRE@fam@a
\cmdPRE@fam@t
\cmdPRE@fam@e
\cmdPRE@fam@s
}
here you have your 10 parameters \newline
}

%Change again the @ catcode
%to normal
\makeatother

\begin{document}
%An example using newcommand with two parameters
\myprintname{James}{Bond}

%an example using a newcommand with maximum number of parameters
\mymaxparams{un}{dos}{tres}{quatre}{cinc}{sis}{set}{vuit}{nou}
\myxkeyval{}
\myxkeyval{d=D,u=u,p=p,l=l,i=i,c=c,a=a,t=t,e=e,s=s has 10 different letters}

\end{document}


Isograms are words that have no duplicate letter. I find it funny that “duplicates” is an Isogram 🙂

### References

xkeyval documentation ⇒GO
xkeyval package at CTAN ⇒GO
keyval package at CTAN⇒GO

Filed under code, tools

### 3 responses to “xkeyval and the 9 arguments”

1. Pingback: The monster environment | Castells

2. Hikari Boulders

I think there is an error in

\newcommand{\myprintname}[1]{
my name is #2 , #1 #2
}
\myprintname{James}{Bond}

The number of arguments should be 2, not 1.

• kxtells

Hello! You think and you are right! There are two arguments instead of 1.

I’ll fix it in the post.

Thanks for the tip

This site uses Akismet to reduce spam. Learn how your comment data is processed.