summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-08-07 21:37:39 +0000
committerKarl Berry <karl@freefriends.org>2020-08-07 21:37:39 +0000
commitd6a7e0e5536b4924edec286797ed38021b94509d (patch)
tree04407161e6a03a0698d3029183d3959a762a0bb2 /Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
parent5a14bab00bc59f46bdb92dcfc08ca2d331e3c3ec (diff)
l3 (7aug20)
git-svn-id: svn://tug.org/texlive/trunk@56067 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3keys.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3keys.dtx381
1 files changed, 212 insertions, 169 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
index 77fa7d1aff1..9c5216ceb6a 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
+++ b/Master/texmf-dist/source/latex/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}