diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3keys.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3keys.dtx | 161 |
1 files changed, 105 insertions, 56 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index d1f9f192687..860854cc779 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -2,7 +2,7 @@ % %% File: l3keys.dtx % -% Copyright (C) 2006-2020 The LaTeX3 Project +% Copyright (C) 2006-2021 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2020-12-07} +% \date{Released 2021-01-09} % % \maketitle % @@ -891,7 +891,45 @@ % \end{verbatim} % are treated identically. % -% \begin{function}[EXP,updated = 2020-02-20]{\keyval_parse:NNn} +% \begin{function}[rEXP, added=2020-12-19]{\keyval_parse:nnn} +% \begin{syntax} +% \cs{keyval_parse:nnn} \Arg{code_1} \Arg{code_2} \Arg{key--value list} +% \end{syntax} +% Parses the \meta{key--value list} into a series of \meta{keys} and +% associated \meta{values}, or keys alone (if no \meta{value} was +% given). \meta{code_1} receives each \meta{key} (with no \meta{value}) as a +% trailing brace group, whereas \meta{code_2} is appended by two brace groups, +% the \meta{key} and \meta{value}. +% The order of the \meta{keys} in the \meta{key--value list} +% is preserved. Thus +% \begin{verbatim} +% \keyval_parse:nnn +% { \use_none:nn { code 1 } } +% { \use_none:nnn { code 2 } } +% { key1 = value1 , key2 = value2, key3 = , key4 } +% \end{verbatim} +% is converted into an input stream +% \begin{verbatim} +% \use_none:nnn { code 2 } { key1 } { value1 } +% \use_none:nnn { code 2 } { key2 } { value2 } +% \use_none:nnn { code 2 } { key3 } { } +% \use_none:nn { code 1 } { key4 } +% \end{verbatim} +% Note that there is a difference between an empty value (an equals +% sign followed by nothing) and a missing value (no equals sign at +% all). Spaces are trimmed from the ends of the \meta{key} and \meta{value}, +% then one \emph{outer} set of braces is removed from the \meta{key} +% and \meta{value} as part of the processing. If you need exactly the output +% shown above, you'll need to either \texttt{x}-type or \texttt{e}-type expand +% the function. +% \begin{texnote} +% The result of each list element is returned within \cs{exp_not:n}, which +% means that the converted input stream does not expand further when +% appearing in an \texttt{x}-type or \texttt{e}-type argument expansion. +% \end{texnote} +% \end{function} +% +% \begin{function}[rEXP,updated = 2020-12-19]{\keyval_parse:NNn} % \begin{syntax} % \cs{keyval_parse:NNn} \meta{function_1} \meta{function_2} \Arg{key--value list} % \end{syntax} @@ -920,6 +958,9 @@ % all). Spaces are trimmed from the ends of the \meta{key} and \meta{value}, % then one \emph{outer} set of braces is removed from the \meta{key} % and \meta{value} as part of the processing. +% +% This shares the implementation of \cs{keyval_parse:nnn}, the difference is +% only semantically. % \begin{texnote} % The result is returned within \cs{exp_not:n}, which means that the % converted input stream does not expand further when appearing in an @@ -969,30 +1010,31 @@ { % \end{macrocode} % -% \begin{macro}[EXP]{\keyval_parse:NNn} +% \begin{macro}[EXP]{\keyval_parse:nnn, \keyval_parse:NNn} % The main function starts the first of two loops. The outer loop splits the % key--value list at active commas, the inner loop will do so at other commas. % The use of \cs{s_@@_mark} here prevents loss of braces from the key % argument. % \begin{macrocode} - \cs_new:Npn \keyval_parse:NNn ##1 ##2 ##3 - { \@@_loop_active:NNw ##1 ##2 \s_@@_mark ##3 #1 \s_@@_tail #1 } + \cs_new:Npn \keyval_parse:nnn ##1 ##2 ##3 + { \@@_loop_active:nnw {##1} {##2} \s_@@_mark ##3 #1 \s_@@_tail #1 } + \cs_new_eq:NN \keyval_parse:NNn \keyval_parse:nnn % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_loop_active:NNw} +% \begin{macro}[EXP]{\@@_loop_active:nnw} % First a fast test for the end of the loop is done, it'll gobble everything % up to a \cs{s_@@_tail}. The loop ending macro will gobble everything to the -% last \cs{s_@@_mark} in this definition. +% last comma in this definition. % If the end isn't reached yet, start the second loop splitting at other -% commas, and after that one iterate the current loop. +% commas, the next iteration of this first loop will be inserted by the end of +% \cs{@@_loop_other:nnw}. % \begin{macrocode} - \cs_new:Npn \@@_loop_active:NNw ##1 ##2 ##3 #1 + \cs_new:Npn \@@_loop_active:nnw ##1 ##2 ##3 #1 { \@@_if_recursion_tail:w ##3 \@@_end_loop_active:w \s_@@_tail - \@@_loop_other:NNw ##1 ##2 ##3 , \s_@@_tail , - \@@_loop_active:NNw ##1 ##2 \s_@@_mark + \@@_loop_other:nnw {##1} {##2} ##3 , \s_@@_tail , } % \end{macrocode} % \end{macro} @@ -1003,14 +1045,14 @@ % token following \cs{s_@@_mark} that followed the equals sign. Hence they % also test for the presence of such an equals sign simultaneously. % \begin{macrocode} - \cs_new:Npn \@@_split_other:w ##1 = ##2 \s_@@_mark ##3 ##4 \s_@@_stop + \cs_new:Npn \@@_split_other:w ##1 = ##2 \s_@@_mark ##3 { ##3 ##1 \s_@@_stop \s_@@_mark ##2 } - \cs_new:Npn \@@_split_active:w ##1 #2 ##2 \s_@@_mark ##3 ##4 \s_@@_stop + \cs_new:Npn \@@_split_active:w ##1 #2 ##2 \s_@@_mark ##3 { ##3 ##1 \s_@@_stop \s_@@_mark ##2 } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_loop_other:NNw} +% \begin{macro}[EXP]{\@@_loop_other:nnw} % The second loop uses the same test for its end as the first loop, next it % splits at the first active equals sign using \cs{@@_split_active:w}. The % \cs{s_@@_nil} prevents accidental brace stripping and acts as a delimiter in @@ -1018,16 +1060,15 @@ % number of necessary expansion steps for the expected average use case of % other equals signs and hence perform better on average. % \begin{macrocode} - \cs_new:Npn \@@_loop_other:NNw ##1 ##2 ##3 , + \cs_new:Npn \@@_loop_other:nnw ##1 ##2 ##3 , { \@@_if_recursion_tail:w ##3 \@@_end_loop_other:w \s_@@_tail \@@_split_active:w ##3 \s_@@_nil \s_@@_mark \@@_split_active_auxi:w #2 \s_@@_mark \@@_clean_up_active:w - \s_@@_stop - ##1 ##2 - \@@_loop_other:NNw ##1 ##2 \s_@@_mark + {##1} {##2} + \s_@@_mark } % \end{macrocode} % \end{macro} @@ -1050,7 +1091,6 @@ \@@_split_other:w ##1 \s_@@_nil \s_@@_mark \@@_misplaced_equal_after_active_error:w = \s_@@_mark \@@_split_active_auxii:w - \s_@@_stop } % \end{macrocode} % \cs{@@_split_active_auxii:w} gets the correct key name with a leading @@ -1061,7 +1101,8 @@ \cs_new:Npn \@@_split_active_auxii:w ##1 \s_@@_nil \s_@@_mark \@@_misplaced_equal_after_active_error:w \s_@@_stop \s_@@_mark - { \@@_trim:nN { ##1 } \@@_split_active_auxiii:w } + ##2 \s_@@_nil #2 \s_@@_mark \@@_clean_up_active:w + { \@@_trim:nN {##1} \@@_split_active_auxiii:w ##2 \s_@@_nil } % \end{macrocode} % Next we test for a misplaced active equals sign in the value, if none is % found \cs{@@_split_active_auxiv:w} will be called. @@ -1071,8 +1112,7 @@ \@@_split_active:w ##2 \s_@@_nil \s_@@_mark \@@_misplaced_equal_in_split_error:w #2 \s_@@_mark \@@_split_active_auxiv:w - \s_@@_stop - { ##1 } + {##1} } % \end{macrocode} % This runs the last test after sanitising the remainder of the previous one. @@ -1086,16 +1126,15 @@ \@@_split_other:w ##1 \s_@@_nil \s_@@_mark \@@_misplaced_equal_in_split_error:w = \s_@@_mark \@@_split_active_auxv:w - \s_@@_stop } % \end{macrocode} % This last macro in this execution branch sanitises the last test, trims the -% value and passes it to \cs{@@_pair:nnNN}. +% value and passes it to \cs{@@_pair:nnnn}. % \begin{macrocode} \cs_new:Npn \@@_split_active_auxv:w ##1 \s_@@_nil \s_@@_mark \@@_misplaced_equal_in_split_error:w \s_@@_stop \s_@@_mark - { \@@_trim:nN { ##1 } \@@_pair:nnNN } + { \@@_trim:nN { ##1 } \@@_pair:nnnn } % \end{macrocode} % \end{macro} % \end{macro} @@ -1115,7 +1154,6 @@ \@@_split_other:w ##1 \s_@@_nil \s_@@_mark \@@_split_other_auxi:w = \s_@@_mark \@@_clean_up_other:w - \s_@@_stop } % \end{macrocode} % \end{macro} @@ -1132,24 +1170,25 @@ { \@@_trim:nN { ##1 } \@@_split_other_auxii:w } % \end{macrocode} % We know that the value doesn't contain misplaced active equals signs but we -% have to test for others. +% have to test for others. Also we need to sanitise the previous test, which +% is done here and not earlier to avoid superfluous argument grabbing. % \begin{macrocode} - \cs_new:Npn \@@_split_other_auxii:w ##1 ##2 \s_@@_nil + \cs_new:Npn \@@_split_other_auxii:w + ##1 ##2 \s_@@_nil = \s_@@_mark \@@_clean_up_other:w { \@@_split_other:w ##2 \s_@@_nil \s_@@_mark \@@_misplaced_equal_in_split_error:w = \s_@@_mark \@@_split_other_auxiii:w - \s_@@_stop { ##1 } } % \end{macrocode} % \cs{@@_split_other_auxiii:w} sanitises the test for other equals signs, -% trims the value and forwards it to \cs{@@_pair:nnNN}. +% trims the value and forwards it to \cs{@@_pair:nnnn}. % \begin{macrocode} \cs_new:Npn \@@_split_other_auxiii:w ##1 \s_@@_nil \s_@@_mark \@@_misplaced_equal_in_split_error:w \s_@@_stop \s_@@_mark - { \@@_trim:nN { ##1 } \@@_pair:nnNN } + { \@@_trim:nN { ##1 } \@@_pair:nnnn } % \end{macrocode} % \end{macro} % \end{macro} @@ -1159,14 +1198,14 @@ % \cs{@@_clean_up_other:w} is the last branch that might exist. It is called % if no equals sign was found, hence the only possibilities left are a blank % list element, which is to be skipped, or a lonely key. If it's no empty list -% element this will trim the key name and forward it to \cs{@@_key:nNN}. +% element this will trim the key name and forward it to \cs{@@_key:nn}. % \begin{macrocode} \cs_new:Npn \@@_clean_up_other:w ##1 \s_@@_nil \s_@@_mark \@@_split_other_auxi:w \s_@@_stop \s_@@_mark { \@@_if_blank:w ##1 \s_@@_nil \s_@@_stop \@@_blank_true:w - \s_@@_mark \s_@@_stop \use:n - { \@@_trim:nN { ##1 } \@@_key:nNN } + \s_@@_mark \s_@@_stop + \@@_trim:nN { ##1 } \@@_key:nn } % \end{macrocode} % \end{macro} @@ -1174,21 +1213,26 @@ % \begin{macro}[EXP]{\@@_misplaced_equal_after_active_error:w} % \begin{macro}[EXP]{\@@_misplaced_equal_in_split_error:w} % All these two macros do is gobble the remainder of the current other loop -% execution and throw an error. +% execution and throw an error. Afterwards they have to insert the next loop +% iteration. % \begin{macrocode} \cs_new:Npn \@@_misplaced_equal_after_active_error:w \s_@@_mark ##1 \s_@@_stop \s_@@_mark ##2 \s_@@_nil - \s_@@_mark ##3 \s_@@_nil ##4 ##5 + = \s_@@_mark \@@_split_active_auxii:w + \s_@@_mark ##3 \s_@@_nil + #2 \s_@@_mark \@@_clean_up_active:w { \__kernel_msg_expandable_error:nn { kernel } { misplaced-equals-sign } + \@@_loop_other:nnw } \cs_new:Npn \@@_misplaced_equal_in_split_error:w \s_@@_mark ##1 \s_@@_stop \s_@@_mark ##2 \s_@@_nil - ##3 ##4 ##5 + ##3 \s_@@_mark ##4 ##5 { \__kernel_msg_expandable_error:nn { kernel } { misplaced-equals-sign } + \@@_loop_other:nnw } % \end{macrocode} % \end{macro} @@ -1197,21 +1241,20 @@ % \begin{macro}[EXP]{\@@_end_loop_other:w, \@@_end_loop_active:w} % All that's left for the parsing loops are the macros which end the % recursion. Both just gobble the remaining tokens of the respective loop -% including the next recursion call. +% including the next recursion call. \cs{@@_end_loop_other:w} also has to +% insert the next iteration of the active loop. % \begin{macrocode} \cs_new:Npn \@@_end_loop_other:w \s_@@_tail - \@@_split_active:w ##1 \s_@@_nil - \s_@@_mark \@@_split_active_auxi:w + \@@_split_active:w + \s_@@_mark \s_@@_tail + \s_@@_nil \s_@@_mark + \@@_split_active_auxi:w #2 \s_@@_mark \@@_clean_up_active:w - \s_@@_stop - ##2 ##3 - \@@_loop_other:NNw ##4 \s_@@_mark - { } + { \@@_loop_active:nnw } \cs_new:Npn \@@_end_loop_active:w \s_@@_tail - \@@_loop_other:NNw ##1 , \s_@@_tail , - \@@_loop_active:NNw ##2 \s_@@_mark + \@@_loop_other:nnw ##1 \s_@@_mark \s_@@_tail , \s_@@_tail , { } % \end{macrocode} % \end{macro} @@ -1226,23 +1269,26 @@ \group_end: % \end{macrocode} % -% \begin{macro}[EXP]{\@@_pair:nnNN, \@@_key:nNN} +% \begin{macro}[EXP]{\@@_pair:nnnn, \@@_key:nn} % These macros will be called on the parsed keys and values of the key--value % list. All arguments are completely trimmed. They test for blank key names -% and call the functions passed to \cs{keyval_parse:NNn} inside of -% \cs{exp_not:n} with the correct arguments. +% and call the functions passed to \cs{keyval_parse:nnn} inside of +% \cs{exp_not:n} with the correct arguments. Afterwards they insert the next +% iteration of the other loop. % \begin{macrocode} -\cs_new:Npn \@@_pair:nnNN #1 #2 #3 #4 +\cs_new:Npn \@@_pair:nnnn #1 #2 #3 #4 { \@@_if_blank:w \s_@@_mark #2 \s_@@_nil \s_@@_stop \@@_blank_key_error:w \s_@@_mark \s_@@_stop \exp_not:n { #4 { #2 } { #1 } } + \@@_loop_other:nnw {#3} {#4} } -\cs_new:Npn \@@_key:nNN #1 #2 #3 +\cs_new:Npn \@@_key:nn #1 #2 { \@@_if_blank:w \s_@@_mark #1 \s_@@_nil \s_@@_stop \@@_blank_key_error:w \s_@@_mark \s_@@_stop \exp_not:n { #2 { #1 } } + \@@_loop_other:nnw {#2} } % \end{macrocode} % \end{macro} @@ -1263,7 +1309,8 @@ % These macros will be called if the tests above didn't gobble them, they % execute the branching. % \begin{macrocode} -\cs_new:Npn \@@_blank_true:w \s_@@_mark \s_@@_stop \use:n #1 #2 #3 { } +\cs_new:Npn \@@_blank_true:w \s_@@_mark \s_@@_stop \@@_trim:nN #1 \@@_key:nn + { \@@_loop_other:nnw } \cs_new:Npn \@@_blank_key_error:w \s_@@_mark \s_@@_stop \exp_not:n #1 { \__kernel_msg_expandable_error:nn @@ -1303,7 +1350,6 @@ \@@_trim_auxiii:w #1 \s_@@_nil \@@_trim_auxiv:w - \s_@@_stop } \cs_new:Npn \@@_trim_auxi:w ##1 \s_@@_mark #1 ##2 \s_@@_mark ##3 { @@ -1327,8 +1373,11 @@ % \end{macrocode} % This is the one macro which differs from the original definition. % \begin{macrocode} - \cs_new:Npn \@@_trim_auxiv:w \s_@@_mark ##1 \s_@@_nil ##2 \s_@@_stop ##3 - { ##3 { ##1 } } + \cs_new:Npn \@@_trim_auxiv:w + \s_@@_mark ##1 \s_@@_nil + \@@_trim_auxiii:w \s_@@_nil \@@_trim_auxiii:w + ##2 + { ##2 { ##1 } } } \@@_tmp:n { ~ } \group_end: |