5

To help me learn l3keys I created two small demos.

The first uses l3keys for a command and seems to work correctly as far as I can tell.

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\documentclass{article}

\ExplSyntaxOn
\prop_gput:Nnn \g_msg_module_type_prop { foo }{ Command }
\msg_new:nnnn { foo }{ unknownoption }
  { Unknown~option. }{ Try~again~but~with~a~known~option. }

\tl_new:N \l__foo_thing_tl
\tl_new:N \l__foo_towhom_tl
\keys_define:nn { foo }
  {
    thing   .tl_set:N = \l__foo_thing_tl ,
    thing   .default:n = door ,
    thing   .initial:n = ice  ,
    towhom  .tl_set:N = \l__foo_towhom_tl ,
    towhom  .default:n = Dana ,
    towhom  .initial:n = Ina  ,
    unknown .code:n = \msg_fatal:nn { foo }{ unknownoption }
  }

\cs_new_protected:Npn \__foo_foo:nn #1#2
  {
    \group_begin:
      \keys_set:nn { foo } { #1 }
      #2~\l__foo_thing_tl \c_space_tl to~\l__foo_towhom_tl.
    \group_end:
  }

\DeclareDocumentCommand{ \foosetup } { m }
  { \keys_set:nn { foo } { #1 } }

\DeclareDocumentCommand{ \foo } { O{} m }
  {
    \__foo_foo:nn { #1 } { #2 }
  }
\ExplSyntaxOff

\begin{document}
This demo shows how to use \texttt{l3keys} for a command.

\foo{Give the}                       \par
\foo[thing]{Give the}                \par
\foo[thing,towhom]{Give the}         \par
\foo[thing=car,towhom=Tom]{Give the} \par
\foosetup{thing=apple}
\foo{Give the}                       \par
\foo[towhom]{Give the}               \par
\end{document}

Here is the output:

Output from first MWE

The second uses l3keys for a package and seems to work correctly except in one case where a key doesn't correctly initialize.

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\begin{filecontents}[overwrite,noheader]{foopkg.sty}
\ProvidesExplPackage{foopkg}{}{}{}
\msg_new:nnnn { foopkg }{ unknownoption }
  { Unknown~option. }{ Try~again~but~with~a~known~option. }

\tl_new:N \l__foopkg_thing_tl
\tl_new:N \l__foopkg_towhom_tl
\keys_define:nn { foopkg }
  {
    thing   .tl_set:N  = \l__foopkg_thing_tl ,
    thing   .default:n = door ,
    thing   .initial:n = ice  ,
    towhom  .tl_set:N  = \l__foopkg_towhom_tl ,
    towhom  .default:n = Dana ,
    towhom  .initial:n = Ina  ,
    unknown .code:n    = \msg_fatal:nn { foopkg }{ unknownoption }
  }

\ProcessKeyOptions[foopkg]

\DeclareDocumentCommand{ \foosetup } { m }
  { \keys_set:nn { foopkg } { #1 } }

\cs_new_protected:Npn \__foopkg_foo:nn #1#2
  {
    \group_begin:
    \keys_set:nn { foopkg } { #1 }
    #2~\l__foopkg_thing_tl \c_space_tl to~\l__foopkg_towhom_tl.
    \group_end:
  }

\DeclareDocumentCommand{ \foo } { O{} m }
  {
    \__foopkg_foo:nn { #1 } { #2 }
  }
\end{filecontents}

\documentclass{article}
%\usepackage[thing=vase,towhom=Val]{foopkg}
\usepackage{foopkg}

\begin{document}
This demo shows how to use \texttt{l3keys} for a package.

\foo{Give the}                       \par
\foosetup{thing=door}
\foo{Give the}                       \par
\foosetup{thing,towhom}
\foo{Give the}                       \par
\foosetup{thing=car,towhom=Tom}
\foo{Give the}                       \par
\foosetup{thing=apple}
\foo{Give the}                       \par
\foosetup{towhom}
\foo{Give the}                       \par
\end{document}

Here is the output:

Output from the second MWE

In the second demo, the second occurrence of Tom should ideally be Ina but I don't understand why the key doesn't reset. This question seems relevant but I'm already, I think, using the solution there and either I'm doing something wrong or I'm not understanding something simple. Can the two demos be made to give the same results?

4
  • it has nothing to do with package or not. You use more \footsetup in your second example and that is not grouped. Feb 28 at 21:32
  • I could not figure out how to use grouping in the \foosetup command. Feb 28 at 21:43
  • well typically you don't want grouping, I mean it is a setup command so naturally it should affect following calls to the key. Feb 29 at 9:10
  • Sure that makes sense. Feb 29 at 20:52

2 Answers 2

5

The initial:n property is what the variable is set to when \keys_define:nn is executed, i.e. equivalent to applying \keys_set:nn. Thus is applies exactly once. If you want reset keys before the start of \keys_set:nn in a case where the keys are not set in a group, add the key to the start of the list:

\keys_set:nn { foopkg } { towhom = Ina , #1 }
1
  • I could have sworn I tried that (from the linked question) but obviously didn't do it correctly. Seems to work properly now. Feb 28 at 21:44
5

The reason is adequately described in Joseph's answer: .initial:n just sets the key once.

Instead of adding the keys to the list and introducing parsing overhead every time you could also just parse the key=value pair once and compile the result into a token list you use to reset the key:

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\begin{filecontents}[overwrite,noheader]{foopkg.sty}
\ProvidesExplPackage{foopkg}{}{}{}
\msg_new:nnnn { foopkg }{ unknownoption }
  { Unknown~option. }{ Try~again~but~with~a~known~option. }

\tl_new:N \l__foopkg_thing_tl
\tl_new:N \l__foopkg_towhom_tl
\tl_new:N \l__foopkg_reset_defaults_tl
\keys_define:nn { foopkg }
  {
    thing   .tl_set:N  = \l__foopkg_thing_tl ,
    thing   .default:n = door ,
    thing   .initial:n = ice  ,
    towhom  .tl_set:N  = \l__foopkg_towhom_tl ,
    towhom  .default:n = Dana ,
    towhom  .initial:n = Ina  ,
    unknown .code:n    = \msg_fatal:nn { foopkg }{ unknownoption }
  }

\ProcessKeyOptions[foopkg]

\keys_precompile:nnN { foopkg } { towhom = Ina } \l__foopkg_reset_defaults_tl
\DeclareDocumentCommand{ \foosetup } { m }
  {
    \l__foopkg_reset_defaults_tl
    \keys_set:nn { foopkg } { #1 }
  }

\cs_new_protected:Npn \__foopkg_foo:nn #1#2
  {
    \group_begin:
    \keys_set:nn { foopkg } { #1 }
    #2~\l__foopkg_thing_tl \c_space_tl to~\l__foopkg_towhom_tl.
    \group_end:
  }

\DeclareDocumentCommand{ \foo } { O{} m }
  {
    \__foopkg_foo:nn { #1 } { #2 }
  }
\end{filecontents}

\documentclass{article}
%\usepackage[thing=vase,towhom=Val]{foopkg}
\usepackage{foopkg}

\begin{document}
This demo shows how to use \texttt{l3keys} for a package.

\foo{Give the}                       \par
\foosetup{thing=door}
\foo{Give the}                       \par
\foosetup{thing,towhom}
\foo{Give the}                       \par
\foosetup{thing=car,towhom=Tom}
\foo{Give the}                       \par
\foosetup{thing=apple}
\foo{Give the}                       \par
\foosetup{towhom}
\foo{Give the}                       \par
\end{document}

A small variation, which I think is more correct than using a tl to reset the values:

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\begin{filecontents}[overwrite,noheader]{foopkg.sty}
\ProvidesExplPackage{foopkg}{}{}{}
\msg_new:nnnn { foopkg }{ unknownoption }
  { Unknown~option. }{ Try~again~but~with~a~known~option. }

\tl_new:N \l__foopkg_thing_tl
\tl_new:N \l__foopkg_towhom_tl
\keys_define:nn { foopkg }
  {
    thing   .tl_set:N  = \l__foopkg_thing_tl ,
    thing   .default:n = door ,
    thing   .initial:n = ice  ,
    towhom  .tl_set:N  = \l__foopkg_towhom_tl ,
    towhom  .default:n = Dana ,
    towhom  .initial:n = Ina  ,
    unknown .code:n    = \msg_fatal:nn { foopkg }{ unknownoption }
  }

\ProcessKeyOptions[foopkg]

\group_begin:
  \keys_precompile:nnN { foopkg } { towhom = Ina } \l_tmpa_tl
  \exp_args:NNV \cs_new_protected:Npn \__foopkg_reset_defaults: \l_tmpa_tl
\group_end:
\DeclareDocumentCommand{ \foosetup } { m }
  {
    \__foopkg_reset_defaults:
    \keys_set:nn { foopkg } { #1 }
  }

\cs_new_protected:Npn \__foopkg_foo:nn #1#2
  {
    \group_begin:
    \keys_set:nn { foopkg } { #1 }
    #2~\l__foopkg_thing_tl \c_space_tl to~\l__foopkg_towhom_tl.
    \group_end:
  }

\DeclareDocumentCommand{ \foo } { O{} m }
  {
    \__foopkg_foo:nn { #1 } { #2 }
  }
\end{filecontents}

\documentclass{article}
%\usepackage[thing=vase,towhom=Val]{foopkg}
\usepackage{foopkg}

\begin{document}
This demo shows how to use \texttt{l3keys} for a package.

\foo{Give the}                       \par
\foosetup{thing=door}
\foo{Give the}                       \par
\foosetup{thing,towhom}
\foo{Give the}                       \par
\foosetup{thing=car,towhom=Tom}
\foo{Give the}                       \par
\foosetup{thing=apple}
\foo{Give the}                       \par
\foosetup{towhom}
\foo{Give the}                       \par
\end{document}
5
  • Oh I like that approach very much. Feb 29 at 20:52
  • I'm curious about why you didn't use \tl_use:N \l__foopkg_reset_defaults_tl before \keys_set:nn. It doesn't look as though it matters, but I'm curious. Mar 1 at 19:39
  • @LaTeXereXeTaL for a tl it is documented behaviour that the \tl_use:N is optional and you can also use it directly. If you prefer it you can put it there.
    – Skillmon
    Mar 1 at 20:01
  • I see I misread the relevant sentence in interface3.pdf. Thank you. Mar 1 at 20:08
  • I'd really prefer a different approach really, I'll update my answer with that alternative...
    – Skillmon
    Mar 1 at 20:43

You must log in to answer this question.

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