l3keys 带值多选

l3keys 带值多选

我想要一个包来接受一个参数expl3的多个选择列表,其中每个值都是可选的,如果未指定则为默认值。key=booleanfalse

我仍然觉得通用的例子expl3太难理解了。因此,对于一个具体的例子,让我们制作一个food包含许多键的包,但我们只考虑一个名为的包fruit。此键应接受实际水果的列表,每个水果都可以选择带有值truefalse。当指定实际水果时,键处理应创建一个toggleetoolbox设置它,true除非它明确具有false参数值。未指定的水果应该有一个,togglefalse

我知道expl3bool,但我负担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}

输出演示

相关内容