10

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, 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...

11

#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 '15 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? – EngBIRD Nov 6 '15 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. – clemens Nov 6 '15 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. – clemens Nov 6 '15 at 19:24
  • So isn't it a bit confusing to use a local group in a module setup command here? – cfr Nov 7 '15 at 0:23
7

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! – EngBIRD Nov 6 '15 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 '15 at 22:45

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.