当使用 定义选择键时,l3keys2e
有两种可能的方法,我使用新包中的子键。当定义 watch 时,每个值应该做什么,interface3.pdf
我可以使用以下示例中的.code
哪个来完成key-b
,但我想直接使用 设置布尔值,.bool_set
如中所示key-a
。不幸的是,这似乎不起作用:当使用key-a=ch-a
as 选项时,编译会挂起。
\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
确实需要被赋予一个值( 或true
)false
。请注意,键的属性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-a
ch-a=true
true
ch-a
最后,代码编译挂起而不是产生错误,这是一个很好的迹象,表明 内部出了问题l3keys
。我不知道实现的细节,今天我也没有时间深入研究源代码以查看哪里出了问题——但这里有真正的专家,他们可以做得更好!与此同时,看起来你所做的是正确的key-b
。
更新(2014 年 5 月 21 日,19:40 GMT)
仔细阅读source3
可以发现问题的根本原因。为了确保使用.bool_set:N
属性定义的键仅接受true
和false
作为值,它在内部定义为选择键。实际上,编写
\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
。