diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3clist.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3clist.dtx | 171 |
1 files changed, 103 insertions, 68 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index ec24d2de47c..0b011f80e0e 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2020-05-05} +% \date{Released 2020-05-11} % % \maketitle % @@ -94,8 +94,7 @@ % than their sequence analogues for large lists. However, these % functions work slowly for \enquote{unsafe} items that must be braced, % and may produce errors when their argument contains |{|, |}| or |#| -% (assuming the usual \TeX{} category codes apply). In addition, comma -% lists cannot store quarks \cs{q_mark} or \cs{q_stop}. The sequence +% (assuming the usual \TeX{} category codes apply). The sequence % data type should thus certainly be preferred to comma lists to store % such items. % @@ -785,6 +784,41 @@ % \end{macrocode} % \end{variable} % +% \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:n} +% 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:n +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\@@_tmp:w} % A temporary function for various purposes. % \begin{macrocode} @@ -826,11 +860,11 @@ { \exp_after:wN \@@_sanitize:Nn \exp_after:wN \c_empty_tl \exp:w \@@_trim_next:w \prg_do_nothing: - #1 , \q_recursion_tail , \q_recursion_stop + #1 , \q_@@_recursion_tail , \q_@@_recursion_stop } \cs_new:Npn \@@_sanitize:Nn #1#2 { - \quark_if_recursion_tail_stop:n {#2} + \@@_if_recursion_tail_stop:n {#2} #1 \@@_wrap_item:w #2 , \exp_after:wN \@@_sanitize:Nn \exp_after:wN , \exp:w \@@_trim_next:w \prg_do_nothing: @@ -850,7 +884,7 @@ % \end{itemize} % All \pkg{l3clist} functions go through the same test when they need % to determine whether to brace an item, so it is not a problem that -% this test has false positives such as \enquote{\cs{q_mark} +% this test has false positives such as \enquote{\cs{s_@@_mark} % \texttt{?}}. If the argument starts or end with a space or contains % a comma then one of the three arguments of \cs{@@_if_wrap:w} will % have its end delimiter (partly) in one of the three copies of |#1| @@ -865,7 +899,8 @@ \tl_if_empty:oTF { \@@_if_wrap:w - \q_mark ? #1 ~ \q_mark ? ~ #1 \q_mark , ~ \q_mark #1 , + \s_@@_mark ? #1 ~ \s_@@_mark ? ~ #1 + \s_@@_mark , ~ \s_@@_mark #1 , } { \tl_if_head_is_group:nTF { #1 { } } @@ -882,7 +917,7 @@ } { \prg_return_true: } } -\cs_new:Npn \@@_if_wrap:w #1 \q_mark ? ~ #2 ~ \q_mark #3 , { } +\cs_new:Npn \@@_if_wrap:w #1 \s_@@_mark ? ~ #2 ~ \s_@@_mark #3 , { } % \end{macrocode} % \end{macro} % \end{macro} @@ -1180,10 +1215,10 @@ \if_meaning:w #1 \c_empty_clist \tl_set:Nn #2 { \q_no_value } \else: - \exp_after:wN \@@_get:wN #1 , \q_stop #2 + \exp_after:wN \@@_get:wN #1 , \s_@@_stop #2 \fi: } -\cs_new_protected:Npn \@@_get:wN #1 , #2 \q_stop #3 +\cs_new_protected:Npn \@@_get:wN #1 , #2 \s_@@_stop #3 { \tl_set:Nn #3 {#1} } \cs_generate_variant:Nn \clist_get:NN { c } % \end{macrocode} @@ -1199,8 +1234,8 @@ % An empty clist leads to \cs{q_no_value}, otherwise grab until the % first comma and assign to the variable. The second argument of % \cs{@@_pop:wwNNN} is a comma list ending in a comma and -% \cs{q_mark}, unless the original clist contained exactly one item: -% then the argument is just \cs{q_mark}. The next auxiliary picks +% \cs{s_@@_mark}, unless the original clist contained exactly one item: +% then the argument is just \cs{s_@@_mark}. The next auxiliary picks % either \cs{exp_not:n} or \cs{use_none:n} as |#2|, ensuring that the % result can safely be an empty comma list. % \begin{macrocode} @@ -1213,21 +1248,21 @@ \if_meaning:w #2 \c_empty_clist \tl_set:Nn #3 { \q_no_value } \else: - \exp_after:wN \@@_pop:wwNNN #2 , \q_mark \q_stop #1#2#3 + \exp_after:wN \@@_pop:wwNNN #2 , \s_@@_mark \s_@@_stop #1#2#3 \fi: } -\cs_new_protected:Npn \@@_pop:wwNNN #1 , #2 \q_stop #3#4#5 +\cs_new_protected:Npn \@@_pop:wwNNN #1 , #2 \s_@@_stop #3#4#5 { \tl_set:Nn #5 {#1} #3 #4 { \@@_pop:wN \prg_do_nothing: #2 \exp_not:o - , \q_mark \use_none:n - \q_stop + , \s_@@_mark \use_none:n + \s_@@_stop } } -\cs_new:Npn \@@_pop:wN #1 , \q_mark #2 #3 \q_stop { #2 {#1} } +\cs_new:Npn \@@_pop:wN #1 , \s_@@_mark #2 #3 \s_@@_stop { #2 {#1} } \cs_generate_variant:Nn \clist_pop:NN { c } \cs_generate_variant:Nn \clist_gpop:NN { c } % \end{macrocode} @@ -1246,7 +1281,7 @@ \if_meaning:w #1 \c_empty_clist \prg_return_false: \else: - \exp_after:wN \@@_get:wN #1 , \q_stop #2 + \exp_after:wN \@@_get:wN #1 , \s_@@_stop #2 \prg_return_true: \fi: } @@ -1260,7 +1295,7 @@ \if_meaning:w #2 \c_empty_clist \prg_return_false: \else: - \exp_after:wN \@@_pop:wwNNN #2 , \q_mark \q_stop #1#2#3 + \exp_after:wN \@@_pop:wwNNN #2 , \s_@@_mark \s_@@_stop #1#2#3 \prg_return_true: \fi: } @@ -1364,13 +1399,13 @@ % the expanded comma list, and another copy of the \meta{item}. % The loop is controlled by the argument grabbed by % \cs{@@_remove_all:w}: when the item was found, -% the \cs{q_mark} delimiter used is the one inserted by -% \cs{@@_tmp:w}, and \cs{use_none_delimit_by_q_stop:w} +% the \cs{s_@@_mark} delimiter used is the one inserted by +% \cs{@@_tmp:w}, and \cs{@@_use_none_delimit_by_s_stop:w} % is deleted. At the end, the final \meta{item} is % grabbed, and the argument of \cs{@@_tmp:w} contains -% \cs{q_mark}: in that case, \cs{@@_remove_all:w} -% removes the second \cs{q_mark} (inserted by \cs{@@_tmp:w}), -% and lets \cs{use_none_delimit_by_q_stop:w} act. +% \cs{s_@@_mark}: in that case, \cs{@@_remove_all:w} +% removes the second \cs{s_@@_mark} (inserted by \cs{@@_tmp:w}), +% and lets \cs{@@_use_none_delimit_by_s_stop:w} act. % % No brace is lost because items are always grabbed with a leading comma. % The result of the first assignment has an extra leading comma, @@ -1396,13 +1431,13 @@ \cs_set:Npn \@@_tmp:w ##1 , #4 , { ##1 - , \q_mark , \use_none_delimit_by_q_stop:w , + , \s_@@_mark , \@@_use_none_delimit_by_s_stop:w , \@@_remove_all: } #2 #3 { \exp_after:wN \@@_remove_all: - #3 , \q_mark , #4 , \q_stop + #3 , \s_@@_mark , #4 , \s_@@_stop } \clist_if_empty:NF #3 { @@ -1416,7 +1451,7 @@ } \cs_new:Npn \@@_remove_all: { \exp_after:wN \@@_remove_all:w \@@_tmp:w , } -\cs_new:Npn \@@_remove_all:w #1 , \q_mark , #2 , { \exp_not:n {#1} } +\cs_new:Npn \@@_remove_all:w #1 , \s_@@_mark , #2 , { \exp_not:n {#1} } \cs_generate_variant:Nn \clist_remove_all:Nn { c } \cs_generate_variant:Nn \clist_gremove_all:Nn { c } % \end{macrocode} @@ -1448,19 +1483,19 @@ % \begin{macro}[EXP]{\clist_reverse:n} % \begin{macro}[EXP]{\@@_reverse:wwNww, \@@_reverse_end:ww} % The reversed token list is built one item at a time, and stored -% between \cs{q_stop} and \cs{q_mark}, in the form of |?| followed by +% between \cs{s_@@_stop} and \cs{s_@@_mark}, in the form of |?| followed by % zero or more instances of \enquote{\meta{item}\texttt{,}}. We start from a comma % list \enquote{\meta{item_1}\texttt{,\ldots,}\meta{item_n}}. During the loop, % the auxiliary \cs{@@_reverse:wwNww} receives \enquote{\texttt{?}\meta{item_i}} as % |#1|, \enquote{\meta{item_{i+1}}\texttt{,\ldots,}\meta{item_n}} as |#2|, -% \cs{@@_reverse:wwNww} as |#3|, what remains until \cs{q_stop} as +% \cs{@@_reverse:wwNww} as |#3|, what remains until \cs{s_@@_stop} as % |#4|, and \enquote{\meta{item_{i-1}}\texttt{,\ldots,}\meta{item_1}\texttt{,}} as |#5|. % The auxiliary moves |#1| just before |#5|, with a comma, and calls % itself (|#3|). After the last item is moved, \cs{@@_reverse:wwNww} -% receives \enquote{\cs{q_mark} \cs{@@_reverse:wwNww} \texttt{!}} as its argument +% receives \enquote{\cs{s_@@_mark} \cs{@@_reverse:wwNww} \texttt{!}} as its argument % |#1|, thus \cs{@@_reverse_end:ww} as its argument |#3|. This second % auxiliary cleans up until the marker~|!|, removes the trailing comma -% (introduced when the first item was moved after \cs{q_stop}), and +% (introduced when the first item was moved after \cs{s_@@_stop}), and % leaves its argument~|#1| within \cs{exp_not:n}. There is also a % need to remove a leading comma, hence \cs{exp_not:o} and % \cs{use_none:n}. @@ -1468,14 +1503,14 @@ \cs_new:Npn \clist_reverse:n #1 { \@@_reverse:wwNww ? #1 , - \q_mark \@@_reverse:wwNww ! , - \q_mark \@@_reverse_end:ww - \q_stop ? \q_mark + \s_@@_mark \@@_reverse:wwNww ! , + \s_@@_mark \@@_reverse_end:ww + \s_@@_stop ? \s_@@_mark } \cs_new:Npn \@@_reverse:wwNww - #1 , #2 \q_mark #3 #4 \q_stop ? #5 \q_mark - { #3 ? #2 \q_mark #3 #4 \q_stop #1 , #5 \q_mark } -\cs_new:Npn \@@_reverse_end:ww #1 ! #2 , \q_mark + #1 , #2 \s_@@_mark #3 #4 \s_@@_stop ? #5 \s_@@_mark + { #3 ? #2 \s_@@_mark #3 #4 \s_@@_stop #1 , #5 \s_@@_mark } +\cs_new:Npn \@@_reverse_end:ww #1 ! #2 , \s_@@_mark { \exp_not:o { \use_none:n #2 } } % \end{macrocode} % \end{macro} @@ -1511,14 +1546,14 @@ % item is non-blank, exit: the second auxiliary grabs % \cs{prg_return_false:} as |#2|, unless every item in % the comma list was blank and the loop actually got broken -% by the trailing |\q_mark \prg_return_false:| item. +% by the trailing \cs{s_@@_mark} \cs{prg_return_false:} item. % \begin{macrocode} \prg_new_conditional:Npnn \clist_if_empty:n #1 { p , T , F , TF } { \@@_if_empty_n:w ? #1 - , \q_mark \prg_return_false: - , \q_mark \prg_return_true: - \q_stop + , \s_@@_mark \prg_return_false: + , \s_@@_mark \prg_return_true: + \s_@@_stop } \cs_new:Npn \@@_if_empty_n:w #1 , { @@ -1526,7 +1561,7 @@ { \@@_if_empty_n:w ? } { \@@_if_empty_n:wNw } } -\cs_new:Npn \@@_if_empty_n:wNw #1 \q_mark #2#3 \q_stop {#2} +\cs_new:Npn \@@_if_empty_n:wNw #1 \s_@@_mark #2#3 \s_@@_stop {#2} % \end{macrocode} % \end{macro} % \end{macro} @@ -1595,7 +1630,7 @@ % If the variable is empty, the mapping is skipped (otherwise, % that comma-list would be seen as consisting of one empty item). % Then loop over the comma-list, grabbing one comma-delimited -% item at a time. The end is marked by \cs{q_recursion_tail}. +% item at a time. The end is marked by \cs{q_@@_recursion_tail}. % The auxiliary function \cs{@@_map_function:Nw} is also used % in \cs{clist_map_inline:Nn}. % \begin{macrocode} @@ -1604,13 +1639,13 @@ \clist_if_empty:NF #1 { \exp_last_unbraced:NNo \@@_map_function:Nw #2 #1 - , \q_recursion_tail , + , \q_@@_recursion_tail , \prg_break_point:Nn \clist_map_break: { } } } \cs_new:Npn \@@_map_function:Nw #1#2 , { - \quark_if_recursion_tail_break:nN {#2} \clist_map_break: + \@@_if_recursion_tail_break:nN {#2} \clist_map_break: #1 {#2} \@@_map_function:Nw #1 } @@ -1634,12 +1669,12 @@ \cs_new:Npn \clist_map_function:nN #1#2 { \exp_after:wN \@@_map_function_n:Nn \exp_after:wN #2 - \exp:w \@@_trim_next:w \prg_do_nothing: #1 , \q_recursion_tail , + \exp:w \@@_trim_next:w \prg_do_nothing: #1 , \q_@@_recursion_tail , \prg_break_point:Nn \clist_map_break: { } } \cs_new:Npn \@@_map_function_n:Nn #1 #2 { - \quark_if_recursion_tail_break:nN {#2} \clist_map_break: + \@@_if_recursion_tail_break:nN {#2} \clist_map_break: \@@_map_unbrace:Nw #1 #2, \exp_after:wN \@@_map_function_n:Nn \exp_after:wN #1 \exp:w \@@_trim_next:w \prg_do_nothing: @@ -1675,7 +1710,7 @@ { @@_map_ \int_use:N \g__kernel_prg_map_int :w } ##1 {#2} \exp_last_unbraced:Nco \@@_map_function:Nw { @@_map_ \int_use:N \g__kernel_prg_map_int :w } - #1 , \q_recursion_tail , + #1 , \q_@@_recursion_tail , \prg_break_point:Nn \clist_map_break: { \int_gdecr:N \g__kernel_prg_map_int } } @@ -1702,7 +1737,7 @@ % The quark test is done before assigning the item to the variable: % this avoids storing a quark which the user wouldn't expect. % The strange \cs{use:n} avoids unlikely problems when |#2| would -% contain \cs{q_recursion_stop}. +% contain \cs{q_@@_recursion_stop}. % \begin{macrocode} \cs_new_protected:Npn \clist_map_variable:NNn #1#2#3 { @@ -1711,7 +1746,7 @@ \exp_args:Nno \use:nn { \@@_map_variable:Nnw #2 {#3} } #1 - , \q_recursion_tail , \q_recursion_stop + , \q_@@_recursion_tail , \q_@@_recursion_stop \prg_break_point:Nn \clist_map_break: { } } } @@ -1722,7 +1757,7 @@ } \cs_new_protected:Npn \@@_map_variable:Nnw #1#2#3, { - \quark_if_recursion_tail_stop:n {#3} + \@@_if_recursion_tail_stop:n {#3} \tl_set:Nn #1 {#3} \use:n {#2} \@@_map_variable:Nnw #1 {#2} @@ -1769,13 +1804,13 @@ { 0 \exp_not:N \@@_count:w \c_space_tl - #1 \exp_not:n { , \q_recursion_tail , \q_recursion_stop } + #1 \exp_not:n { , \q_@@_recursion_tail , \q_@@_recursion_stop } } } \cs_new:Npn \@@_count:n #1 { + 1 } \cs_new:Npx \@@_count:w #1 , { - \exp_not:n { \exp_args:Nf \quark_if_recursion_tail_stop:n } {#1} + \exp_not:n { \exp_args:Nf \@@_if_recursion_tail_stop:n } {#1} \exp_not:N \tl_if_blank:nF {#1} { + 1 } \exp_not:N \@@_count:w \c_space_tl } @@ -1801,15 +1836,15 @@ % quarks), 5: the rest of the comma list, 6: a \meta{continuation} % function (\texttt{use_ii} or \texttt{use_iii} with its % \meta{separator} argument), 7: junk, and 8: the temporary result, -% which is built in a brace group following \cs{q_stop}. The +% which is built in a brace group following \cs{q_@@_stop}. The % \meta{separator} and the first of the three items are placed in the % result, then we use the \meta{continuation}, placing the remaining % two items after it. When we begin this loop, the three items really -% belong to the comma list, the first \cs{q_mark} is taken as a +% belong to the comma list, the first \cs{q_@@_mark} is taken as a % delimiter to the \texttt{use_ii} function, and the continuation is % \texttt{use_ii} itself. When we reach the last two items of the -% original token list, \cs{q_mark} is taken as a third item, and now -% the second \cs{q_mark} serves as a delimiter to \texttt{use_ii}, +% original token list, \cs{q_@@_mark} is taken as a third item, and now +% the second \cs{q_@@_mark} serves as a delimiter to \texttt{use_ii}, % switching to the other \meta{continuation}, \texttt{use_iii}, which % uses the \meta{separator between final two}. % \begin{macrocode} @@ -1826,9 +1861,9 @@ { \exp_after:wN \@@_use:nwwwwnwn \exp_after:wN { \exp_after:wN } #1 , - \q_mark , { \@@_use:nwwwwnwn {#3} } - \q_mark , { \@@_use:nwwn {#4} } - \q_stop { } + \s_@@_mark , { \@@_use:nwwwwnwn {#3} } + \s_@@_mark , { \@@_use:nwwn {#4} } + \s_@@_stop { } } } { @@ -1839,9 +1874,9 @@ \cs_generate_variant:Nn \clist_use:Nnnn { c } \cs_new:Npn \@@_use:wwn #1 , #2 , #3 { \exp_not:n { #1 #3 #2 } } \cs_new:Npn \@@_use:nwwwwnwn - #1#2 , #3 , #4 , #5 \q_mark , #6#7 \q_stop #8 - { #6 {#3} , {#4} , #5 \q_mark , {#6} #7 \q_stop { #8 #1 #2 } } -\cs_new:Npn \@@_use:nwwn #1#2 , #3 \q_stop #4 + #1#2 , #3 , #4 , #5 \s_@@_mark , #6#7 \s_@@_stop #8 + { #6 {#3} , {#4} , #5 \s_@@_mark , {#6} #7 \s_@@_stop { #8 #1 #2 } } +\cs_new:Npn \@@_use:nwwn #1#2 , #3 \s_@@_stop #4 { \exp_not:n { #4 #1 #2 } } \cs_new:Npn \clist_use:Nn #1#2 { \clist_use:Nnnn #1 {#2} {#2} {#2} } @@ -1877,21 +1912,21 @@ \int_compare:nNnTF {#2} < 0 { \int_compare:nNnTF {#2} < { - #1 } - { \use_none_delimit_by_q_stop:w } + { \@@_use_none_delimit_by_s_stop:w } { \exp_args:Nf #4 { \int_eval:n { #2 + 1 + #1 } } } } { \int_compare:nNnTF {#2} > {#1} - { \use_none_delimit_by_q_stop:w } + { \@@_use_none_delimit_by_s_stop:w } { #4 {#2} } } - { } , #3 , \q_stop + { } , #3 , \s_@@_stop } \cs_generate_variant:Nn \@@_item:nnnN { ffo, ff } \cs_new:Npn \@@_item_N_loop:nw #1 #2, { \int_compare:nNnTF {#1} = 0 - { \use_i_delimit_by_q_stop:nw { \exp_not:n {#2} } } + { \@@_use_i_delimit_by_s_stop:nw { \exp_not:n {#2} } } { \exp_args:Nf \@@_item_N_loop:nw { \int_eval:n { #1 - 1 } } } } \cs_generate_variant:Nn \clist_item:Nn { c } @@ -1936,7 +1971,7 @@ } } } -\cs_new:Npn \@@_item_n_end:n #1 #2 \q_stop +\cs_new:Npn \@@_item_n_end:n #1 #2 \s_@@_stop { \tl_trim_spaces_apply:nN {#1} \@@_item_n_strip:n } \cs_new:Npn \@@_item_n_strip:n #1 { \@@_item_n_strip:w #1 , } \cs_new:Npn \@@_item_n_strip:w #1 , { \exp_not:n {#1} } |