# Misunderstanding from l3keys documentation

Based on the interface3 documentation and a nice article in TUGboat, Volume 31 (2010), No. 1 called Programming key–value in expl3 by Joseph Wright (available here), I have been trying to put together a MWE that will allow me to create a custom document command that will populate a structured table based on values and paragraphs passed by keys. i.e. document call would look something like:

\CustomCommand[key1={abc},key2={def}] % would include a mandatory argument only if absolutely necessary


This is in response to comments left in this Line breaks introduced in database export as extra lines in table question which practically point out that keys will be a more practical way of passing information than endless ordered arguments.

I thought I had understood the examples in the documentation and tried to put together a simple example but the output makes no sense to me:

\documentclass[10pt]{article}

\usepackage{xparse}

\ExplSyntaxOn

\keys_define:nn { mymodule }
{
key-start-date .tl_set:N = \l_mymodule_tl
}

\DeclareDocumentCommand \MyModuleSetup { o m }
{
Hello~World~The~date~today~is~{\l_mymodule_tl}~and~I~say~#1
}

\ExplSyntaxOff

\begin{document}

\MyModuleSetup[key-start-date={Date}]{Goodbye~World}

\end{document}


This yields:

Hello World The date today is and I say key-start-date=Date

I expected

Hello World The date today is Date and I say Goodbye World

To start with, I don't understand why the key name is parsed out as text...

#1 is the optional argument in your definition, #2 would be the mandatory one: \DeclareDocumentCommand \MyModuleSetup { o m }. So when you use

\MyModuleSetup[key-start-date={Date}]{Goodbye~World}


#1 is key-start-date={Date} and #2 is Goodbye~World. This is exactly what you're seeing.

Also you are defining the key with \keys_define:nn but aren't setting it it \keys_set:nn. A working suggestion:

\documentclass[10pt]{article}

\usepackage{xparse}

\ExplSyntaxOn

% define the variable before using it:
\tl_new:N \l_mymodule_start_date_tl

% define key:
\keys_define:nn { mymodule }
{
key-start-date .tl_set:N = \l_mymodule_start_date_tl
}

% #1: set keys (optional)
% #2: do something (mandatory)
\DeclareDocumentCommand \MyModuleSetup { o m }
{
% start a group to keep key setting local:
\group_begin:
% set keys if optional argument #1 is given:
\IfNoValueF {#1} { \keys_set:nn {mymodule} {#1} }
% do something with variable and mandatory argument #2:
Hello~World~The~date~today~is~{\l_mymodule_start_date_tl}~and~I~say~#2
\group_end:
}

\ExplSyntaxOff

\begin{document}

\MyModuleSetup[key-start-date={Date}]{Goodbye World}

\end{document}

• Damn, you were quicker ;-)
– user31729
Nov 6, 2015 at 19:17
• Thanks, what a fast answer, I have watched the edits evolve over the last few minutes and I noticed that the \group encapsulators were not necessary in your first iteration. What purpose to they serve? Nov 6, 2015 at 19:20
• @EngBIRD without the group the variable will keep the value set by the use of the macro. With group it will be reset at the end of the macro. Nov 6, 2015 at 19:22
• @EngBIRD A module setup command should simply be something like \NewDocumentCommand \mysetup {m} { \keys_set:nn {mymodule} {#1} } but in other user commands a local setting of keys is usually what users expect. Nov 6, 2015 at 19:24
• So isn't it a bit confusing to use a local group in a module setup command here?
– cfr
Nov 7, 2015 at 0:23

keys_set:nn is missing in the usage of \DeclareDocumentCommand, so \l_mymodule_tl is effectively empty.

\documentclass[10pt]{article}

\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l_mymodule_tl
\keys_define:nn { mymodule }
{
key-start-date .tl_set:N= \l_mymodule_tl
}

\DeclareDocumentCommand \MyModuleSetup {O{}m }
{
\keys_set:nn{mymodule}{#1}
Hello~World~The~date~today~is~{\tl_use:N \l_mymodule_tl}~and~I~say~#1
}

\ExplSyntaxOff

\begin{document}

\MyModuleSetup[key-start-date={Date}]{Goodbye~World}

\end{document}

• Wow, you guys are lighting fast. I completely misapplied the concept that key-start-date .tl_set:N= \l_mymodule_tl set the value. I see know that the document command has to set the optional arguments to the keys, so that the definitions can parse it out and then use set to store it to the variable. Please correct me if I am wrong here. Thanks! Nov 6, 2015 at 19:21
• You just missed \keys_set:nn --> each macro that should be aware of your keys must use \keys_set:nn
– user31729
Nov 6, 2015 at 22:45