diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3keys.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3keys.dtx | 381 |
1 files changed, 212 insertions, 169 deletions
diff --git a/macros/latex/contrib/l3kernel/l3keys.dtx b/macros/latex/contrib/l3kernel/l3keys.dtx index 77fa7d1aff..9c5216ceb6 100644 --- a/macros/latex/contrib/l3kernel/l3keys.dtx +++ b/macros/latex/contrib/l3kernel/l3keys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2020-07-17} +% \date{Released 2020-08-07} % % \maketitle % @@ -934,7 +934,7 @@ % \section{\pkg{l3keys} Implementation} % % \begin{macrocode} -%<*initex|package> +%<*package> % \end{macrocode} % % \subsection{Low-level interface} @@ -1493,44 +1493,29 @@ % % \subsubsection{Internal auxiliaries} % -% \begin{variable}{\s_@@_stop} +% \begin{variable}{\s_@@_nil,\s_@@_mark,\s_@@_stop} % Internal scan marks. % \begin{macrocode} +\scan_new:N \s_@@_nil +\scan_new:N \s_@@_mark \scan_new:N \s_@@_stop % \end{macrocode} % \end{variable} % -% \begin{variable}{\q_@@_nil,\q_@@_no_value} +% \begin{variable}{\q_@@_no_value} % Internal quarks. % \begin{macrocode} -\quark_new:N \q_@@_nil \quark_new:N \q_@@_no_value % \end{macrocode} % \end{variable} % -% \begin{macro}[pTF]{\@@_quark_if_nil:n} +% \begin{macro}[pTF]{\@@_quark_if_no_value:N} % Branching quark conditional. % \begin{macrocode} -\__kernel_quark_new_conditional:Nn \@@_quark_if_nil:n { TF } \__kernel_quark_new_conditional:Nn \@@_quark_if_no_value:N { TF } % \end{macrocode} % \end{macro} % -% \begin{variable}{\q_@@_recursion_tail,\q_@@_recursion_stop} -% Internal recursion quarks. -% \begin{macrocode} -\quark_new:N \q_@@_recursion_tail -\quark_new:N \q_@@_recursion_stop -% \end{macrocode} -% \end{variable} -% -% \begin{macro}[EXP]{\@@_if_recursion_tail_stop:n} -% Functions to query recursion quarks. -% \begin{macrocode} -\__kernel_quark_new_test:N \@@_if_recursion_tail_stop:n -% \end{macrocode} -% \end{macro} -% % \subsection{The key defining mechanism} % % \begin{macro}{\keys_define:nn} @@ -1580,7 +1565,7 @@ \str_if_empty:NF \l_@@_property_str { \__kernel_msg_error:nnxx { kernel } { key-property-unknown } - { \l_@@_property_str } { \l_keys_path_str } + \l_@@_property_str \l_keys_path_str } } } @@ -1590,53 +1575,59 @@ % \end{macro} % % \begin{macro}{\@@_property_find:n} -% \begin{macro}{\@@_property_find:w} +% \begin{macro} +% { +% \@@_property_find_auxi:w , +% \@@_property_find_auxii:w , +% \@@_property_find_auxiii:w , +% \@@_property_find_auxiv:w +% } % Searching for a property means finding the last |.| in the input, % and storing the text before and after it. Everything is turned into -% strings, so there is no problem using an \texttt{x}-type expansion. +% strings, so there is no problem using an \texttt{x}-type expansion. Since +% |\__keys_trim_spaces:n| will turn its argument into a string anyway, this +% function uses \cs{cs_set_nopar:Npx} instead of \cs{tl_set:Nx} to gain some +% speed. % \begin{macrocode} \cs_new_protected:Npn \@@_property_find:n #1 { - \str_set:Nx \l_@@_property_str { \@@_trim_spaces:n {#1} } - \exp_after:wN \@@_property_find:w \l_@@_property_str . . - \s_@@_stop {#1} + \cs_set_nopar:Npx \l__keys_property_str { \__keys_trim_spaces:n { #1 } } + \exp_after:wN \@@_property_find_auxi:w \l__keys_property_str + \s_@@_nil \@@_property_find_auxii:w + . \s_@@_nil \@@_property_find_err:w } -\cs_new_protected:Npn \@@_property_find:w #1 . #2 . #3 \s_@@_stop #4 +\cs_new_protected:Npn \@@_property_find_auxi:w #1 . #2 \s_@@_nil #3 { - \tl_if_blank:nTF {#3} - { - \str_clear:N \l_@@_property_str - \__kernel_msg_error:nnn { kernel } { key-no-property } {#4} - } - { - \str_if_eq:nnTF {#3} { . } - { - \str_set:Nx \l_keys_path_str - { - \str_if_empty:NF \l_@@_module_str - { \l_@@_module_str / } - \tl_trim_spaces:n {#1} - } - \str_set:Nn \l_@@_property_str { . #2 } - } - { - \str_set:Nx \l_keys_path_str { \l_@@_module_str / #1 . #2 } - \@@_property_search:w #3 \s_@@_stop - } - \tl_set_eq:NN \l_keys_path_tl \l_keys_path_str - } + #3 #1 \s_@@_mark #2 \s_@@_nil #3 } -\cs_new_protected:Npn \@@_property_search:w #1 . #2 \s_@@_stop +\cs_new_protected:Npn \@@_property_find_auxii:w + #1 \s_@@_mark #2 \s_@@_nil \@@_property_find_auxii:w . \s_@@_nil + \@@_property_find_err:w { - \str_if_eq:nnTF {#2} { . } - { - \str_set:Nx \l_keys_path_str { \l_keys_path_str } - \str_set:Nn \l_@@_property_str { . #1 } - } - { - \str_set:Nx \l_keys_path_str { \l_keys_path_str . #1 } - \@@_property_search:w #2 \s_@@_stop - } + \cs_set_nopar:Npx \l_keys_path_str + { \str_if_empty:NF \l__keys_module_str { \l__keys_module_str / } #1 } + \@@_property_find_auxi:w #2 \s_@@_nil \@@_property_find_auxiii:w . \s_@@_nil + \@@_property_find_auxiv:w + } +\cs_new_protected:Npn \@@_property_find_auxiii:w #1 \s_@@_mark + { + \cs_set_nopar:Npx \l_keys_path_str { \l_keys_path_str . #1 } + \@@_property_find_auxi:w + } +\cs_new_protected:Npn \@@_property_find_auxiv:w + #1 \s_@@_nil \@@_property_find_auxiii:w + \s_@@_mark \s_@@_nil \@@_property_find_auxiv:w + { + \cs_set_nopar:Npx \l__keys_property_str { . #1 } + \cs_set_nopar:Npx \l_keys_path_str + { \exp_after:wN \__keys_trim_spaces:n \exp_after:wN { \l_keys_path_str } } + \tl_set_eq:NN \l_keys_path_tl \l_keys_path_str + } +\cs_new_protected:Npn \@@_property_find_err:w + #1 \s_@@_nil #2 \@@_property_find_err:w + { + \str_clear:N \l__keys_property_str + \__kernel_msg_error:nnn { kernel } { key-no-property } {#1} } % \end{macrocode} % \end{macro} @@ -1658,9 +1649,8 @@ \l_@@_property_str \s_@@_stop { \use:c { \c_@@_props_root_str \l_@@_property_str } } { - \__kernel_msg_error:nnxx { kernel } - { key-property-requires-value } { \l_@@_property_str } - { \l_keys_path_str } + \__kernel_msg_error:nnxx { kernel } { key-property-requires-value } + \l_@@_property_str \l_keys_path_str } } { \use:c { \c_@@_props_root_str \l_@@_property_str } {#1} } @@ -1690,7 +1680,7 @@ \@@_cmd_set:nn { \l_keys_path_str / unknown } { \__kernel_msg_error:nnx { kernel } { boolean-values-only } - { \l_keys_key_str } + \l_keys_key_str } \@@_default_set:n { true } } @@ -1712,7 +1702,7 @@ \@@_cmd_set:nn { \l_keys_path_str / unknown } { \__kernel_msg_error:nnx { kernel } { boolean-values-only } - { \l_keys_key_str } + \l_keys_key_str } \@@_default_set:n { true } } @@ -1741,7 +1731,7 @@ { choice } { \__kernel_msg_error:nnxx { kernel } { nested-choice-key } - { \l_keys_path_tl } { \@@_parent:o \l_keys_path_str } + \l_keys_path_tl { \@@_parent:o \l_keys_path_str } } { \@@_choice_make_aux:N #1 } } @@ -1751,11 +1741,11 @@ { \cs_set_nopar:cpn { \c_@@_type_root_str \l_keys_path_str } { choice } - \@@_cmd_set:nn { \l_keys_path_str } { #1 {##1} } + \@@_cmd_set:nn \l_keys_path_str { #1 {##1} } \@@_cmd_set:nn { \l_keys_path_str / unknown } { \__kernel_msg_error:nnxx { kernel } { key-choice-unknown } - { \l_keys_path_str } {##1} + \l_keys_path_str {##1} } } % \end{macrocode} @@ -1886,7 +1876,8 @@ { \@@_execute_inherit: } { \str_clear:N \l_@@_inherit_str - \cs_if_exist_use:cT { \c_@@_code_root_str \l_keys_path_str } { {#1} } + \cs_if_exist:cT { \c_@@_code_root_str \l_keys_path_str } + { \@@_execute:nn \l_keys_path_str {#1} } } } % \end{macrocode} @@ -1900,8 +1891,7 @@ { \@@_cmd_set:Vo \l_keys_path_str { - \exp_after:wN \keys_set:nn - \exp_after:wN { \l_@@_module_str } {#1} + \exp_after:wN \keys_set:nn \exp_after:wN { \l_@@_module_str } {#1} } } \cs_new_protected:Npn \@@_meta_make:nn #1#2 @@ -1916,11 +1906,9 @@ \cs_new_protected:Npn \@@_prop_put:Nn #1#2 { \prop_if_exist:NF #1 { \prop_new:N #1 } - \exp_after:wN \@@_find_key_module:NNw - \exp_after:wN \l_@@_tmpa_tl - \exp_after:wN \l_@@_tmpb_tl - \l_keys_path_str / \s_@@_stop - \@@_cmd_set:nx { \l_keys_path_str } + \exp_after:wN \@@_find_key_module:wNN \l_keys_path_str \s_@@_stop + \l_@@_tmpa_tl \l_@@_tmpb_tl + \@@_cmd_set:nx \l_keys_path_str { \exp_not:c { prop_ #2 put:Nnn } \exp_not:N #1 @@ -1951,7 +1939,6 @@ % % \begin{macro}{\@@_value_requirement:nn} % \begin{macro}{\@@_validate_forbidden:, \@@_validate_required:} -% \begin{macro}{\@@_validate_cleanup:w} % Validating key input is done using a second function which runs before % the main key code. Setting that up means setting it equal to a generic % stub which does the check. This approach makes the lookup very fast at @@ -1991,8 +1978,8 @@ \bool_if:NF \l_@@_no_value_bool { \__kernel_msg_error:nnxx { kernel } { value-forbidden } - { \l_keys_path_str } { \l_keys_value_tl } - \@@_validate_cleanup:w + \l_keys_path_str \l_keys_value_tl + \use_none:nnn } } \cs_new_protected:Npn \@@_validate_required: @@ -2000,15 +1987,13 @@ \bool_if:NT \l_@@_no_value_bool { \__kernel_msg_error:nnx { kernel } { value-required } - { \l_keys_path_str } - \@@_validate_cleanup:w + \l_keys_path_str + \use_none:nnn } } -\cs_new_protected:Npn \@@_validate_cleanup:w #1 \cs_end: #2#3 { } % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro}{\@@_variable_set:NnnN, \@@_variable_set:cnnN} % \begin{macro}{\@@_variable_set_required:NnnN, \@@_variable_set_required:cnnN} @@ -2018,7 +2003,7 @@ \cs_new_protected:Npn \@@_variable_set:NnnN #1#2#3#4 { \use:c { #2_if_exist:NF } #1 { \use:c { #2 _new:N } #1 } - \@@_cmd_set:nx { \l_keys_path_str } + \@@_cmd_set:nx \l_keys_path_str { \exp_not:c { #2 _ #3 set:N #4 } \exp_not:N #1 @@ -2110,7 +2095,7 @@ % \texttt{set} function. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_str .code:n } #1 - { \@@_cmd_set:nn { \l_keys_path_str } {#1} } + { \@@_cmd_set:nn \l_keys_path_str {#1} } % \end{macrocode} % \end{macro} % @@ -2447,7 +2432,7 @@ \cs_new_protected:Npn \keys_set_known:nnN #1#2#3 { \exp_args:No \@@_set_known:nnnnN - \l_@@_unused_clist { \q_@@_no_value } {#1} {#2} #3 + \l_@@_unused_clist \q_@@_no_value {#1} {#2} #3 } \cs_generate_variant:Nn \keys_set_known:nnN { nV , nv , no } \cs_new_protected:Npn \keys_set_known:nnnN #1#2#3#4 @@ -2460,11 +2445,11 @@ { \clist_clear:N \l_@@_unused_clist \@@_set_known:nnn {#2} {#3} {#4} - \tl_set:Nx #5 { \exp_not:o { \l_@@_unused_clist } } + \tl_set:Nx #5 { \exp_not:o \l_@@_unused_clist } \tl_set:Nn \l_@@_unused_clist {#1} } \cs_new_protected:Npn \keys_set_known:nn #1#2 - { \@@_set_known:nnn { \q_@@_no_value } {#1} {#2} } + { \@@_set_known:nnn \q_@@_no_value {#1} {#2} } \cs_generate_variant:Nn \keys_set_known:nn { nV , nv , no } \cs_new_protected:Npn \@@_set_known:nnn #1#2#3 { @@ -2525,7 +2510,7 @@ { \exp_args:No \@@_set_filter:nnnnnN \l_@@_unused_clist - { \q_@@_no_value } {#1} {#2} {#3} #4 + \q_@@_no_value {#1} {#2} {#3} #4 } \cs_generate_variant:Nn \keys_set_filter:nnnN { nnV , nnv , nno } \cs_new_protected:Npn \keys_set_filter:nnnnN #1#2#3#4#5 @@ -2538,11 +2523,11 @@ { \clist_clear:N \l_@@_unused_clist \@@_set_filter:nnnn {#2} {#3} {#4} {#5} - \tl_set:Nx #6 { \exp_not:o { \l_@@_unused_clist } } + \tl_set:Nx #6 { \exp_not:o \l_@@_unused_clist } \tl_set:Nn \l_@@_unused_clist {#1} } \cs_new_protected:Npn \keys_set_filter:nnn #1#2#3 - {\@@_set_filter:nnnn { \q_@@_no_value } {#1} {#2} {#3} } + {\@@_set_filter:nnnn \q_@@_no_value {#1} {#2} {#3} } \cs_generate_variant:Nn \keys_set_filter:nnn { nnV , nnv , nno } \cs_new_protected:Npn \@@_set_filter:nnnn #1#2#3#4 { @@ -2604,7 +2589,14 @@ % % \begin{macro}{\@@_set_keyval:n, \@@_set_keyval:nn} % \begin{macro}{\@@_set_keyval:nnn, \@@_set_keyval:onn} -% \begin{macro}{\@@_find_key_module:NNw} +% \begin{macro}{\@@_find_key_module:wNN} +% \begin{macro} +% { +% \@@_find_key_module_auxi:Nw , +% \@@_find_key_module_auxii:Nw , +% \@@_find_key_module_auxiii:Nn , +% \@@_find_key_module_auxiv:Nw +% } % \begin{macro}{\@@_set_selective:} % A shared system once again. First, set the current path and add a % default if needed. There are then checks to see if the a value is @@ -2638,30 +2630,46 @@ } \str_clear:N \l_@@_module_str \str_clear:N \l_@@_inherit_str - \exp_after:wN \@@_find_key_module:NNw - \exp_after:wN \l_@@_module_str - \exp_after:wN \l_keys_key_str - \l_keys_path_str / \s_@@_stop + \exp_after:wN \@@_find_key_module:wNN \l_keys_path_str \s_@@_stop + \l_@@_module_str \l_keys_key_str \tl_set_eq:NN \l_keys_key_tl \l_keys_key_str \@@_value_or_default:n {#3} \bool_if:NTF \l_@@_selective_bool - { \@@_set_selective: } - { \@@_execute: } + \@@_set_selective: + \@@_execute: \str_set:Nn \l_@@_module_str {#1} } \cs_generate_variant:Nn \@@_set_keyval:nnn { o } -\cs_new_protected:Npn \@@_find_key_module:NNw #1#2#3 / #4 \s_@@_stop +% \end{macrocode} +% This function uses \cs{cs_set_nopar:Npx} internally for performance reasons, +% the argument |#1| is already a string in every usage, so turning it into a +% string again seems unnecessary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_find_key_module:wNN #1 \s_@@_stop #2 #3 { - \tl_if_blank:nTF {#4} - { \str_set:Nn #2 {#3} } - { - \str_put_right:Nx #1 - { - \str_if_empty:NF #1 { / } - #3 - } - \@@_find_key_module:NNw #1#2 #4 \s_@@_stop - } + \@@_find_key_module_auxi:Nw #2 #1 \s_@@_nil \@@_find_key_module_auxii:Nw + / \s_@@_nil \@@_find_key_module_auxiv:Nw #3 + } +\cs_new_protected:Npn \@@_find_key_module_auxi:Nw #1 #2 / #3 \s_@@_nil #4 + { + #4 #1 #2 \s_@@_mark #3 \s_@@_nil #4 + } +\cs_new_protected:Npn \@@_find_key_module_auxii:Nw + #1 #2 \s_@@_mark #3 \s_@@_nil \@@_find_key_module_auxii:Nw + { + \cs_set_nopar:Npx #1 { \tl_if_empty:NF #1 { #1 / } #2 } + \@@_find_key_module_auxi:Nw #1 #3 \s_@@_nil \@@_find_key_module_auxiii:Nw + } +\cs_new_protected:Npn \@@_find_key_module_auxiii:Nw #1 #2 \s_@@_mark + { + \cs_set_nopar:Npx #1 { \tl_if_empty:NF #1 { #1 / } #2 } + \@@_find_key_module_auxi:Nw #1 + } +\cs_new_protected:Npn \@@_find_key_module_auxiv:Nw + #1 #2 \s_@@_nil #3 \s_@@_mark + \s_@@_nil \@@_find_key_module_auxiv:Nw #4 + { + \cs_set_nopar:Npn #4 { #2 } } % \end{macrocode} % If selective setting is active, there are a number of possible sub-cases @@ -2679,8 +2687,8 @@ } { \bool_if:NTF \l_@@_filtered_bool - { \@@_execute: } - { \@@_store_unused: } + \@@_execute: + \@@_store_unused: } } % \end{macrocode} @@ -2699,20 +2707,20 @@ \str_if_eq:nnT {##1} {####1} { \bool_set_true:N \l_@@_tmp_bool - \clist_map_break:n { \seq_map_break: } + \clist_map_break:n \seq_map_break: } } } \bool_if:NTF \l_@@_tmp_bool { \bool_if:NTF \l_@@_filtered_bool - { \@@_store_unused: } - { \@@_execute: } + \@@_store_unused: + \@@_execute: } { \bool_if:NTF \l_@@_filtered_bool - { \@@_execute: } - { \@@_store_unused: } + \@@_execute: + \@@_store_unused: } } % \end{macrocode} @@ -2720,6 +2728,7 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\@@_value_or_default:n} % \begin{macro}{\@@_default_inherit:} @@ -2765,7 +2774,7 @@ % \end{macro} % % \begin{macro}{\@@_execute:, \@@_execute_inherit:, \@@_execute_unknown:} -% \begin{macro}[EXP]{\@@_execute:nn} +% \begin{macro}[EXP]{\@@_execute:nn, \@@_execute:no} % \begin{macro}{\@@_store_unused:,\@@_store_unused_aux:} % Actually executing a key is done in two parts. First, look for the % key itself, then look for the \texttt{unknown} key with the same @@ -2778,8 +2787,7 @@ \cs_if_exist:cTF { \c_@@_code_root_str \l_keys_path_str } { \cs_if_exist_use:c { \c_@@_validate_root_str \l_keys_path_str } - \cs:w \c_@@_code_root_str \l_keys_path_str \exp_after:wN \cs_end: - \exp_after:wN { \l_keys_value_tl } + \@@_execute:no \l_keys_path_str \l_keys_value_tl } { \cs_if_exist:cTF @@ -2803,10 +2811,8 @@ { \str_set:Nn \l_@@_inherit_str {##1} \cs_if_exist_use:c { \c_@@_validate_root_str ##1 / \l_keys_key_str } - \cs:w \c_@@_code_root_str ##1 / \l_keys_key_str - \exp_after:wN \cs_end: \exp_after:wN - { \l_keys_value_tl } - \clist_map_break:n { \use_none:n } + \@@_execute:no { ##1 / \l_keys_key_str } \l_keys_value_tl + \clist_map_break:n \use_none:n } } \@@_execute_unknown: @@ -2818,24 +2824,35 @@ { \cs_if_exist:cTF { \c_@@_code_root_str \l_@@_module_str / unknown } - { - \cs:w \c_@@_code_root_str \l_@@_module_str / unknown - \exp_after:wN \cs_end: \exp_after:wN { \l_keys_value_tl } - } + { \@@_execute:no { \l_@@_module_str / unknown } \l_keys_value_tl } { \__kernel_msg_error:nnxx { kernel } { key-unknown } - { \l_keys_path_str } { \l_@@_module_str } + \l_keys_path_str \l_@@_module_str } } } +% \end{macrocode} +% A key's code is in the control sequence with csname +% \cs{c_@@_code_root_str} |#1|. We expand it once to get the +% replacement text (with argument |#2|) and call \cs{use:n} +% with this replacement as its argument. This ensures that any +% undefined control sequence error in the key's code will lead to an +% error message of the form |<argument>|\ldots{}\meta{control +% sequence} in which one can read the (undefined) \meta{control +% sequence} in full, rather than an error message that starts with the +% potentially very long key name, which would make the (undefined) +% \meta{control sequence} be truncated or sometimes completely hidden. +% See \url{https://github.com/latex3/latex2e/issues/351}. +% \begin{macrocode} \cs_new:Npn \@@_execute:nn #1#2 + { \@@_execute:no {#1} { \prg_do_nothing: #2 } } +\cs_new:Npn \@@_execute:no #1#2 { - \cs_if_exist:cTF { \c_@@_code_root_str #1 } + \exp_args:NNo \exp_args:No \use:n { \cs:w \c_@@_code_root_str #1 \exp_after:wN \cs_end: - \exp_after:wN { \l_keys_value_tl } + \exp_after:wN {#2} } - {#2} } % \end{macrocode} % When there is no relative path, things here are easy: just save the key @@ -2850,7 +2867,7 @@ { \clist_put_right:Nx \l_@@_unused_clist { - \exp_not:o \l_keys_key_str + \l_keys_key_str \bool_if:NF \l_@@_no_value_bool { = { \exp_not:o \l_keys_value_tl } } } @@ -2860,7 +2877,7 @@ { \clist_put_right:Nx \l_@@_unused_clist { - \exp_not:o \l_keys_path_str + \l_keys_path_str \bool_if:NF \l_@@_no_value_bool { = { \exp_not:o \l_keys_value_tl } } } @@ -2917,7 +2934,7 @@ \cs_new:Npn \@@_choice_find:n #1 { \str_if_empty:NTF \l_@@_inherit_str - { \@@_choice_find:nn { \l_keys_path_str } {#1} } + { \@@_choice_find:nn \l_keys_path_str {#1} } { \@@_choice_find:nn { \l_@@_inherit_str / \l_keys_key_str } {#1} @@ -2926,8 +2943,8 @@ \cs_new:Npn \@@_choice_find:nn #1#2 { \cs_if_exist:cTF { \c_@@_code_root_str #1 / \@@_trim_spaces:n {#2} } - { \use:c { \c_@@_code_root_str #1 / \@@_trim_spaces:n {#2} } {#2} } - { \use:c { \c_@@_code_root_str #1 / unknown } {#2} } + { \@@_execute:nn { #1 / \@@_trim_spaces:n {#2} } {#2} } + { \@@_execute:nn { #1 / unknown } {#2} } } \cs_new:Npn \@@_multichoice_find:n #1 { \clist_map_function:nN {#1} \@@_choice_find:n } @@ -2938,23 +2955,35 @@ % % \subsection{Utilities} % -% \begin{macro}[EXP]{\@@_parent:n, \@@_parent:o} -% \begin{macro}[EXP]{\@@_parent:w} +% \begin{macro}[EXP]{\@@_parent:o} +% \begin{macro}[EXP] +% { +% \@@_parent_auxi:w , +% \@@_parent_auxii:w , +% \@@_parent_auxiii:n , +% \@@_parent_auxiv:w +% } % Used to strip off the ending part of the key path after the last~|/|. % \begin{macrocode} -\cs_new:Npn \@@_parent:n #1 - { \@@_parent:w #1 / / \s_@@_stop { } } -\cs_generate_variant:Nn \@@_parent:n { o } -\cs_new:Npn \@@_parent:w #1 / #2 / #3 \s_@@_stop #4 +\cs_new:Npn \@@_parent:o #1 + { + \exp_after:wN \@@_parent_auxi:w #1 \q_nil \@@_parent_auxii:w + / \q_nil \@@_parent_auxiv:w + } +\cs_new:Npn \@@_parent_auxi:w #1 / #2 \q_nil #3 + { + #3 { #1 } #2 \q_nil #3 + } +\cs_new:Npn \@@_parent_auxii:w #1 #2 \q_nil \@@_parent_auxii:w + { + #1 \@@_parent_auxi:w #2 \q_nil \@@_parent_auxiii:n + } +\cs_new:Npn \@@_parent_auxiii:n #1 + { + / #1 \@@_parent_auxi:w + } +\cs_new:Npn \@@_parent_auxiv:w #1 \q_nil \@@_parent_auxiv:w { - \tl_if_blank:nTF {#2} - { - \tl_if_blank:nF {#4} - { \use_none:n #4 } - } - { - \@@_parent:w #2 / #3 \s_@@_stop { #4 / #1 } - } } % \end{macrocode} % \end{macro} @@ -2968,29 +2997,43 @@ % \@@_trim_spaces_auxiii:w % } % Space stripping has to allow for the fact that the key here might have -% several parts, and spaces need to be stripped from each part. +% several parts, and spaces need to be stripped from each part. Since the key +% name is turned into a string groups can't be stripped accidentally and the +% precautions of \cs{tl_trim_spaces:n} aren't necessary, in this case it is +% much faster to just directly strip spaces around |/|. % \begin{macrocode} -\cs_new:Npn \@@_trim_spaces:n #1 - { - \exp_after:wN \@@_trim_spaces_auxi:w \tl_to_str:n {#1} - / \q_@@_nil \s_@@_stop - } -\cs_new:Npn \@@_trim_spaces_auxi:w #1 / #2 \s_@@_stop +\group_begin: + \cs_set:Npn \@@_tmp:n #1 + { + \cs_new:Npn \@@_trim_spaces:n ##1 + { + \exp_after:wN \@@_trim_spaces_auxi:w \tl_to_str:n { / ##1 } / + \s_@@_nil \@@_trim_spaces_auxi:w + \s_@@_mark \@@_trim_spaces_auxii:w + #1 / #1 + \s_@@_nil \@@_trim_spaces_auxii:w + \s_@@_mark \@@_trim_spaces_auxiii:w + } + } + \@@_tmp:n { ~ } +\group_end: +\cs_new:Npn \@@_trim_spaces_auxi:w #1 ~ / #2 \s_@@_nil #3 { - \@@_quark_if_nil:nTF {#2} - { \tl_trim_spaces:n {#1} } - { \@@_trim_spaces_auxii:w #1 / #2 } + #3 #1 / #2 \s_@@_nil #3 } -\cs_new:Npn \@@_trim_spaces_auxii:w #1 / #2 / \q_@@_nil +\cs_new:Npn \@@_trim_spaces_auxii:w #1 / ~ #2 \s_@@_mark #3 { - \tl_trim_spaces:n {#1} - \@@_trim_spaces_auxiii:w #2 / \q_@@_recursion_tail / \q_@@_recursion_stop + #3 #1 / #2 \s_@@_mark #3 } -\cs_set:Npn \@@_trim_spaces_auxiii:w #1 / +\cs_new:Npn \@@_trim_spaces_auxiii:w + / #1 / + \s_@@_nil \@@_trim_spaces_auxi:w + \s_@@_mark \@@_trim_spaces_auxii:w + / + \s_@@_nil \@@_trim_spaces_auxii:w + \s_@@_mark \@@_trim_spaces_auxiii:w { - \@@_if_recursion_tail_stop:n {#1} - / \tl_trim_spaces:n { #1 } - \@@_trim_spaces_auxiii:w + #1 } % \end{macrocode} % \end{macro} @@ -3102,7 +3145,7 @@ % \end{macrocode} % % \begin{macrocode} -%</initex|package> +%</package> % \end{macrocode} % %\end{implementation} |