为什么我无法正确重置 l3keys 中的按键?

为什么我无法正确重置 l3keys 中的按键?

为了帮助我学习,l3keys我创建了两个小演示。

第一个用于l3keys命令,据我所知,它似乎工作正常。

% !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}

输出如下:

第一个 MWE 的输出

第二个用于l3keys包,似乎工作正常,除了密钥无法正确初始化的情况。

% !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}

输出如下:

第二个 MWE 的输出

在第二个演示中,第二次出现Tom应该是理想情况,Ina但我不明白为什么密钥没有重置。这个问题似乎相关,但我认为我已经在使用那里的解决方案,要么我做错了,要么我没有理解一些简单的事情。这两个演示能给出相同的结果吗?

答案1

属性initial:n是变量被设置为\keys_define:nn是执行IE相当于应用\keys_set:nn。因此它只应用一次。如果要在 开始之前重置键,\keys_set:nn如果键未设置在组中,请将键添加到列表的开头:

\keys_set:nn { foopkg } { towhom = Ina , #1 }

答案2

原因在约瑟夫的回答.initial:n仅设置一次密钥。

您不必每次都向列表中添加键并引入解析开销,只需解析一次 key=value 对,并将结果编译成用于重置键的标记列表:

% !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}

一个小小的变化,我认为这比使用tl重置值更正确:

% !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}

相关内容