我想要一个包来接受一个参数expl3
的多个选择列表,其中每个值都是可选的,如果未指定则为默认值。key=boolean
false
我仍然觉得通用的例子expl3
太难理解了。因此,对于一个具体的例子,让我们制作一个food
包含许多键的包,但我们只考虑一个名为的包fruit
。此键应接受实际水果的列表,每个水果都可以选择带有值true
或false
。当指定实际水果时,键处理应创建一个toggle
并etoolbox
设置它,true
除非它明确具有false
参数值。未指定的水果应该有一个,toggle
即false
。
我知道expl3
有bool
,但我负担expl3
过重,而且我忘了买头痛药,因为我的 LaTeX 购物清单还不能用。另外,我希望expl3
现在主文档中的切换功能可以轻松使用。
最小不工作片段
\RequirePackage{etoolbox} % for toggles
\providetoggle{fruitapple} \providetoggle{fruitbanana}
\providetoggle{fruitcherry} \providetoggle{fruitdurian}
\providetoggle{fruitelderberry} \providetoggle{fruitfig}
% yawn, there must be a way to loop over a list to make the toggles
\keys_define:nn { food }
{
fruit .multichoices:nn =
{ apple, banana, cherry,
durian, elderberry, fig
} % ideally reuse the list of allowed fruit that made the toggles
{
\iow_term:x { % from l3keys manual
You~gave~choice~'\tl_use:N \l_keys_choice_tl'~
which~is~in~position~
\int_use:N \l_keys_choice_int \c_space_tl
in~the~list.
}
% some missing logic to determine the value of the current key... then
\toggletrue{fruit\tl_use:N \l_keys_choice_tl}
}
}
这适用于指定原始列表
\usepackage[fruit={apple, banana, durian}]{food}
You gave choice 'apple' which is in position 1 in the list.
You gave choice 'banana' which is in position 2 in the list.
You gave choice 'durian' which is in position 4 in the list.
\begin{document}
\iftoggle{fruitapple}{Buy apples}{No apples}
\end{document}
Buy apples
但如果添加任何值,则需要在 1 号通道进行清理
\usepackage[fruit={apple, banana=true, cherry=false}]{food}
You gave choice 'apple' which is in position 1 in the list.
LaTeX Error: Key 'food/fruit' accepts only a fixed set of choices.
除了搜索此网站和更广泛的互联网之外,我还搜索了我安装的 MikTeX 的源代码以查找示例。我没有找到任何类似的东西。软件包昨天已更新。
答案1
这里没有简单的键,参数实际上是另一个键值,因此如果您想使用键,则必须嵌套调用:
\documentclass[12pt]{article}
\RequirePackage{etoolbox} % for toggles
\ExplSyntaxOn
\clist_new:N\l_food_fruits_clist
\clist_set:Nn\l_food_fruits_clist {apple,banana,cherry,durian,elderberry,fig}
\clist_map_inline:Nn \l_food_fruits_clist
{ \providetoggle{fruit#1} }
\keys_define:nn { food }
{
fruit .code:n =
{
\keys_set:nn { food / fruit}{ #1 }
}
}
\clist_map_inline:Nn \l_food_fruits_clist
{
\keys_define:nn { food/fruit }
{
#1 .choice:,
#1 / true .code:n =
{
\iow_term:x { you~gave~#1~the~value~##1}
\toggletrue {fruit#1}
},
#1 / false .code:n =
{
\iow_term:x { you~gave~#1~the~value~##1}
\togglefalse{fruit#1}
},
#1 .default:n = {true}
}
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\keys_set:nn {food}{fruit={apple, banana=true, cherry=false}}
\ExplSyntaxOff
\iftoggle{fruitapple}{Buy apples}{No apples}
\iftoggle{fruitcherry}{Buy cherries}{No cherries}
\end{document}
答案2
我认为使用l3keys
这里没有意义,因为它更适合“代码”。您应该使用嵌套的“属性列表”,因为它们是为存储数据而设计的。
我不完全确定您正在寻找哪种界面,但您可以尝试这个:
\documentclass[12pt]{article}
\ExplSyntaxOn
\prop_new:N \l_food_prop
\cs_generate_variant:Nn \prop_put_from_keyval:Nn { NV, Ne }
\NewDocumentCommand \setfood { m } {
\prop_set_from_keyval:Nn \l_tmpa_prop { #1 }
\prop_map_inline:Nn \l_tmpa_prop {
\prop_get:NnNF \l_tmpb_prop { ##1 } {
\prop_clear:N \l_tmpb_prop
}
\prop_clear:N \l_tmpb_prop
\clist_set:Nn \l_tmpa_clist { ##2 }
\clist_map_variable:NNn \l_tmpa_clist \l_tmpa_tl {
\tl_if_in:NnF \l_tmpa_tl { = } {
\tl_put_right:Nn \l_tmpa_tl { = false }
}
\prop_put_from_keyval:NV \l_tmpb_prop \l_tmpa_tl
}
\prop_put_from_keyval:Ne \l_food_prop { ##1 = \l_tmpb_prop }
}
}
\tl_new:N \l_food_tl
\NewDocumentCommand \iffoodexists { m m m m } {
\prop_get:NnN \l_food_prop { #1 } \l_tmpa_prop
\prop_get:NnN \l_tmpa_prop { #2 } \l_food_tl
\quark_if_no_value:NTF \l_food_tl {
#4
} {
#3
}
}
\NewDocumentCommand \foodvalue { m m } {
\iffoodexists { #1 } { #2 } { \l_food_tl } { (empty) }
}
\ExplSyntaxOff
\begin{document}
\setfood{
fruit={
apple,
banana=true,
},
vegetable={
avocado=false,
},
}
fruit/apple: \foodvalue{fruit}{apple}
fruit/banana: \foodvalue{fruit}{banana}
fruit/cherry: \foodvalue{fruit}{cherry}
vegetable/avocado: \foodvalue{vegetable}{avocado}
\setfood{fruit={apple=true}, spice={allspice}}
fruit/apple: \foodvalue{fruit}{apple}
spice/allspice: \foodvalue{spice}{allspice}
animal/aardvark: \iffoodexists{animal}{aardvark}{Aardvark!}{That's not a food!}
\end{document}