3

If I have previously set up a .meta:n key with

\keys_define:nn { module } { key .meta:n = { … } }

then it's easy to replace the key with new values by calling \kerys_define:nn with new meta options.

But what if I want to append to the current meta options for the key?

MWE

In this MWE, I want \setstyle to replace the meta options for style and \setstyle* to append to the meta options for style. How can I do this?

\documentclass{article}
\ExplSyntaxOn
\keys_define:nn { dcp }
  { 
    keya .tl_set:N = \l__dcp_keya_tl ,
    keyb .tl_set:N = \l__dcp_keyb_tl ,
    keyc .tl_set:N = \l__dcp_keyc_tl ,
    style .choice:
  }
\NewDocumentCommand \setstyle { s m }
  {
    \bool_if:NTF #1
      {
        % how can I append to style?
      }
      {
        % set style
        \keys_define:nn { dcp } { style .meta:n = {#2} }
      }
  }
\NewDocumentCommand \showstyle { }
  {
    \keys_show:nn { dcp } { style }
  }
\ExplSyntaxOff
\setstyle{keya=x,keyb=y}
\begin{document}
\showstyle
\setstyle{keya=x,keyb=yy}
\showstyle
\setstyle*{keyc=z}
\showstyle
\end{document}
David Purton
  • 25,884
  • I have an off-topic question: Is there any advantage to using \bool_if:NTF #1 as a substitute for \IfBooleanTF{#1} when testing whether a function defined by \NewDocumentCommand is starred or unstarred? – User23456234 Dec 27 '23 at 05:36
  • @User23456234, I don't think so. But all this code will live in an Expl3 style so I'm just using the Expl3 interface rather than the LaTeX one. – David Purton Dec 27 '23 at 07:31

1 Answers1

4

Not sure if there is an official interface, but storing the keys as a clist seems to work. I had to change the \showstyle command because with the way I've defined \setstyle, \keys_show:nn just shows

>  code  =>  \keys_set:nV {dcp}\l_dcp_style_clist

which is not very helpful. Also, I would fully understand if this is not what you had in mind...

\documentclass{article}
\ExplSyntaxOn
\keys_define:nn { dcp }
  { 
    keya .tl_set:N = \l__dcp_keya_tl ,
    keyb .tl_set:N = \l__dcp_keyb_tl ,
    keyc .tl_set:N = \l__dcp_keyc_tl ,
    %style .choice:
  }
\clist_new:N \l_dcp_style_clist
\NewDocumentCommand \setstyle { s m }
  {
    \bool_if:NTF #1
      {
        % append to style
        \clist_put_right:Nn \l_dcp_style_clist { #2 }
      }
      {
        % set style
        \clist_set:Nn \l_dcp_style_clist { #2 }
      }
    \keys_define:nn { dcp }
      {
        style .code:n = \keys_set:nV { dcp } \l_dcp_style_clist
      }
  }
\NewDocumentCommand \showstyle { }
  {
    \keys_set:nn { dcp } { style }
    \l__dcp_keya_tl
    \l__dcp_keyb_tl
    \l__dcp_keyc_tl
  }
\ExplSyntaxOff

\begin{document}

\setstyle{keya=x,keyb=y}

\showstyle

\setstyle{keya=x,keyb=yy}

\showstyle

\setstyle*{keyc=z}

\showstyle

\end{document}

I've not benchmarked but it's possible precompiling offers some speed benefit; you could change the definition of \setstyle to

\cs_generate_variant:Nn \keys_precompile:nnN { nV }
\NewDocumentCommand \setstyle { s m }
  {
    \bool_if:NTF #1
      {
        % append to style
        \clist_put_right:Nn \l_dcp_style_clist { #2 }
      }
      {
        % set style
        \clist_set:Nn \l_dcp_style_clist { #2 }
      }
    \keys_precompile:nVN { dcp } \l_dcp_style_clist \l_dcp_stylekeys_tl
    \keys_define:nn { dcp }
      {
        style .code:n = \l_dcp_stylekeys_tl
      }
  }
mbert
  • 4,171