%% %% This is file `keys3.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% keys3.dtx (with options: `package') %% --------------------------------------------------------------- %% The keys3 package --- Key management for LaTeX3 %% Maintained by Joseph Wright %% E-mail: joseph.wright@morningstar2.co.uk %% Released under the LaTeX Project Public License v1.3c or later %% See http://www.latex-project.org/lppl.txt %% --------------------------------------------------------------- %% %% EXPERIMENTAL CODE %% %% Do not distribute this file without also distributing the %% source files specified above. %% %% Do not distribute a modified version of this file. %% \RequirePackage{expl3} \GetIdInfo$Id: keys3.dtx 110 2009-06-12 21:27:24Z josephwright $ {Key management for LaTeX3} \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} \tl_new:Nn \c_keys_root_tl { keys~>~ } \tl_new:Nn \c_keys_properties_root_tl { keys_properties } \tl_new:Nn \c_keys_value_forbidden_tl { forbidden } \tl_new:Nn \c_keys_value_required_tl { required } \int_new:N \l_keys_choice_int \tl_new:N \l_keys_choice_tl \tl_new:N \l_keys_key_tl \tl_new:N \l_keys_path_tl \tl_new:N \l_keys_module_tl \bool_new:N \l_keys_no_value_bool \toks_new:N \l_keys_value_toks \cs_new_nopar:Nn \keys_bool_set:N { \keys_cmd_set:nNx { \l_keys_path_tl / true } 1 { \exp_not:c { bool_ \keys_variable_get_scope:N #1 set_true:N } \exp_not:N #1 } \keys_cmd_set:nNx { \l_keys_path_tl / false } 1 { \exp_not:N \use:c { bool_ \keys_variable_get_scope:N #1 set_false:N } \exp_not:N #1 } \keys_bool_set_aux:N #1 } \cs_new_nopar:Nn \keys_bool_set_inverse:N { \keys_cmd_set:nNx { \l_keys_path_tl / true } 1 { \exp_not:c { bool_ \keys_variable_get_scope:N #1 set_false:N } \exp_not:N #1 } \keys_cmd_set:nNx { \l_keys_path_tl / false } 1 { \exp_not:c { bool_ \keys_variable_get_scope:N #1 set_true:N } \exp_not:N #1 } \keys_bool_set_aux:N #1 } \cs_new_nopar:Nn \keys_bool_set_aux:N { \keys_choice_make: \cs_if_exist:NF #1 { \bool_new:N #1 } \keys_default_set:n { true } } \cs_new_nopar:Nn \keys_choice_find:n { \keys_execute_aux:nn { \l_keys_path_tl / #1 } { \keys_execute_aux:nn { \l_keys_path_tl / unknown } { } } } \cs_new_nopar:Nn \keys_choice_make: { \keys_cmd_set:nNn { \l_keys_path_tl } 1 { \keys_choice_find:n {##1} } \keys_cmd_set:nNn { \l_keys_path_tl / unknown } 1 { \msg_error:nnxx { keys } { choice~unknown } { \l_keys_path_tl } {##1} } } \cs_new:Nn \keys_choices_generate:nx { \keys_choice_make: \int_zero:N \l_keys_choice_int \cs_set_nopar:Nn \keys_choices_generate_aux:n { \int_incr:N \l_keys_choice_int \keys_cmd_set:nNx { \l_keys_path_tl / ##1 } 1 { \exp_not:n { \tl_set:Nn \l_keys_choice_tl } {##1} \exp_not:n { \int_set:Nn \l_keys_choice_int } { \int_use:N \l_keys_choice_int } #2 } } \clist_map_function:nN {#1} \keys_choices_generate_aux:n } \cs_new_nopar:Nn \keys_choices_generate_aux:n { } \cs_new:Nn \keys_cmd_set:nNn { \keys_cmd_set_aux:nN {#1} #2 \cs_generate_from_arg_count:cNnn { \c_keys_root_tl #1 .cmd:w } \cs_set:Npn #2 {#3} } \cs_new:Nn \keys_cmd_set:nNx { \keys_cmd_set_aux:nN {#1} #2 \cs_generate_from_arg_count:cNnn { \c_keys_root_tl #1 .cmd:w } \cs_set:Npx #2 {#3} } \cs_new_nopar:Nn \keys_cmd_set_aux:nN { \keys_property_undefine:n { #1 .default_tl } \num_set:cn { \c_keys_root_tl #1 .args_num } {#2} \tl_set:cn { \c_keys_root_tl #1 .req_tl } { } } \cs_new:Nn \keys_default_set:n { \tl_set:cn { \c_keys_root_tl \l_keys_path_tl .default_tl } {#1} } \cs_generate_variant:Nn \keys_default_set:n { V } \cs_new:Nn \keys_define:nn { \tl_set:Nn \l_keys_module_tl {#1} \cs_set_eq:NN \KV_key_no_value_elt:n \keys_define_elt:n \cs_set_eq:NN \KV_key_value_elt:nn \keys_define_elt:nn \KV_parse_no_space_removal_no_sanitize:n {#2} } \cs_new:Nn \keys_define_elt:n { \bool_set_true:N \l_keys_no_value_bool \keys_define_elt_aux:nn {#1} { } } \cs_new:Nn \keys_define_elt:nn { \bool_set_false:N \l_keys_no_value_bool \keys_define_elt_aux:nn {#1} {#2} } \cs_new:Nn \keys_define_elt_aux:nn { \keys_property_find:n {#1} \cs_set_eq:Nc \keys_tmp:w { \c_keys_properties_root_tl \l_keys_key_tl } \cs_if_exist:NTF \keys_tmp:w { \keys_define_key:n {#2} }{ \msg_error:nnx { keys } { property~unknown } { \l_keys_key_tl } } } \cs_new:Nn \keys_define_key:n { \bool_if:NTF \l_keys_no_value_bool { \intexpr_compare:nTF { \exp_args:Nc \cs_get_arg_count_from_signature:N { \l_keys_key_tl } = \c_zero } { \keys_tmp:w }{ \msg_error:nnx { keys } { property~value~required } { \l_keys_key_tl } } }{ \intexpr_compare:nTF { \exp_args:Nc \cs_get_arg_count_from_signature:N { \l_keys_key_tl } = \c_one } { \keys_tmp:w {#1} }{ \keys_tmp:w #1 } } } \cs_new_nopar:Nn \keys_execute: { \keys_execute_aux:nn { \l_keys_path_tl } { \keys_execute_unknown: } } \cs_new_nopar:Nn \keys_execute_unknown: { \keys_execute_aux:nn { \l_keys_module_tl / unknown } { \msg_error:nnx { keys } { key~unknown } { \l_keys_path_tl } } } \cs_new_nopar:Nn \keys_execute_aux:nn { \cs_set_eq:Nc \keys_tmp:w { \c_keys_root_tl #1 .cmd:w } \cs_if_exist:NTF \keys_tmp:w { \intexpr_compare:nTF { \num_use:c { \c_keys_root_tl #1 .args_num } = \c_one } { \exp_args:NV \keys_tmp:w \l_keys_value_toks }{ \exp_after:wN \keys_tmp:w \toks_use:N \l_keys_value_toks } }{ #2 } } \cs_new_nopar:Npn \keys_if_value_requirement:nTF #1 { \tl_if_eq:ccTF { c_keys_value_ #1 _tl } { \c_keys_root_tl \l_keys_path_tl .req_tl } } \cs_new_nopar:Nn \keys_property_find:n { \tl_set:Nx \l_keys_path_tl { \l_keys_module_tl / } \tl_if_in:nnTF {#1} {.} { \keys_property_find_aux:n {#1} }{ \msg_error:nnx { keys } { no~property } { #1 } } } \cs_new_nopar:Nn \keys_property_find_aux:n { \keys_property_find_aux:w #1 \q_stop } \cs_new_nopar:Npn \keys_property_find_aux:w #1 . #2 \q_stop { \tl_if_in:nnTF {#2} {.} { \tl_set:Nx \l_keys_path_tl { \l_keys_path_tl . #1 } \keys_property_find_aux:w #2 \q_stop }{ \tl_set:Nx \l_keys_path_tl { \l_keys_path_tl \tl_to_str:n {#1} } \tl_set:Nn \l_keys_key_tl { . #2 } } } \cs_new_nopar:Nn \keys_property_new:nn { \cs_new:cn { \c_keys_properties_root_tl #1 } {#2} } \cs_new_nopar:Nn \keys_property_undefine:n { \cs_set_eq:cN { \c_keys_root_tl #1 } \c_undefined } \cs_new:Nn \keys_set:nn { \tl_set:Nn \l_keys_module_tl {#1} \cs_set_eq:NN \KV_key_no_value_elt:n \keys_set_elt:n \cs_set_eq:NN \KV_key_value_elt:nn \keys_set_elt:nn \KV_parse_space_removal_sanitize:n {#2} } \cs_new:Nn \keys_set_elt:n { \bool_set_true:N \l_keys_no_value_bool \keys_set_elt_aux:nn {#1} { } } \cs_new:Nn \keys_set_elt:nn { \bool_set_false:N \l_keys_no_value_bool \keys_set_elt_aux:nn {#1} {#2} } \cs_new:Nn \keys_set_elt_aux:nn { \tl_set:Nx \l_keys_key_tl { \tl_to_str:n {#1} } \tl_set:Nx \l_keys_path_tl { \l_keys_module_tl / \l_keys_key_tl } \keys_value_or_default:n {#2} \keys_if_value_requirement:nTF { required } { \bool_if:NTF \l_keys_no_value_bool { \msg_error:nnx { keys } { key~value~required } { \l_keys_path_tl } }{ \keys_set_elt_aux: } }{ \keys_set_elt_aux: } } \cs_new_nopar:Nn \keys_set_elt_aux: { \keys_if_value_requirement:nTF { forbidden } { \bool_if:NTF \l_keys_no_value_bool { \keys_execute: }{ \msg_error:nnxx { keys} { key~value~forbidden } { \l_keys_path_tl } { \toks_use:N \l_keys_value_toks } } }{ \keys_execute: } } \cs_new_nopar:Nn \keys_show:nn { \cs_show:c { \c_keys_root_tl #1 / \tl_to_str:n {#2} .cmd:w } } \cs_new:Npn \keys_tmp:w {} \cs_new:Nn \keys_value_or_default:n { \toks_set:Nn \l_keys_value_toks {#1} \bool_if:NT \l_keys_no_value_bool { \cs_if_exist:cT { \c_keys_root_tl \l_keys_path_tl .default_tl } { \toks_set:Nv \l_keys_value_toks { \c_keys_root_tl \l_keys_path_tl .default_tl } } } } \cs_new_nopar:Nn \keys_value_requirement:n { \tl_set_eq:cc { \c_keys_root_tl \l_keys_path_tl .req_tl } { c_keys_value_ #1 _tl } } \cs_new_nopar:Nn \keys_variable_get_scope:N { \tl_if_eq:xxT { \token_to_str:N g } { \keys_variable_get_scope_aux:N #1 } { g } } \cs_new_nopar:Nn \keys_variable_get_scope_aux:N { \exp_last_unbraced:NNo \use_i:nn \use_i_delimit_by_q_stop:nw \token_to_str:N #1 \q_stop } \group_begin: \char_set_lccode:nn {`\&} {`\_} \char_make_other:N \& \tl_to_lowercase:n { \group_end: \cs_new_nopar:Nn \keys_variable_get_type:N { \exp_after:wN \keys_variable_get_type_aux:w \token_to_str:N #1 & \q_nil \q_stop } \cs_new_nopar:Npn \keys_variable_get_type_aux:w #1 & #2 \q_stop { \quark_if_nil:nTF {#2} { #1 }{ \keys_variable_get_type_aux:w #2 \q_stop } } } \cs_new_nopar:Nn \keys_variable_set:NN { \cs_if_exist:NF #2 { \use:c { \keys_variable_get_type:N #2 _new:N } #2 } \keys_cmd_set:nNx { \l_keys_path_tl } 1 { \exp_not:c { \keys_variable_get_type:N #2 _ \keys_variable_get_scope:N #2 set:N #1 } \exp_not:N #2 {##1} } } \keys_property_new:nn { .choice: } { \keys_choice_make: } \keys_property_new:nn { .code:n } { \keys_cmd_set:nNn { \l_keys_path_tl } 1 {#1} } \keys_property_new:nn { .code:Nn } { \keys_cmd_set:nNn { \l_keys_path_tl } #1 {#2} } \keys_property_new:nn { .code:x } { \keys_cmd_set:nNx { \l_keys_path_tl } 1 {#1} } \keys_property_new:nn { .code:Nx } { \keys_cmd_set:nNx { \l_keys_path_tl } #1 {#2} } \keys_property_new:nn { .default:n } { \keys_default_set:n {#1} } \keys_property_new:nn { .default:V } { \keys_default_set:V #1 } \keys_property_new:nn { .generate_choices:nn } { \keys_choices_generate:nx {#1} { \exp_not:n {#2} } } \keys_property_new:nn { .generate_choices:nx } { \keys_choices_generate:nx {#1} {#2} } \keys_property_new:nn { .set:N } { \keys_variable_set:NN n #1 } \keys_property_new:nn { .set_x:N } { \keys_variable_set:NN x #1 } \keys_property_new:nn { .set_bool:N } { \keys_bool_set:N #1 } \keys_property_new:nn { .set_bool_inverse:N } { \keys_bool_set_inverse:N #1 } \keys_property_new:nn { .value_forbidden: } { \keys_value_requirement:n { forbidden } } \keys_property_new:nn { .value_required: } { \keys_value_requirement:n { required } } \msg_new:nnn { keys } { choice~unknown } {% Choice `#2' unknown for key `#1':\\% the key is being ignored.% } \msg_new:nnn { keys } { key~unknown } {% The key `#1' is unknown and is being ignored.% } \msg_new:nnn { keys } { key~value~forbidden }{% The key `#1' cannot taken a value:\\% the given input `#2' is being ignored.% } \msg_new:nnn { keys } { key~value~required } {% The key `#1' requires a value\\% and is being ignored.% } \msg_new:nnn { keys } { no~property } {% No property given in definition of key `#1'.% } \msg_new:nnn { keys } { property~unknown } {% The key property `#1' is unknown.% } \msg_new:nnn { keys } { property~value~required } {% The property `#1' requires a value\\% and is being ignored.% } %% %% Copyright (C) 2008-2009 by %% Joseph Wright %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of %% this license or (at your option) any later version. The latest %% version of this license is in the file: %% %% http://www.latex-project.org/lppl.txt %% %% This work is "maintained" (as per LPPL maintenance status) by %% Joseph Wright. %% %% This work consists of the file keys3.dtx %% and the derived files keys3.pdf, %% keys3.sty and %% keys3.ins. %% %% %% End of file `keys3.sty'.