我正在尝试创建一个选项l3keys
,如果它收到一个值,即使是一个空值,它也会添加到属性列表中,但如果它没有收到任何值,它就会从属性列表中删除。
但是,我似乎无法在“操作”中区分。我知道可以key
捕获这种情况,但它不能接收代码块,只能接收值。我也知道我可以在中区分这种情况,但我希望在整个集合中的某些选项中实现这种行为,而对整个事物使用会变得复杂。key=
.code:n
.default:n
\keyval_parse:nnn
\keyval_parse:nnn
MWE 说明了这种情况:
\documentclass{article}
\ExplSyntaxOn
\prop_new:N \l__myprops_prop
\keys_define:nn { options }
{
mykey .code:n =
{
\tl_if_novalue:nTF {#1}
{ \prop_remove:Nn \l__myprops_prop { mykey } }
{ \prop_put:Nnn \l__myprops_prop { mykey } {#1} }
\prop_show:N \l__myprops_prop
} ,
mykey2 .code:n =
{
\tl_if_empty:nTF {#1}
{ \prop_remove:Nn \l__myprops_prop { mykey2 } }
{ \prop_put:Nnn \l__myprops_prop { mykey2 } {#1} }
\prop_show:N \l__myprops_prop
}
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\keys_set:nn { options } { mykey }
\keys_set:nn { options } { mykey= }
\keys_set:nn { options } { mykey=val }
\prop_clear:N \l__myprops_prop
\keys_set:nn { options } { mykey2 }
\keys_set:nn { options } { mykey2= }
\keys_set:nn { options } { mykey2=val }
\ExplSyntaxOff
\end{document}
本文档的日志包含:
The property list \l__myprops_prop contains the pairs (without outer braces):
> {mykey} => {}.
<recently read> }
l.27 \keys_set:nn { options } { mykey }
The property list \l__myprops_prop contains the pairs (without outer braces):
> {mykey} => {}.
<recently read> }
l.28 \keys_set:nn { options } { mykey= }
The property list \l__myprops_prop contains the pairs (without outer braces):
> {mykey} => {val}.
<recently read> }
l.29 \keys_set:nn { options } { mykey=val }
The property list \l__myprops_prop is empty
> .
<recently read> }
l.31 \keys_set:nn { options } { mykey2 }
The property list \l__myprops_prop is empty
> .
<recently read> }
l.32 \keys_set:nn { options } { mykey2= }
The property list \l__myprops_prop contains the pairs (without outer braces):
> {mykey2} => {val}.
<recently read> }
l.33 \keys_set:nn { options } { mykey2=val }
这表明key
和 都没有key=
通过“无值”测试,而 和 都key
通过key=
了空值测试。不幸的是,我无法使用空值来“表示”删除,因为“空”是所讨论键的有效值。这确实是\keyval_parse:nnn
这里唯一的选择吗?
答案1
这建立在与 @Phelype 的答案相同的基本思想上,即用作\c_novalue_tl
标记,但不是环绕\keyval_parse:nnn
它\keys_set:nn
,而是使用.default:x
处理程序将默认值设置为\c_novalue_tl
:
\documentclass{article}
\ExplSyntaxOn
\prop_new:N \l__myprops_prop
\cs_new_protected:Npn \__myprops_handle:n #1
{
\tl_if_novalue:nTF {#1}
{ \prop_remove:NV \l__myprops_prop \l_keys_key_str }
{ \prop_put:NVn \l__myprops_prop \l_keys_key_str {#1} }
\prop_show:N \l__myprops_prop
}
\keys_define:nn { options }
{
mykey .code:n = \__myprops_handle:n {#1}
,mykey .default:x = \c_novalue_tl
,mykey2 .code:n = \__myprops_handle:n {#1}
,mykey2 .default:x = \c_novalue_tl
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\keys_set:nn { options } { mykey }
\keys_set:nn { options } { mykey= }
\keys_set:nn { options } { mykey=val }
\prop_clear:N \l__myprops_prop
\keys_set:nn { options } { mykey2 }
\keys_set:nn { options } { mykey2= }
\keys_set:nn { options } { mykey2=val }
\ExplSyntaxOff
\end{document}
答案2
没有内置方法来区分mykey
何时mykey={}
使用处理程序进行声明.code:n
。在内部,这些情况是不同的,并且有一个布尔变量可以跟踪这些情况,但所有变量都使用来自的私有变量l3keys
。
您可以使用可用的接口来执行的操作是使用\keyval_parse:nnn
,正如您所建议的那样,区分两种情况,然后在mykey
使用 时将其转换为mykey = \c_novalue_tl
,然后密钥中的代码可以检测到使用\tl_if_novalue:nTF
。这使得解析比仅使用 慢一点,\keys_set:nn
因为 中的一些常见簿记代码\keys_set:nn
执行得更频繁,但这可能是最小的。
下面的示例实现了,如果没有给出值,\gusbrs_keys_set:nn
则传递给一个键:\c_novalue_tl
\documentclass{article}
\ExplSyntaxOn
\cs_new_protected:Npn \gusbrs_keys_set:nn #1 #2
{
\keyval_parse:nnn
{ \__gusbrs_keys_set:nn {#1} }
{ \__gusbrs_keys_set:nnn {#1} }
{#2}
}
\cs_new_protected:Npn \__gusbrs_keys_set:nn #1 #2
{ \use:x { \keys_set:nn {#1} { #2 = \c_novalue_tl } } }
\cs_new_protected:Npn \__gusbrs_keys_set:nnn #1 #2 #3
{ \keys_set:nn {#1} { #2 = #3 } }
\ExplSyntaxOff
\ExplSyntaxOn
\prop_new:N \l__myprops_prop
\keys_define:nn { options }
{
mykey .code:n =
{
\tl_if_novalue:nTF {#1}
{ \prop_remove:Nn \l__myprops_prop { mykey } }
{ \prop_put:Nnn \l__myprops_prop { mykey } {#1} }
\prop_show:N \l__myprops_prop
} ,
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\gusbrs_keys_set:nn { options } { mykey }
\gusbrs_keys_set:nn { options } { mykey= }
\gusbrs_keys_set:nn { options } { mykey=val }
\ExplSyntaxOff
\end{document}
这打印在终端上:
The property list \l__myprops_prop is empty
> .
<recently read> }
l.35 \gusbrs_keys_set:nn { options } { mykey }
?
The property list \l__myprops_prop contains the pairs (without outer braces):
> {mykey} => {}.
<recently read> }
l.36 \gusbrs_keys_set:nn { options } { mykey= }
?
The property list \l__myprops_prop contains the pairs (without outer braces):
> {mykey} => {val}.
<recently read> }
l.37 \gusbrs_keys_set:nn { options } { mykey=val }
?