diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3str.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3str.dtx | 140 |
1 files changed, 90 insertions, 50 deletions
diff --git a/macros/latex/contrib/l3kernel/l3str.dtx b/macros/latex/contrib/l3kernel/l3str.dtx index 66909707c0..d4cbc2bb49 100644 --- a/macros/latex/contrib/l3kernel/l3str.dtx +++ b/macros/latex/contrib/l3kernel/l3str.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2020-05-05} +% \date{Released 2020-05-11} % % \maketitle % @@ -862,6 +862,46 @@ %<@@=str> % \end{macrocode} % +% \subsection{Internal auxiliaries} +% +% \begin{variable}{\s_@@_mark,\s_@@_stop} +% Internal scan marks. +% \begin{macrocode} +\scan_new:N \s_@@_mark +\scan_new:N \s_@@_stop +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[EXP]{ +% \@@_use_none_delimit_by_s_stop:w, +% \@@_use_i_delimit_by_s_stop:nw +% } +% Functions to gobble up to a scan mark. +% \begin{macrocode} +\cs_new:Npn \@@_use_none_delimit_by_s_stop:w #1 \s_@@_stop { } +\cs_new:Npn \@@_use_i_delimit_by_s_stop:nw #1 #2 \s_@@_stop {#1} +% \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_break:NN, +% \@@_if_recursion_tail_stop_do:Nn +% } +% Functions to query recursion quarks. +% \begin{macrocode} +\__kernel_quark_new_test:N \@@_if_recursion_tail_break:NN +\__kernel_quark_new_test:N \@@_if_recursion_tail_stop_do:Nn +% \end{macrocode} +% \end{macro} +% % \subsection{Creating and setting string variables} % % \begin{macro} @@ -978,7 +1018,7 @@ % issues if we are fed a token list variable. Then the code is a much % simplified version of the token list code because neither the % delimiter nor the replacement can contain macro parameters or -% braces. The delimiter \cs{q_mark} cannot appear in the string to +% braces. The delimiter \cs{s_@@_mark} cannot appear in the string to % edit so it is used in all cases. Some |x|-expansion is unnecessary. % There is no need to avoid losing braces nor to protect against % expansion. The ending code is much simplified and does not need to @@ -1018,9 +1058,9 @@ { \@@_replace_next:w #4 - \use_none_delimit_by_q_stop:w + \@@_use_none_delimit_by_s_stop:w #5 - \q_stop + \s_@@_stop } } \cs_new_eq:NN \@@_replace_next:w ? @@ -1214,7 +1254,7 @@ \@@_case:nnTF {#1} {#2} } \cs_new:Npn \@@_case:nnTF #1#2#3#4 - { \@@_case:nw {#1} #2 {#1} { } \q_mark {#3} \q_mark {#4} \q_stop } + { \@@_case:nw {#1} #2 {#1} { } \s_@@_mark {#3} \s_@@_mark {#4} \s_@@_stop } \cs_generate_variant:Nn \str_case:nn { V , o , nV , nv } \prg_generate_conditional_variant:Nnn \str_case:nn { V , o , nV , nv } { T , F , TF } @@ -1245,14 +1285,14 @@ \@@_case_e:nnTF {#1} {#2} } \cs_new:Npn \@@_case_e:nnTF #1#2#3#4 - { \@@_case_e:nw {#1} #2 {#1} { } \q_mark {#3} \q_mark {#4} \q_stop } + { \@@_case_e:nw {#1} #2 {#1} { } \s_@@_mark {#3} \s_@@_mark {#4} \s_@@_stop } \cs_new:Npn \@@_case_e:nw #1#2#3 { \str_if_eq:eeTF {#1} {#2} { \@@_case_end:nw {#3} } { \@@_case_e:nw {#1} } } -\cs_new:Npn \@@_case_end:nw #1#2#3 \q_mark #4#5 \q_stop +\cs_new:Npn \@@_case_end:nw #1#2#3 \s_@@_mark #4#5 \s_@@_stop { \exp_end: #1 #4 } % \end{macrocode} % \end{macro} @@ -1280,12 +1320,12 @@ % These are received by \cs{@@_map_function:Nn}, which passes % the space to |#1| and calls \cs{@@_map_function:w} to deal with the % next space. The space before the braced space allows to optimize -% the \cs{q_recursion_tail} test. Of course we need to include a +% the \cs{q_@@_recursion_tail} test. Of course we need to include a % trailing space (the question mark is needed to avoid losing the % space when \TeX{} tokenizes the line). % At the cost of about three more auxiliaries this code could get a $9$ % times speed up by testing only every $9$-th character for whether it -% is \cs{q_recursion_tail} (also by converting $9$ spaces at a time in +% is \cs{q_@@_recursion_tail} (also by converting $9$ spaces at a time in % the \cs{str_map_function:nN} case). % % For the \texttt{map_variable} functions we use a string assignment @@ -1297,7 +1337,7 @@ \exp_after:wN \@@_map_function:w \exp_after:wN \@@_map_function:Nn \exp_after:wN #2 \__kernel_tl_to_str:w {#1} - \q_recursion_tail ? ~ + \q_@@_recursion_tail ? ~ \prg_break_point:Nn \str_map_break: { } } \cs_new:Npn \str_map_function:NN @@ -1306,7 +1346,7 @@ { #1 { ~ { ~ } \@@_map_function:w } } \cs_new:Npn \@@_map_function:Nn #1#2 { - \if_meaning:w \q_recursion_tail #2 + \if_meaning:w \q_@@_recursion_tail #2 \exp_after:wN \str_map_break: \fi: #1 #2 \@@_map_function:Nn #1 @@ -1323,7 +1363,7 @@ \exp_not:c { @@_map_ \int_use:N \g__kernel_prg_map_int :w } \__kernel_str_to_other_fast:n {#1} } - \q_recursion_tail + \q_@@_recursion_tail \prg_break_point:Nn \str_map_break: { \int_gdecr:N \g__kernel_prg_map_int } } @@ -1332,7 +1372,7 @@ \cs_generate_variant:Nn \str_map_inline:Nn { c } \cs_new:Npn \@@_map_inline:NN #1#2 { - \quark_if_recursion_tail_break:NN #2 \str_map_break: + \@@_if_recursion_tail_break:NN #2 \str_map_break: \exp_args:No #1 { \token_to_str:N #2 } \@@_map_inline:NN #1 } @@ -1343,14 +1383,14 @@ \exp_not:n { \@@_map_variable:NnN #2 {#3} } \__kernel_str_to_other_fast:n {#1} } - \q_recursion_tail + \q_@@_recursion_tail \prg_break_point:Nn \str_map_break: { } } \cs_new_protected:Npn \str_map_variable:NNn { \exp_args:No \str_map_variable:nNn } \cs_new_protected:Npn \@@_map_variable:NnN #1#2#3 { - \quark_if_recursion_tail_break:NN #3 \str_map_break: + \@@_if_recursion_tail_break:NN #3 \str_map_break: \str_set:Nn #1 {#3} \use:n {#2} \@@_map_variable:NnN #1 {#2} @@ -1378,17 +1418,17 @@ % \begin{macro}[EXP]{\@@_to_other_loop:w, \@@_to_other_end:w} % First apply \cs{tl_to_str:n}, then replace all spaces by % \enquote{other} spaces, $8$ at a time, storing the converted part of -% the string between the \cs{q_mark} and \cs{q_stop} markers. The end +% the string between the \cs{s_@@_mark} and \cs{s_@@_stop} markers. The end % is detected when \cs{@@_to_other_loop:w} finds one of the trailing % |A|, distinguished from any contents of the initial token list by % their category. Then \cs{@@_to_other_end:w} is called, and finds -% the result between \cs{q_mark} and the first |A| (well, there is +% the result between \cs{s_@@_mark} and the first |A| (well, there is % also the need to remove a space). % \begin{macrocode} \cs_new:Npn \__kernel_str_to_other:n #1 { \exp_after:wN \@@_to_other_loop:w - \tl_to_str:n {#1} ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop + \tl_to_str:n {#1} ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \s_@@_mark \s_@@_stop } \group_begin: \tex_lccode:D `\* = `\ % @@ -1397,15 +1437,15 @@ { \group_end: \cs_new:Npn \@@_to_other_loop:w - #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop + #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \s_@@_stop { \if_meaning:w A #8 \@@_to_other_end:w \fi: \@@_to_other_loop:w - #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop + #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \s_@@_stop } - \cs_new:Npn \@@_to_other_end:w \fi: #1 \q_mark #2 * A #3 \q_stop + \cs_new:Npn \@@_to_other_end:w \fi: #1 \s_@@_mark #2 * A #3 \s_@@_stop { \fi: #2 } } % \end{macrocode} @@ -1421,7 +1461,7 @@ \cs_new:Npn \__kernel_str_to_other_fast:n #1 { \exp_after:wN \@@_to_other_fast_loop:w \tl_to_str:n {#1} ~ - A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_stop + A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \s_@@_stop } \group_begin: \tex_lccode:D `\* = `\ % @@ -1438,7 +1478,7 @@ #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * #9 \@@_to_other_fast_loop:w * } - \cs_new:Npn \@@_to_other_fast_end:w #1 * A #2 \q_stop {#1} + \cs_new:Npn \@@_to_other_fast_end:w #1 * A #2 \s_@@_stop {#1} } % \end{macrocode} % \end{macro} @@ -1481,25 +1521,25 @@ \exp_after:wN \@@_item:w \int_value:w \int_eval:n {#2} \exp_after:wN ; \int_value:w \@@_count:n {#1} ; - #1 \q_stop + #1 \s_@@_stop } \cs_new:Npn \@@_item:w #1; #2; { \int_compare:nNnTF {#1} < 0 { \int_compare:nNnTF {#1} < {-#2} - { \use_none_delimit_by_q_stop:w } + { \@@_use_none_delimit_by_s_stop:w } { - \exp_after:wN \use_i_delimit_by_q_stop:nw + \exp_after:wN \@@_use_i_delimit_by_s_stop:nw \exp:w \exp_after:wN \@@_skip_exp_end:w \int_value:w \int_eval:n { #1 + #2 } ; } } { \int_compare:nNnTF {#1} > {#2} - { \use_none_delimit_by_q_stop:w } + { \@@_use_none_delimit_by_s_stop:w } { - \exp_after:wN \use_i_delimit_by_q_stop:nw + \exp_after:wN \@@_use_i_delimit_by_s_stop:nw \exp:w \@@_skip_exp_end:w #1 ; { } } } @@ -1581,7 +1621,7 @@ \int_value:w \@@_count:n {#1} \exp_after:wN ; \int_value:w \int_eval:n { (#2) - 1 } \exp_after:wN ; \int_value:w \int_eval:n {#3} ; - #1 \q_stop + #1 \s_@@_stop } \cs_new:Npn \@@_range:w #1; #2; #3; { @@ -1635,7 +1675,7 @@ % \@@_collect_end:wn, \@@_collect_end:nnnnnnnnw % } % Collects |max(#1,0)| characters, and removes everything else until -% \cs{q_stop}. This is somewhat similar to \cs{@@_skip_exp_end:w}, but +% \cs{s_@@_stop}. This is somewhat similar to \cs{@@_skip_exp_end:w}, but % accepts integer expression arguments. This time we can only grab % $7$ characters at a time. At the end, we use an \cs{if_case:w} % trick again, so that the $8$ first arguments of @@ -1668,7 +1708,7 @@ #1 \else: 0 \fi: \exp_stop_f: \or: \or: \or: \or: \or: \or: \fi: } -\cs_new:Npn \@@_collect_end:nnnnnnnnw #1#2#3#4#5#6#7#8 #9 \q_stop +\cs_new:Npn \@@_collect_end:nnnnnnnnw #1#2#3#4#5#6#7#8 #9 \s_@@_stop { #1#2#3#4#5#6#7#8 } % \end{macrocode} % \end{macro} @@ -1695,13 +1735,13 @@ \exp_after:wN \@@_count_spaces_loop:w \tl_to_str:n {#1} ~ X 7 ~ X 6 ~ X 5 ~ X 4 ~ X 3 ~ X 2 ~ X 1 ~ X 0 ~ X -1 ~ - \q_stop + \s_@@_stop } } \cs_new:Npn \@@_count_spaces_loop:w #1~#2~#3~#4~#5~#6~#7~#8~#9~ { \if_meaning:w X #9 - \use_i_delimit_by_q_stop:nw + \@@_use_i_delimit_by_s_stop:nw \fi: 9 + \@@_count_spaces_loop:w } @@ -1755,13 +1795,13 @@ { X 8 } { X 7 } { X 6 } { X 5 } { X 4 } { X 3 } { X 2 } { X 1 } { X 0 } - \q_stop + \s_@@_stop } } \cs_new:Npn \@@_count_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9 { \if_meaning:w X #9 - \exp_after:wN \use_none_delimit_by_q_stop:w + \exp_after:wN \@@_use_none_delimit_by_s_stop:w \fi: 9 + \@@_count_loop:NNNNNNNNN } @@ -1781,14 +1821,14 @@ % hands it to \cs{str_head:n}. To circumvent the fact that \TeX{} % skips spaces when grabbing undelimited macro parameters, % \cs{@@_head:w} takes an argument delimited by a space. If |#1| -% starts with a non-space character, \cs{use_i_delimit_by_q_stop:nw} +% starts with a non-space character, \cs{@@_use_i_delimit_by_s_stop:nw} % leaves that in the input stream. On the other hand, if |#1| starts % with a space, the \cs{@@_head:w} takes an empty argument, and the % single (initially braced) space in the definition of \cs{@@_head:w} % makes its way to the output. Finally, for an empty argument, the % (braced) empty brace group in the definition of \cs{str_head:n} % gives an empty result after passing through -% \cs{use_i_delimit_by_q_stop:nw}. +% \cs{@@_use_i_delimit_by_s_stop:nw}. % \begin{macrocode} \cs_new:Npn \str_head:N { \exp_args:No \str_head:n } \cs_generate_variant:Nn \str_head:N { c } @@ -1796,14 +1836,14 @@ { \exp_after:wN \@@_head:w \tl_to_str:n {#1} - { { } } ~ \q_stop + { { } } ~ \s_@@_stop } \cs_new:Npn \@@_head:w #1 ~ % - { \use_i_delimit_by_q_stop:nw #1 { ~ } } + { \@@_use_i_delimit_by_s_stop:nw #1 { ~ } } \cs_new:Npn \str_head_ignore_spaces:n #1 { - \exp_after:wN \use_i_delimit_by_q_stop:nw - \tl_to_str:n {#1} { } \q_stop + \exp_after:wN \@@_use_i_delimit_by_s_stop:nw + \tl_to_str:n {#1} { } \s_@@_stop } % \end{macrocode} % \end{macro} @@ -1823,7 +1863,7 @@ % end-marker |X| be unexpandable and not a control sequence). The % \texttt{_ignore_spaces} is rather simpler: after converting the % input to a string, \cs{@@_tail_auxii:w} removes one undelimited -% argument and leaves everything else until an end-marker \cs{q_mark}. +% argument and leaves everything else until an end-marker \cs{s_@@_mark}. % One can check that an empty (or blank) string yields an empty % tail. % \begin{macrocode} @@ -1833,15 +1873,15 @@ { \exp_after:wN \@@_tail_auxi:w \reverse_if:N \if_charcode:w - \scan_stop: \tl_to_str:n {#1} X X \q_stop + \scan_stop: \tl_to_str:n {#1} X X \s_@@_stop } -\cs_new:Npn \@@_tail_auxi:w #1 X #2 \q_stop { \fi: #1 } +\cs_new:Npn \@@_tail_auxi:w #1 X #2 \s_@@_stop { \fi: #1 } \cs_new:Npn \str_tail_ignore_spaces:n #1 { \exp_after:wN \@@_tail_auxii:w - \tl_to_str:n {#1} \q_mark \q_mark \q_stop + \tl_to_str:n {#1} \s_@@_mark \s_@@_mark \s_@@_stop } -\cs_new:Npn \@@_tail_auxii:w #1 #2 \q_mark #3 \q_stop { #2 } +\cs_new:Npn \@@_tail_auxii:w #1 #2 \s_@@_mark #3 \s_@@_stop { #2 } % \end{macrocode} % \end{macro} % \end{macro} @@ -1880,7 +1920,7 @@ } \cs_new:Npn \@@_change_case_aux:nn #1#2 { - \@@_change_case_loop:nw {#2} #1 \q_recursion_tail \q_recursion_stop + \@@_change_case_loop:nw {#2} #1 \q_@@_recursion_tail \q_@@_recursion_stop \@@_change_case_result:n { } } \cs_new:Npn \@@_change_case_output:nw #1#2 \@@_change_case_result:n #3 @@ -1888,12 +1928,12 @@ \cs_generate_variant:Nn \@@_change_case_output:nw { f } \cs_new:Npn \@@_change_case_end:wn #1 \@@_change_case_result:n #2 { \tl_to_str:n {#2} } -\cs_new:Npn \@@_change_case_loop:nw #1#2 \q_recursion_stop +\cs_new:Npn \@@_change_case_loop:nw #1#2 \q_@@_recursion_stop { \tl_if_head_is_space:nTF {#2} { \@@_change_case_space:n } { \@@_change_case_char:nN } - {#1} #2 \q_recursion_stop + {#1} #2 \q_@@_recursion_stop } \exp_last_unbraced:NNNNo \cs_new:Npn \@@_change_case_space:n #1 \c_space_tl @@ -1903,7 +1943,7 @@ } \cs_new:Npn \@@_change_case_char:nN #1#2 { - \quark_if_recursion_tail_stop_do:Nn #2 + \@@_if_recursion_tail_stop_do:Nn #2 { \@@_change_case_end:wn } \@@_change_case_output:fw { \use:c { char_str_ #1 case:N } #2 } |