使用选择键和选择设置布尔值

使用选择键和选择设置布尔值

当使用 定义选择键时,l3keys2e有两种可能的方法,我使用新包中的子键。当定义 watch 时,每个值应该做什么,interface3.pdf我可以使用以下示例中的.code哪个来完成key-b,但我想直接使用 设置布尔值,.bool_set如中所示key-a。不幸的是,这似乎不起作用:当使用key-a=ch-aas 选项时,编译会挂起。

\begin{filecontents}{test.sty}
% load xparse and identify package
\RequirePackage{xparse}
\ProvidesExplPackage{test}{2014/05/20}{0}{}

\RequirePackage{l3keys2e}

% define bools for key-b
\bool_new:N \l_test_key_b_a_bool
\bool_new:N \l_test_key_b_b_bool
% define keys
\keys_define:nn { testkeys } {
   % this won't work
   key-a .choice:,
      key-a / ch-a .bool_set:N = \l_test_key_a_a_bool,
      key-a / ch-b .bool_set:N = \l_test_key_a_b_bool,
   % this will work
   key-b .choice:,
      key-b / ch-a .code:n = { \bool_set_true:N \l_test_key_b_a_bool },
      key-b / ch-b .code:n = { \bool_set_true:N \l_test_key_b_b_bool },
}
\ProcessKeysOptions{ testkeys }

% demo-commands (real life is more complex ...)
\NewDocumentCommand { \getChoiceA } { } {
   \bool_if:NT \l_test_key_a_a_bool { ch-a }
   \bool_if:NT \l_test_key_a_b_bool { ch-b }
}
\NewDocumentCommand { \getChoiceB } { } {
   \bool_if:NT \l_test_key_b_a_bool { ch-a }
   \bool_if:NT \l_test_key_b_b_bool { ch-b }
}
\end{filecontents}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\documentclass{article}

\usepackage[
%   key-a=ch-a,% uncomment this line to see the problem
   key-b=ch-a
]{test}

\begin{document}
   Choice of key-a was: \getChoiceA

   Choice of key-b was: \getChoiceB
\end{document}

这是一个.bool_set无法使用她的错误,还是有一些我没有看到的明智的考虑?

答案1

在我看来,它确实像是一个错误,或者至少是一种非常不理想的行为。

从技术上讲,使用 属性定义的键.bool_set:N确实需要被赋予一个值( 或truefalse。请注意,键的属性key-a / ch-a不是.bool_set_true:N。事实上,目前还没有实现这样的属性l3keys。因此,可以说您定义的方式key-a违背了预期的语法,而您定义的方式key-b是正确的。

然而,像你这样的嵌套案例和非嵌套案例之间的关键区别在于

\keys_define:nn { testkeys } { key-c .bool_set:N = \l_test_key_c_bool }
\keys_set:nn { testkeys } { key-c }

在非嵌套情况下,布尔值将要true如果未提供任何值,则默认设置为。如果您将key-a / ch-a而不是传递key-a = ch-a给包,也会发生相同的情况。

ch-a使用以下方式在代码中添加显式默认值

\keys_define:nn { testkeys } 
  { 
    key-a / ch-a .default:n = { true } ,
    key-a / ch-b .default:n = { true } 
  }

也无济于事。传递key-a = { ch-a = true }会产生错误,因为在这种情况下会寻找名为“ ”l3keys下的选项,而不是传递给。key-ach-a=truetruech-a

最后,代码编译挂起而不是产生错误,这是一个很好的迹象,表明 内部出了问题l3keys。我不知道实现的细节,今天我也没有时间深入研究源代码以查看哪里出了问题——但这里有真正的专家,他们可以做得更好!与此同时,看起来你所做的是正确的key-b

更新(2014 年 5 月 21 日,19:40 GMT)

仔细阅读source3可以发现问题的根本原因。为了确保使用.bool_set:N属性定义的键仅接受truefalse作为值,它在内部定义为选择键。实际上,编写

\keys_define:nn { testkeys } { key-c .bool_set:N = \l_test_key_c_bool }

相当于写作

\keys_define:nn { testkeys } 
  { 
    key-c           .choice:                                              ,
    key-c           .default:n = { true }                                 ,
    key-c / true    .code:n    = { \bool_set_true:N  \l_test_key_c_bool } ,
    key-c / false   .code:n    = { \bool_set_false:N \l_test_key_c_bool } ,
    key-c / unknown .code:n    = 
      \__msg_kernel_error:nnx { kernel } { boolean-values-only }
        { \l_keys_key_tl } ,
  }

由于嵌套选择键(相当合理)不起作用,因此使用 定义另一个选择键的选项之一.bool_set:N不起作用。事实上,由于选择键路径的设置方式,您对 所做的操作key-a会导致无限循环,就像下面这样

\keys_define:nn { testkeys } 
  { 
    foo                 .choice:                ,
    foo                 .default:n = { bar }    ,
    foo / bar           .choice:                ,
    foo / bar           .default:n = { bar-a }  ,
    foo / bar / bar-a   .code:n    = { BAR-A }  ,
    foo / bar / bar-b   .code:n    = { BAR-B }  ,
    foo / buzz          .choice:                ,
    foo / buzz          .default:n = { buzz-a } ,
    foo / buzz / buzz-a .code:n    = { BUZZ-A } ,
    foo / buzz / buzz-b .code:n    = { BUZZ-B } ,
  }
\keys_set:nn { testkeys } { foo = bar }

虽然我认为这种行为对于不言而喻的选择键来说没问题,但我不认为这适合.bool_set:N,所以我将向邮件列表发送修复请求latex3

相关内容