diff options
author | Karl Berry <karl@freefriends.org> | 2012-07-23 17:15:00 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-07-23 17:15:00 +0000 |
commit | 134349701bddf7cbbacf6030c6b9f9838aff96fa (patch) | |
tree | ec1140c46e1c0347a671a6fa3cf8af5a79e95f93 /Master/texmf-dist/source/latex/l3kernel/l3clist.dtx | |
parent | f7855c12c18bb97b7b9e49ab685ee558d8c0b47b (diff) |
l3kernel 3990 (17jul12)
git-svn-id: svn://tug.org/texlive/trunk@27108 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3clist.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3clist.dtx | 931 |
1 files changed, 370 insertions, 561 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index 31a429e61ef..5fbb63f89d9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -37,8 +37,8 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3clist.dtx 3490 2012-03-04 01:00:53Z bruno $ - {L3 Experimental comma separated lists} +\GetIdInfo$Id: l3clist.dtx 3986 2012-07-15 19:23:51Z joseph $ + {L3 Comma separated lists} %</driver|package> %<*driver> \documentclass[full]{l3doc} @@ -88,7 +88,9 @@ % \end{verbatim} % will leave \texttt{true} in the input stream. To include an item % which contains a comma, or starts or ends with a space, -% surround it with braces. +% surround it with braces. The sequence data type should be preferred +% to comma lists if items are to contain |{|, |}|, or |#| (assuming the +% usual \TeX{} category codes apply). % % \section{Creating and initialising comma lists} % @@ -118,7 +120,7 @@ % \cs{clist_clear_new:N} \meta{comma list} % \end{syntax} % Ensures that the \meta{comma list} exists globally by applying -% \cs{clsit_new:N} if necessary, then applies \cs{clist_(g)clear:N} to leave +% \cs{clist_new:N} if necessary, then applies \cs{clist_(g)clear:N} to leave % the list empty. % \end{function} % @@ -130,10 +132,10 @@ % \clist_gset_eq:Nc, \clist_gset_eq:cc % } % \begin{syntax} -% \cs{clist_set_eq:NN} \meta{comma list1} \meta{comma list2} +% \cs{clist_set_eq:NN} \meta{comma list_1} \meta{comma list_2} % \end{syntax} -% Sets the content of \meta{comma list1} equal to that of -% \meta{comma list2}. +% Sets the content of \meta{comma list_1} equal to that of +% \meta{comma list_2}. % \end{function} % % \begin{function} @@ -142,11 +144,11 @@ % \clist_gconcat:NNN, \clist_gconcat:ccc % } % \begin{syntax} -% \cs{clist_concat:NNN} \meta{comma list1} \meta{comma list2} \meta{comma list3} +% \cs{clist_concat:NNN} \meta{comma list_1} \meta{comma list_2} \meta{comma list_3} % \end{syntax} -% Concatenates the content of \meta{comma list2} and \meta{comma list3} -% together and saves the result in \meta{comma list1}. The items in -% \meta{comma list2} will be placed at the left side of the new comma list. +% Concatenates the content of \meta{comma list_2} and \meta{comma list_3} +% together and saves the result in \meta{comma list_1}. The items in +% \meta{comma list_2} will be placed at the left side of the new comma list. % \end{function} % % \begin{function}[EXP, pTF, added=2012-03-03] @@ -173,7 +175,7 @@ % \clist_gset:co, \clist_gset:cx % } % \begin{syntax} -% \cs{clist_set:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}| +% \cs{clist_set:Nn} \meta{comma list} |{|\meta{item_1},\ldots{},\meta{item_n}|}| % \end{syntax} % Sets \meta{comma list} to contain the \meta{items}, % removing any previous content from the variable. @@ -192,7 +194,7 @@ % \clist_gput_left:co, \clist_gput_left:cx % } % \begin{syntax} -% \cs{clist_put_left:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}| +% \cs{clist_put_left:Nn} \meta{comma list} |{|\meta{item_1},\ldots{},\meta{item_n}|}| % \end{syntax} % Appends the \meta{items} to the left of the \meta{comma list}. % Spaces are removed from both sides of each item. @@ -210,22 +212,12 @@ % \clist_gput_right:co, \clist_gput_right:cx % } % \begin{syntax} -% \cs{clist_put_right:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}| +% \cs{clist_put_right:Nn} \meta{comma list} |{|\meta{item_1},\ldots{},\meta{item_n}|}| % \end{syntax} % Appends the \meta{items} to the right of the \meta{comma list}. % Spaces are removed from both sides of each item. % \end{function} % -% \section{Using comma lists} -% -% \begin{function}[EXP]{\clist_use:N, \clist_use:c} -% \begin{syntax} -% \cs{clist_use:N} \meta{comma list} -% \end{syntax} -% Places the \meta{comma list} directly into the input stream, -% including the commas, thus treating it as a \meta{token list}. -% \end{function} -% % \section{Modifying comma lists} % % While comma lists are normally used as ordered lists, it may be @@ -281,17 +273,6 @@ % Tests if the \meta{comma list} is empty (containing no items). % \end{function} % -% \begin{function}[EXP,pTF] -% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc} -% \begin{syntax} -% \cs{clist_if_eq_p:NN} \meta{clist_1} \meta{clist_2} -% \cs{clist_if_eq:NNTF} \meta{clist_1} \meta{clist_2} \Arg{true code} \Arg{false code} -% \end{syntax} -% Compares the content of two \meta{comma lists} and -% is logically \texttt{true} if the two contain the same list of -% entries in the same order. -% \end{function} -% % \begin{function}[updated = 2011-09-06, TF] % { % \clist_if_in:Nn, \clist_if_in:NV, \clist_if_in:No, @@ -326,16 +307,16 @@ % If the result of trimming spaces is empty, the item is ignored. % Otherwise, if the item is surrounded by braces, one set is removed, % and the result is passed to the mapped function. Thus, if your -% comma list that is being mapped is \verb*|{a , {b }, ,{}, {c},}| +% comma list that is being mapped is \verb*|{a , {{b} }, ,{}, {c},}| % then the arguments passed to the mapped function are -% `\verb*|a|', `\verb*|{b }|', an empty argument, and `\verb*|c|'. +% `\verb*|a|', `\verb*|{b} |', an empty argument, and `\verb*|c|'. % % When the comma list is given as an \texttt{N}-type argument, spaces % have already been trimmed on input, and items are simply stripped % of one set of braces if any. This case is more efficient than using % \texttt{n}-type comma lists. % -% \begin{function}[rEXP] +% \begin{function}[rEXP, updated = 2012-06-29] % {\clist_map_function:NN, \clist_map_function:cN, \clist_map_function:nN} % \begin{syntax} % \cs{clist_map_function:NN} \meta{comma list} \meta{function} @@ -348,7 +329,7 @@ % One mapping may be nested inside another. % \end{function} % -% \begin{function} +% \begin{function}[updated = 2012-06-29] % {\clist_map_inline:Nn, \clist_map_inline:cn, \clist_map_inline:nn} % \begin{syntax} % \cs{clist_map_inline:Nn} \meta{comma list} \Arg{inline function} @@ -360,7 +341,7 @@ % are returned from left to right. % \end{function} % -% \begin{function} +% \begin{function}[updated = 2012-06-29] % {\clist_map_variable:NNn, \clist_map_variable:cNn, \clist_map_variable:nNn} % \begin{syntax} % \cs{clist_map_variable:NNn} \meta{comma list} \meta{tl~var.} \Arg{function using tl~var.} @@ -373,7 +354,7 @@ % are returned from left to right. % \end{function} % -% \begin{function}[rEXP]{\clist_map_break:} +% \begin{function}[rEXP, updated = 2012-06-29]{\clist_map_break:} % \begin{syntax} % \cs{clist_map_break:} % \end{syntax} @@ -394,13 +375,13 @@ % level \TeX{} errors. % \begin{texnote} % When the mapping is broken, additional tokens may be inserted by the -% internal macro \cs{prg_break_point:n} before further items are taken +% internal macro \cs{__prg_break_point:Nn} before further items are taken % from the input stream. This will depend on the design of the mapping % function. % \end{texnote} % \end{function} % -% \begin{function}[rEXP]{\clist_map_break:n} +% \begin{function}[updated = 2012-06-29, rEXP]{\clist_map_break:n} % \begin{syntax} % \cs{clist_map_break:n} \Arg{tokens} % \end{syntax} @@ -422,12 +403,23 @@ % level \TeX{} errors. % \begin{texnote} % When the mapping is broken, additional tokens may be inserted by the -% internal macro \cs{prg_break_point:n} before the \meta{tokens} are +% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are % inserted into the input stream. % This will depend on the design of the mapping function. % \end{texnote} % \end{function} % +% \begin{function}[EXP, added = 2012-07-13] +% {\clist_count:N, \clist_count:c, \clist_count:n} +% \begin{syntax} +% \cs{clist_count:N} \meta{comma list} +% \end{syntax} +% Leaves the number of items in the \meta{comma list} in the input +% stream as an \meta{integer denotation}. The total number of items +% in a \meta{comma list} will include those which are duplicates, +% \emph{i.e.}~every item in a \meta{comma list} is unique. +% \end{function} +% % \section{Comma lists as stacks} % % Comma lists can be used as stacks, where data is pushed to and popped @@ -437,22 +429,28 @@ % in the previous section: a comma list should either be used as an % ordered data type or as a stack, but not in both ways. % -% \begin{function}{\clist_get:NN, \clist_get:cN} +% \begin{function}[updated = 2012-05-14]{\clist_get:NN, \clist_get:cN} % \begin{syntax} % \cs{clist_get:NN} \meta{comma list} \meta{token list variable} % \end{syntax} % Stores the left-most item from a \meta{comma list} in the % \meta{token list variable} without removing it from the % \meta{comma list}. The \meta{token list variable} is assigned locally. +% If the \meta{comma list} is empty the \meta{token list variable} will +% contain the marker value \cs{q_no_value}. % \end{function} % -% \begin{function}{\clist_get:NN, \clist_get:cN} +% \begin{function}[TF, added = 2012-05-14]{\clist_get:NN, \clist_get:cN} % \begin{syntax} -% \cs{clist_get:NN} \meta{comma list} \meta{token list variable} +% \cs{clist_get:NNTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code} % \end{syntax} -% Stores the right-most item from a \meta{comma list} in the -% \meta{token list variable} without removing it from the -% \meta{comma list}. The \meta{token list variable} is assigned locally. +% If the \meta{comma list} is empty, leaves the \meta{false code} in the +% input stream. The value of the \meta{token list variable} is +% not defined in this case and should not be relied upon. If the +% \meta{comma list} is non-empty, stores the top item from the +% \meta{comma list} in the \meta{token list variable} without removing it +% from the \meta{comma list}. The \meta{token list variable} is assigned +% locally. % \end{function} % % \begin{function}[updated = 2011-09-06]{\clist_pop:NN, \clist_pop:cN} @@ -476,6 +474,32 @@ % the \meta{token list variable} is local. % \end{function} % +% \begin{function}[TF, added = 2012-05-14]{\clist_pop:NN, \clist_pop:cN} +% \begin{syntax} +% \cs{clist_pop:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} +% \end{syntax} +% If the \meta{comma list} is empty, leaves the \meta{false code} in the +% input stream. The value of the \meta{token list variable} is +% not defined in this case and should not be relied upon. If the +% \meta{comma list} is non-empty, pops the top item from the +% \meta{comma list} in the \meta{token list variable}, \emph{i.e.}~removes +% the item from the \meta{comma list}. Both the \meta{comma list} and the +% \meta{token list variable} are assigned locally. +% \end{function} +% +% \begin{function}[TF, added = 2012-05-14]{\clist_gpop:NN, \clist_gpop:cN} +% \begin{syntax} +% \cs{clist_gpop:NNTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code} +% \end{syntax} +% If the \meta{comma list} is empty, leaves the \meta{false code} in the +% input stream. The value of the \meta{token list variable} is +% not defined in this case and should not be relied upon. If the +% \meta{comma list} is non-empty, pops the top item from the +% \meta{comma list} in the \meta{token list variable}, \emph{i.e.}~removes +% the item from the \meta{comma list}. The \meta{comma list} is modified +% globally, while the \meta{token list variable} is assigned locally. +% \end{function} +% % \begin{function} % { % \clist_push:Nn, \clist_push:NV, \clist_push:No, \clist_push:Nx, @@ -506,7 +530,11 @@ % Displays the entries in the comma list in the terminal. % \end{function} % -% \section{Scratch comma lists} +% \section{Constant and scratch comma lists} +% +% \begin{variable}[added = 2012-07-02]{\c_empty_clist} +% Constant that is always empty. +% \end{variable} % % \begin{variable}[added = 2011-09-06]{\l_tmpa_clist, \l_tmpb_clist} % Scratch comma lists for local assignment. These are never used by @@ -522,97 +550,6 @@ % code and so should only be used for short-term storage. % \end{variable} % -% \section{Experimental comma list functions} -% -% This section contains functions which may or may not be retained, depending -% on how useful they are found to be. -% -% \begin{function}[added = 2011-06-25, updated = 2011-09-06, EXP] -% {\clist_length:N, \clist_length:c, \clist_length:n} -% \begin{syntax} -% \cs{clist_length:N} \meta{comma list} -% \end{syntax} -% Leaves the number of items in the \meta{comma list} in the input -% stream as an \meta{integer denotation}. The total number of items -% in a \meta{comma list} will include those which are duplicates, -% \emph{i.e.}~every item in a \meta{comma list} is unique. -% \end{function} -% -% \begin{function}[updated = 2012-01-08, EXP] -% {\clist_item:Nn, \clist_item:cn, \clist_item:nn} -% \begin{syntax} -% \cs{clist_item:Nn} \meta{comma list} \Arg{integer expression} -% \end{syntax} -% Indexing items in the \meta{comma list} from $0$ at the top (left), this -% function will evaluate the \meta{integer expression} and leave the -% appropriate item from the comma list in the input stream. If the -% \meta{integer expression} is negative, indexing occurs from the -% bottom (right) of the comma list. When the \meta{integer expression} -% is larger than the number of items in the \meta{comma list} (as -% calculated by \cs{clist_length:N}) then the function will expand to -% nothing. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the \meta{item} -% will not expand further when appearing in an x-type -% argument expansion. -% \end{texnote} -% \end{function} -% -% \begin{function}[updated = 2011-08-31] -% { -% \clist_set_from_seq:NN, \clist_set_from_seq:cN, -% \clist_set_from_seq:Nc, \clist_set_from_seq:cc, -% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN, -% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc -% } -% \begin{syntax} -% \cs{clist_set_from_seq:NN} \meta{comma list} \meta{sequence} -% \end{syntax} -% Sets the \meta{comma list} to be equal to the content of the -% \meta{sequence}. -% Items which contain either spaces or commas are surrounded by braces. -% \end{function} -% -% \begin{function}[added = 2011-11-26] -% { -% \clist_const:Nn, \clist_const:Nx, -% \clist_const:cn, \clist_const:cx -% } -% \begin{syntax} -% \cs{clist_const:Nn} \meta{clist~var} \Arg{comma list} -% \end{syntax} -% Creates a new constant \meta{clist~var} or raises an error -% if the name is already taken. The value of the -% \meta{clist~var} will be set globally to the -% \meta{comma list}. -% \end{function} -% -% \begin{function}[EXP, pTF, added = 2011-12-07]{\clist_if_empty:n} -% \begin{syntax} -% \cs{clist_if_empty_p:n} \Arg{comma list} -% \cs{clist_if_empty:nTF} \Arg{comma list} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{comma list} is empty (containing no items). -% The rules for space trimming are as for other \texttt{n}-type -% comma-list functions, hence the comma list |{~,~,,~}| (without -% outer braces) is empty, while |{~,{},}| (without outer braces) -% contains one element, which happens to be empty: the comma-list -% is not empty. -% \end{function} -% -% \section{Internal comma-list functions} -% -% \begin{function}[added = 2011-07-09, rEXP]{\clist_trim_spaces:n} -% \begin{syntax} -% \cs{clist_trim_spaces:n} \Arg{comma list} -% \end{syntax} -% Removes leading and trailing spaces from each \meta{item} in the -% \meta{comma list}, leaving the resulting modified list in the -% input stream. This is used by the functions which add data -% into a comma list. -% \end{function} -% % \end{documentation} % % \begin{implementation} @@ -626,25 +563,36 @@ % \end{macrocode} % % \begin{macrocode} +%<@@=clist> +% \end{macrocode} +% +% \begin{macrocode} %<*package> \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} -\package_check_loaded_expl: +\__expl_package_check: %</package> % \end{macrocode} % -% \begin{variable}{\l_clist_internal_clist} +% \begin{variable}{\c_empty_clist} +% An empty comma list is simply an empty token list. +% \begin{macrocode} +\cs_new_eq:NN \c_empty_clist \c_empty_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_internal_clist} % Scratch space for various internal uses. This comma list variable % cannot be declared as such because it comes before \cs{clist_new:N} % \begin{macrocode} -\tl_new:N \l_clist_internal_clist +\tl_new:N \l_@@_internal_clist % \end{macrocode} % \end{variable} % -% \begin{macro}[aux]{\clist_tmp:w} +% \begin{macro}[aux]{\@@_tmp:w} % A temporary function for various purposes. % \begin{macrocode} -\cs_new_protected:Npn \clist_tmp:w { } +\cs_new_protected:Npn \@@_tmp:w { } % \end{macrocode} % \end{macro} % @@ -714,16 +662,16 @@ % \UnitTested % \begin{macro}{\clist_gconcat:NNN, \clist_gconcat:ccc} % \UnitTested -% \begin{macro}[aux]{\clist_concat_aux:NNNN} -% Concatenating sequences is not quite as easy as it seems, as +% \begin{macro}[aux]{\@@_concat:NNNN} +% Concatenating comma lists is not quite as easy as it seems, as % there needs to be the correct addition of a comma to the output. So % a little work to do. % \begin{macrocode} \cs_new_protected_nopar:Npn \clist_concat:NNN - { \clist_concat_aux:NNNN \tl_set:Nx } + { \@@_concat:NNNN \tl_set:Nx } \cs_new_protected_nopar:Npn \clist_gconcat:NNN - { \clist_concat_aux:NNNN \tl_gset:Nx } -\cs_new_protected:Npn \clist_concat_aux:NNNN #1#2#3#4 + { \@@_concat:NNNN \tl_gset:Nx } +\cs_new_protected:Npn \@@_concat:NNNN #1#2#3#4 { #1 #2 { @@ -755,73 +703,58 @@ % % \subsection{Removing spaces around items} % -% \begin{macro}[int,EXP]{\clist_trim_spaces_generic:nw} -% \begin{macro}[aux]{\clist_trim_spaces_generic_aux:w} -% \begin{macro}[aux]{\clist_trim_spaces_generic_aux_ii:nn} -% Used as `\cs{clist_trim_spaces_generic:nw} \Arg{code} -% \cs{q_mark} \meta{item} |,|' (including the comma). +% \begin{macro}[int,EXP]{\@@_trim_spaces_generic:nw} +% \begin{macro}[aux]{\@@_trim_spaces_generic:nn} +% \begin{syntax} +% \cs{@@_trim_spaces_generic:nw} \Arg{code} \cs{q_mark} \meta{item} |,| +% \end{syntax} % This expands to the \meta{code}, followed by a brace group -% containing the \meta{item}, with leading and trailing spaces removed. -% The calling function is responsible for inserting \cs{q_mark} -% in front of the \meta{item}, as well as testing for the end of the list. -% See \cs{tl_trim_spaces:n} for a partial explanation of what -% is happening here. We changed \cs{tl_trim_spaces_aux_iv:w} -% into \cs{clist_trim_spaces_generic_aux:w} compared to -% \cs{tl_trim_spaces:n}, and dropped a \cs{q_mark}, which is -% already included in the argument |##2|. +% containing the \meta{item}, with leading and trailing spaces +% removed. The calling function is responsible for inserting +% \cs{q_mark} in front of the \meta{item}, as well as testing for the +% end of the list. We reuse a \pkg{l3tl} internal function, whose +% first argument must start with \cs{q_mark}. That trims the item +% |#2|, then feeds the result (after having to do an \texttt{o}-type +% expansion) to \cs{@@_trim_spaces_generic:nn} which places the +% \meta{code} in front of the \meta{trimmed item}. % \begin{macrocode} -\cs_set:Npn \clist_tmp:w #1 +\cs_new:Npn \@@_trim_spaces_generic:nw #1#2 , { - \cs_new:Npn \clist_trim_spaces_generic:nw ##1 ##2 , - { - \tl_trim_spaces_aux_i:w - ##2 - \q_nil - \q_mark #1 { } - \q_mark \tl_trim_spaces_aux_ii:w - \tl_trim_spaces_aux_iii:w - #1 \q_nil - \clist_trim_spaces_generic_aux:w - \q_stop - {##1} - } + \__tl_trim_spaces:nn {#2} + { \exp_args:No \@@_trim_spaces_generic:nn } {#1} } -\clist_tmp:w {~} -\cs_new:Npn \clist_trim_spaces_generic_aux:w #1 \q_nil #2 \q_stop - { \exp_args:No \clist_trim_spaces_generic_aux_ii:nn { \use_none:n #1 } } -\cs_new:Npn \clist_trim_spaces_generic_aux_ii:nn #1 #2 { #2 {#1} } +\cs_new:Npn \@@_trim_spaces_generic:nn #1#2 { #2 {#1} } % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % -% \begin{macro}[int,rEXP]{\clist_trim_spaces:n} -% \begin{macro}[aux]{\clist_trim_spaces_aux:nn} -% The first argument of \cs{clist_trim_spaces_aux:nn} is initially empty, +% \begin{macro}[int,rEXP]{\@@_trim_spaces:n} +% \begin{macro}[aux]{\@@_trim_spaces_ii:nn} +% The first argument of \cs{@@_trim_spaces_ii:nn} is initially empty, % and later a comma, namely, as soon as we have added an item to the % resulting list. The auxiliary tests for the end of the list, % and also prevents empty arguments from finding their way into the % output. % \begin{macrocode} -\cs_new:Npn \clist_trim_spaces:n #1 +\cs_new:Npn \@@_trim_spaces:n #1 { - \clist_trim_spaces_generic:nw - { \clist_trim_spaces_aux:nn { } } + \@@_trim_spaces_generic:nw + { \@@_trim_spaces_ii:nn { } } \q_mark #1 , \q_recursion_tail, \q_recursion_stop } -\cs_new:Npn \clist_trim_spaces_aux:nn #1 #2 +\cs_new:Npn \@@_trim_spaces_ii:nn #1 #2 { \quark_if_recursion_tail_stop:n {#2} \tl_if_empty:nTF {#2} { - \clist_trim_spaces_generic:nw - { \clist_trim_spaces_aux:nn {#1} } \q_mark + \@@_trim_spaces_generic:nw + { \@@_trim_spaces_ii:nn {#1} } \q_mark } { #1 \exp_not:n {#2} - \clist_trim_spaces_generic:nw - { \clist_trim_spaces_aux:nn { , } } \q_mark + \@@_trim_spaces_generic:nw + { \@@_trim_spaces_ii:nn { , } } \q_mark } } % \end{macrocode} @@ -846,9 +779,9 @@ % } % \begin{macrocode} \cs_new_protected:Npn \clist_set:Nn #1#2 - { \tl_set:Nx #1 { \clist_trim_spaces:n {#2} } } + { \tl_set:Nx #1 { \@@_trim_spaces:n {#2} } } \cs_new_protected:Npn \clist_gset:Nn #1#2 - { \tl_gset:Nx #1 { \clist_trim_spaces:n {#2} } } + { \tl_gset:Nx #1 { \@@_trim_spaces:n {#2} } } \cs_generate_variant:Nn \clist_set:Nn { NV , No , Nx , c , cV , co , cx } \cs_generate_variant:Nn \clist_gset:Nn { NV , No , Nx , c , cV , co , cx } % \end{macrocode} @@ -871,18 +804,18 @@ % \clist_gput_left:co, \clist_gput_left:cx % } % \UnitTested -% \begin{macro}[aux]{\clist_put_left_aux:NNNn} +% \begin{macro}[aux]{\@@_put_left:NNNn} % Comma lists cannot hold empty values: there are therefore a couple % of sanity checks to avoid accumulating commas. % \begin{macrocode} \cs_new_protected_nopar:Npn \clist_put_left:Nn - { \clist_put_left_aux:NNNn \clist_concat:NNN \clist_set:Nn } + { \@@_put_left:NNNn \clist_concat:NNN \clist_set:Nn } \cs_new_protected_nopar:Npn \clist_gput_left:Nn - { \clist_put_left_aux:NNNn \clist_gconcat:NNN \clist_set:Nn } -\cs_new_protected:Npn \clist_put_left_aux:NNNn #1#2#3#4 + { \@@_put_left:NNNn \clist_gconcat:NNN \clist_set:Nn } +\cs_new_protected:Npn \@@_put_left:NNNn #1#2#3#4 { - #2 \l_clist_internal_clist {#4} - #1 #3 \l_clist_internal_clist #3 + #2 \l_@@_internal_clist {#4} + #1 #3 \l_@@_internal_clist #3 } \cs_generate_variant:Nn \clist_put_left:Nn { NV , No , Nx } \cs_generate_variant:Nn \clist_put_left:Nn { c , cV , co , cx } @@ -909,16 +842,16 @@ % \clist_gput_right:co, \clist_gput_right:cx % } % \UnitTested -% \begin{macro}[aux]{\clist_put_right_aux:NNNn} +% \begin{macro}[aux]{\@@_put_right:NNNn} % \begin{macrocode} \cs_new_protected_nopar:Npn \clist_put_right:Nn - { \clist_put_right_aux:NNNn \clist_concat:NNN \clist_set:Nn } + { \@@_put_right:NNNn \clist_concat:NNN \clist_set:Nn } \cs_new_protected_nopar:Npn \clist_gput_right:Nn - { \clist_put_right_aux:NNNn \clist_gconcat:NNN \clist_gset:Nn } -\cs_new_protected:Npn \clist_put_right_aux:NNNn #1#2#3#4 + { \@@_put_right:NNNn \clist_gconcat:NNN \clist_gset:Nn } +\cs_new_protected:Npn \@@_put_right:NNNn #1#2#3#4 { - #2 \l_clist_internal_clist {#4} - #1 #3 #3 \l_clist_internal_clist + #2 \l_@@_internal_clist {#4} + #1 #3 #3 \l_@@_internal_clist } \cs_generate_variant:Nn \clist_put_right:Nn { NV , No , Nx } \cs_generate_variant:Nn \clist_put_right:Nn { c , cV , co , cx } @@ -933,13 +866,19 @@ % % \begin{macro}{\clist_get:NN, \clist_get:cN} % \UnitTested -% \begin{macro}[aux]{\clist_get_aux:wN} +% \begin{macro}[aux]{\@@_get:wN} % Getting an item from the left of a comma list is pretty easy: just % trim off the first item using the comma. % \begin{macrocode} \cs_new_protected:Npn \clist_get:NN #1#2 - { \exp_after:wN \clist_get_aux:wN #1 , \q_stop #2 } -\cs_new_protected:Npn \clist_get_aux:wN #1 , #2 \q_stop #3 + { + \if_meaning:w #1 \c_empty_clist + \tl_set:Nn #2 { \q_no_value } + \else: + \exp_after:wN \@@_get:wN #1 , \q_stop #2 + \fi: + } +\cs_new_protected:Npn \@@_get:wN #1 , #2 \q_stop #3 { \tl_set:Nn #3 {#1} } \cs_generate_variant:Nn \clist_get:NN { c } % \end{macrocode} @@ -951,28 +890,39 @@ % \begin{macro}{\clist_gpop:NN, \clist_gpop:cN} % \UnitTested % \begin{macro}[aux] -% {\clist_pop_aux:NNN, \clist_pop_aux:NwNNN, \clist_pop_aux:wNN} -% The aim here is to get the popped item as |#1| in the auxiliary, with -% |#2| containing either the remainder of the list \emph{or} \cs{q_nil} -% if there were insufficient items. That keeps the number of auxiliary -% functions down. +% {\@@_pop:NNN, \@@_pop:wwNNN, \@@_pop:wN} +% 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 +% 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} \cs_new_protected_nopar:Npn \clist_pop:NN - { \clist_pop_aux:NNN \tl_set:Nf } + { \@@_pop:NNN \tl_set:Nx } \cs_new_protected_nopar:Npn \clist_gpop:NN - { \clist_pop_aux:NNN \tl_gset:Nf } -\cs_new_protected:Npn \clist_pop_aux:NNN #1#2#3 + { \@@_pop:NNN \tl_gset:Nx } +\cs_new_protected:Npn \@@_pop:NNN #1#2#3 { - \exp_after:wN \clist_pop_aux:wNNN #2 , \q_nil \q_stop #1#2#3 + \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 + \fi: } -\cs_new_protected:Npn \clist_pop_aux:wNNN #1 , #2 \q_stop #3#4#5 +\cs_new_protected:Npn \@@_pop:wwNNN #1 , #2 \q_stop #3#4#5 { \tl_set:Nn #5 {#1} - \quark_if_nil:nTF {#2} - { #3 #4 { } } - { #3 #4 { \clist_pop_aux:w \exp_stop_f: #2 } } + #3 #4 + { + \@@_pop:wN \prg_do_nothing: + #2 \exp_not:o + , \q_mark \use_none:n + \q_stop + } } -\cs_new_protected:Npn \clist_pop_aux:w #1 , \q_nil {#1} +\cs_new:Npn \@@_pop:wN #1 , \q_mark #2 #3 \q_stop { #2 {#1} } \cs_generate_variant:Nn \clist_pop:NN { c } \cs_generate_variant:Nn \clist_gpop:NN { c } % \end{macrocode} @@ -980,6 +930,49 @@ % \end{macro} % \end{macro} % +% \begin{macro}[TF]{\clist_get:NN, \clist_get:cN} +% \begin{macro}[TF]{\clist_pop:NN, \clist_pop:cN} +% \begin{macro}[TF]{\clist_gpop:NN, \clist_gpop:cN} +% \begin{macro}[aux]{\@@_pop_TF:NNN} +% The same, as branching code: very similar to the above. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \clist_get:NN #1#2 { T , F , TF } + { + \if_meaning:w #1 \c_empty_clist + \prg_return_false: + \else: + \exp_after:wN \@@_get:wN #1 , \q_stop #2 + \prg_return_true: + \fi: + } +\cs_generate_variant:Nn \clist_get:NNT { c } +\cs_generate_variant:Nn \clist_get:NNF { c } +\cs_generate_variant:Nn \clist_get:NNTF { c } +\prg_new_protected_conditional:Npnn \clist_pop:NN #1#2 { T , F , TF } + { \@@_pop_TF:NNN \tl_set:Nx #1 #2 } +\prg_new_protected_conditional:Npnn \clist_gpop:NN #1#2 { T , F , TF } + { \@@_pop_TF:NNN \tl_gset:Nx #1 #2 } +\cs_new_protected:Npn \@@_pop_TF:NNN #1#2#3 + { + \if_meaning:w #2 \c_empty_clist + \prg_return_false: + \else: + \exp_after:wN \@@_pop:wwNNN #2 , \q_mark \q_stop #1#2#3 + \prg_return_true: + \fi: + } +\cs_generate_variant:Nn \clist_pop:NNT { c } +\cs_generate_variant:Nn \clist_pop:NNF { c } +\cs_generate_variant:Nn \clist_pop:NNTF { c } +\cs_generate_variant:Nn \clist_gpop:NNT { c } +\cs_generate_variant:Nn \clist_gpop:NNF { c } +\cs_generate_variant:Nn \clist_gpop:NNTF { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}{ % \clist_push:Nn, \clist_push:NV, \clist_push:No, \clist_push:Nx, % \clist_push:cn, \clist_push:cV, \clist_push:co, \clist_push:cx @@ -990,7 +983,7 @@ % \clist_gpush:cn, \clist_gpush:cV, \clist_gpush:co, \clist_gpush:cx % } % \UnitTested -% Pushing to a sequence is the same as adding on the left. +% Pushing to a comma list is the same as adding on the left. % \begin{macrocode} \cs_new_eq:NN \clist_push:Nn \clist_put_left:Nn \cs_new_eq:NN \clist_push:NV \clist_put_left:NV @@ -1012,23 +1005,12 @@ % \end{macro} % \end{macro} % -% \subsection{Using comma lists} -% -% \begin{macro}{\clist_use:N, \clist_use:c} -% \UnitTested -% The approach is the same as for \cs{tl_use:N}. -% \begin{macrocode} -\cs_new_eq:NN \clist_use:N \tl_use:N -\cs_new_eq:NN \clist_use:c \tl_use:c -% \end{macrocode} -% \end{macro} -% % \subsection{Modifying comma lists} % -% \begin{variable}{\l_clist_internal_remove_clist} +% \begin{variable}{\l_@@_internal_remove_clist} % An internal comma list for the removal routines. % \begin{macrocode} -\clist_new:N \l_clist_internal_remove_clist +\clist_new:N \l_@@_internal_remove_clist % \end{macrocode} % \end{variable} % @@ -1036,22 +1018,22 @@ % \UnitTested % \begin{macro}{\clist_gremove_duplicates:N, \clist_gremove_duplicates:c} % \UnitTested -% \begin{macro}[aux]{\clist_remove_duplicates_aux:NN} +% \begin{macro}[aux]{\@@_remove_duplicates:NN} % Removing duplicates means making a new list then copying it. % \begin{macrocode} \cs_new_protected:Npn \clist_remove_duplicates:N - { \clist_remove_duplicates_aux:NN \clist_set_eq:NN } + { \@@_remove_duplicates:NN \clist_set_eq:NN } \cs_new_protected:Npn \clist_gremove_duplicates:N - { \clist_remove_duplicates_aux:NN \clist_gset_eq:NN } -\cs_new_protected:Npn \clist_remove_duplicates_aux:NN #1#2 + { \@@_remove_duplicates:NN \clist_gset_eq:NN } +\cs_new_protected:Npn \@@_remove_duplicates:NN #1#2 { - \clist_clear:N \l_clist_internal_remove_clist + \clist_clear:N \l_@@_internal_remove_clist \clist_map_inline:Nn #2 { - \clist_if_in:NnF \l_clist_internal_remove_clist {##1} - { \clist_put_right:Nn \l_clist_internal_remove_clist {##1} } + \clist_if_in:NnF \l_@@_internal_remove_clist {##1} + { \clist_put_right:Nn \l_@@_internal_remove_clist {##1} } } - #1 #2 \l_clist_internal_remove_clist + #1 #2 \l_@@_internal_remove_clist } \cs_generate_variant:Nn \clist_remove_duplicates:N { c } \cs_generate_variant:Nn \clist_gremove_duplicates:N { c } @@ -1064,21 +1046,21 @@ % \UnitTested % \begin{macro}{\clist_gremove_all:Nn, \clist_gremove_all:cn} % \UnitTested -% \begin{macro}[aux]{\clist_remove_all_aux:NNn} -% \begin{macro}[aux]{\clist_remove_all_aux:w} -% \begin{macro}[aux]{\clist_remove_all_aux:} +% \begin{macro}[aux]{\@@_remove_all:NNn} +% \begin{macro}[aux]{\@@_remove_all:w} +% \begin{macro}[aux]{\@@_remove_all:} % The method used here is very similar to \cs{tl_replace_all:Nnn}. % Build a function delimited by the \meta{item} that should be removed, % surrounded with commas, and call that function followed by % the expanded comma list, and another copy of the \meta{item}. % The loop is controlled by the argument grabbed by -% \cs{clist_remove_all_aux:w}: when the item was found, +% \cs{@@_remove_all:w}: when the item was found, % the \cs{q_mark} delimiter used is the one inserted by -% \cs{clist_tmp:w}, and \cs{use_none_delimit_by_q_stop:w} +% \cs{@@_tmp:w}, and \cs{use_none_delimit_by_q_stop:w} % is deleted. At the end, the final \meta{item} is -% grabbed, and the argument of \cs{clist_tmp:w} contains -% \cs{q_mark}: in that case, \cs{clist_remove_all_aux:w} -% removes the second \cs{q_mark} (inserted by \cs{clist_tmp:w}), +% 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. % % No brace is lost because items are always grabbed with a leading comma. @@ -1090,20 +1072,20 @@ % the second step removes it. % \begin{macrocode} \cs_new_protected:Npn \clist_remove_all:Nn - { \clist_remove_all_aux:NNn \tl_set:Nx } + { \@@_remove_all:NNn \tl_set:Nx } \cs_new_protected:Npn \clist_gremove_all:Nn - { \clist_remove_all_aux:NNn \tl_gset:Nx } -\cs_new_protected:Npn \clist_remove_all_aux:NNn #1#2#3 + { \@@_remove_all:NNn \tl_gset:Nx } +\cs_new_protected:Npn \@@_remove_all:NNn #1#2#3 { - \cs_set:Npn \clist_tmp:w ##1 , #3 , + \cs_set:Npn \@@_tmp:w ##1 , #3 , { ##1 , \q_mark , \use_none_delimit_by_q_stop:w , - \clist_remove_all_aux: + \@@_remove_all: } #1 #2 { - \exp_after:wN \clist_remove_all_aux: + \exp_after:wN \@@_remove_all: #2 , \q_mark , #3 , \q_stop } \clist_if_empty:NF #2 @@ -1115,9 +1097,9 @@ } } } -\cs_new:Npn \clist_remove_all_aux: - { \exp_after:wN \clist_remove_all_aux:w \clist_tmp:w , } -\cs_new:Npn \clist_remove_all_aux:w #1 , \q_mark , #2 , { \exp_not:n {#1} } +\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_generate_variant:Nn \clist_remove_all:Nn { c } \cs_generate_variant:Nn \clist_gremove_all:Nn { c } % \end{macrocode} @@ -1138,43 +1120,31 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[pTF] -% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc} -% \UnitTested -% Simple copies from the token list variable material. -% \begin{macrocode} -\prg_new_eq_conditional:NNn \clist_if_eq:NN \tl_if_eq:NN { p , T , F , TF } -\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc { p , T , F , TF } -\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN { p , T , F , TF } -\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc { p , T , F , TF } -% \end{macrocode} -% \end{macro} -% % \begin{macro}[TF] % { % \clist_if_in:Nn, \clist_if_in:NV, \clist_if_in:No, % \clist_if_in:cn, \clist_if_in:cV, \clist_if_in:co, % \clist_if_in:nn, \clist_if_in:nV, \clist_if_in:no % } -% \begin{macro}[aux]{\clist_if_in_return:nn} +% \begin{macro}[aux]{\@@_if_in_return:nn} % \UnitTested % See description of the \cs{tl_if_in:Nn} function for details. % We simply surround the comma list, and the item, with commas. % \begin{macrocode} \prg_new_protected_conditional:Npnn \clist_if_in:Nn #1#2 { T , F , TF } { - \exp_args:No \clist_if_in_return:nn #1 {#2} + \exp_args:No \@@_if_in_return:nn #1 {#2} } \prg_new_protected_conditional:Npnn \clist_if_in:nn #1#2 { T , F , TF } { - \clist_set:Nn \l_clist_internal_clist {#1} - \exp_args:No \clist_if_in_return:nn \l_clist_internal_clist {#2} + \clist_set:Nn \l_@@_internal_clist {#1} + \exp_args:No \@@_if_in_return:nn \l_@@_internal_clist {#2} } -\cs_new_protected:Npn \clist_if_in_return:nn #1#2 +\cs_new_protected:Npn \@@_if_in_return:nn #1#2 { - \cs_set:Npn \clist_tmp:w ##1 ,#2, { } + \cs_set:Npn \@@_tmp:w ##1 ,#2, { } \tl_if_empty:oTF - { \clist_tmp:w ,#1, {} {} ,#2, } + { \@@_tmp:w ,#1, {} {} ,#2, } { \prg_return_false: } { \prg_return_true: } } \cs_generate_variant:Nn \clist_if_in:NnT { NV , No } @@ -1194,28 +1164,28 @@ % % \begin{macro}{\clist_map_function:NN, \clist_map_function:cN} % \UnitTested -% \begin{macro}[aux]{\clist_map_function_aux:Nw} +% \begin{macro}[aux]{\@@_map_function:Nw} % 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}. -% The auxiliary function \cs{clist_map_function_aux:Nw} is used +% The auxiliary function \cs{@@_map_function:Nw} is used % directly in \cs{clist_map_inline:Nn}. Change with care. % \begin{macrocode} \cs_new:Npn \clist_map_function:NN #1#2 { \clist_if_empty:NF #1 { - \exp_last_unbraced:NNo \clist_map_function_aux:Nw #2 #1 + \exp_last_unbraced:NNo \@@_map_function:Nw #2 #1 , \q_recursion_tail , - \prg_break_point:n { } + \__prg_break_point:Nn \clist_map_break: { } } } -\cs_new:Npn \clist_map_function_aux:Nw #1#2 , +\cs_new:Npn \@@_map_function:Nw #1#2 , { - \quark_if_recursion_tail_break:n {#2} + \__quark_if_recursion_tail_break:nN {#2} \clist_map_break: #1 {#2} - \clist_map_function_aux:Nw #1 + \@@_map_function:Nw #1 } \cs_generate_variant:Nn \clist_map_function:NN { c } % \end{macrocode} @@ -1224,31 +1194,31 @@ % % \begin{macro}{\clist_map_function:nN} % \UnitTested -% \begin{macro}[aux]{\clist_map_function_n_aux:Nn} -% \begin{macro}{\clist_map_aux_unbrace:Nw} +% \begin{macro}[aux]{\@@_map_function_n:Nn} +% \begin{macro}[aux]{\@@_map_unbrace:Nw} % The \texttt{n}-type mapping function is a bit more awkward, -% since spaces mustbe trimmed from each item. -% Space trimming is again based on \cs{clist_trim_spaces_generic:nw}. -% The auxiliary \cs{clist_map_function_n_aux:Nn} receives +% since spaces must be trimmed from each item. +% Space trimming is again based on \cs{@@_trim_spaces_generic:nw}. +% The auxiliary \cs{@@_map_function_n:Nn} receives % as arguments the function, and the result of removing leading % and trailing spaces from the item which lies until the next comma. % Empty items are ignored, then one level of braces is removed -% by \cs{clist_map_aux_unbrace:Nw}. +% by \cs{@@_map_unbrace:Nw}. % \begin{macrocode} \cs_new:Npn \clist_map_function:nN #1#2 { - \clist_trim_spaces_generic:nw { \clist_map_function_n_aux:Nn #2 } + \@@_trim_spaces_generic:nw { \@@_map_function_n:Nn #2 } \q_mark #1, \q_recursion_tail, - \prg_break_point:n { } + \__prg_break_point:Nn \clist_map_break: { } } -\cs_new:Npn \clist_map_function_n_aux:Nn #1 #2 +\cs_new:Npn \@@_map_function_n:Nn #1 #2 { - \quark_if_recursion_tail_break:n {#2} - \tl_if_empty:nF {#2} { \clist_map_aux_unbrace:Nw #1 #2, } - \clist_trim_spaces_generic:nw { \clist_map_function_n_aux:Nn #1 } + \__quark_if_recursion_tail_break:nN {#2} \clist_map_break: + \tl_if_empty:nF {#2} { \@@_map_unbrace:Nw #1 #2, } + \@@_trim_spaces_generic:nw { \@@_map_function_n:Nn #1 } \q_mark } -\cs_new:Npn \clist_map_aux_unbrace:Nw #1 #2, { #1 {#2} } +\cs_new:Npn \@@_map_unbrace:Nw #1 #2, { #1 {#2} } % \end{macrocode} % \end{macro} % \end{macro} @@ -1274,18 +1244,19 @@ { \clist_if_empty:NF #1 { - \int_gincr:N \g_prg_map_int - \cs_gset:cpn { clist_map_ \int_use:N \g_prg_map_int :n } ##1 {#2} - \exp_last_unbraced:Nco \clist_map_function_aux:Nw - { clist_map_ \int_use:N \g_prg_map_int :n } + \int_gincr:N \g__prg_map_int + \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} + \exp_last_unbraced:Nco \@@_map_function:Nw + { __prg_map_ \int_use:N \g__prg_map_int :w } #1 , \q_recursion_tail , - \prg_break_point:n { \int_gdecr:N \g_prg_map_int } + \__prg_break_point:Nn \clist_map_break: + { \int_gdecr:N \g__prg_map_int } } } \cs_new_protected:Npn \clist_map_inline:nn #1 { - \clist_set:Nn \l_clist_internal_clist {#1} - \clist_map_inline:Nn \l_clist_internal_clist + \clist_set:Nn \l_@@_internal_clist {#1} + \clist_map_inline:Nn \l_@@_internal_clist } \cs_generate_variant:Nn \clist_map_inline:Nn { c } % \end{macrocode} @@ -1295,7 +1266,7 @@ % \begin{macro}{\clist_map_variable:NNn, \clist_map_variable:cNn} % \UnitTested % \begin{macro}{\clist_map_variable:nNn} -% \begin{macro}[aux]{\clist_map_variable_aux:Nnw} +% \begin{macro}[aux]{\@@_map_variable:Nnw} % As for other comma-list mappings, filter out the case of % an empty list. Same approach as \cs{clist_map_function:Nn}, % additionally we store each item in the given variable. @@ -1307,23 +1278,23 @@ \clist_if_empty:NF #1 { \exp_args:Nno \use:nn - { \clist_map_variable_aux:Nnw #2 {#3} } + { \@@_map_variable:Nnw #2 {#3} } #1 , \q_recursion_tail , \q_recursion_stop - \prg_break_point:n { } + \__prg_break_point:Nn \clist_map_break: { } } } \cs_new_protected:Npn \clist_map_variable:nNn #1 { - \clist_set:Nn \l_clist_internal_clist {#1} - \clist_map_variable:NNn \l_clist_internal_clist + \clist_set:Nn \l_@@_internal_clist {#1} + \clist_map_variable:NNn \l_@@_internal_clist } -\cs_new_protected:Npn \clist_map_variable_aux:Nnw #1#2#3, +\cs_new_protected:Npn \@@_map_variable:Nnw #1#2#3, { \tl_set:Nn #1 {#3} \quark_if_recursion_tail_stop:N #1 \use:n {#2} - \clist_map_variable_aux:Nnw #1 {#2} + \@@_map_variable:Nnw #1 {#2} } \cs_generate_variant:Nn \clist_map_variable:NNn { c } % \end{macrocode} @@ -1331,293 +1302,99 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\clist_map_break:} -% \begin{macro}{\clist_map_break:n} -% The break statements are simply copies. +% \begin{macro}{\clist_map_break:, \clist_map_break:n} +% The break statements use the general \cs{__prg_map_break:Nn} mechanism. % \begin{macrocode} -\cs_new_eq:NN \clist_map_break: \prg_map_break: -\cs_new_eq:NN \clist_map_break:n \prg_map_break:n +\cs_new_nopar:Npn \clist_map_break: + { \__prg_map_break:Nn \clist_map_break: { } } +\cs_new_nopar:Npn \clist_map_break:n + { \__prg_map_break:Nn \clist_map_break: } % \end{macrocode} % \end{macro} -% \end{macro} -% -% \subsection{Viewing comma lists} -% -% \begin{macro}{\clist_show:N, \clist_show:c} -% \begin{macro}{\clist_show:n} -% Apply the general \cs{msg_aux_show:Nnx}. In the case -% of an \texttt{n}-type comma-list, first store it -% in a scratch variable, then show that variable, -% omitting its name from the $4$-th argument. -% \begin{macrocode} -\cs_new_protected:Npn \clist_show:N #1 - { - \msg_aux_show:Nnx - #1 - { clist } - { \clist_map_function:NN #1 \msg_aux_show:n } - } -\cs_new_protected:Npn \clist_show:n #1 - { - \clist_set:Nn \l_clist_internal_clist {#1} - \msg_aux_show:Nnx - \l_clist_internal_clist - { clist } - { \clist_map_function:NN \l_clist_internal_clist \msg_aux_show:n } - } -\cs_generate_variant:Nn \clist_show:N { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Scratch comma lists} -% -% \begin{variable}{\l_tmpa_clist, \l_tmpb_clist} -% \begin{variable}{\g_tmpa_clist, \g_tmpb_clist} -% Temporary comma list variables. -% \begin{macrocode} -\clist_new:N \l_tmpa_clist -\clist_new:N \l_tmpb_clist -\clist_new:N \g_tmpa_clist -\clist_new:N \g_tmpb_clist -% \end{macrocode} -% \end{variable} -% \end{variable} -% -% \subsection{Experimental functions} -% -% \begin{macro}{\clist_length:N, \clist_length:c} -% \begin{macro}{\clist_length:n} -% \begin{macro}[aux]{\clist_length_aux:w} +% +% \begin{macro}{\clist_count:N, \clist_count:c, \clist_count:n} +% \begin{macro}[aux]{\@@_count:n} +% \begin{macro}[aux]{\@@_count:w} % Counting the items in a comma list is done using the same approach as for -% other length functions: turn each entry into a \texttt{+1} then use +% other token count functions: turn each entry into a \texttt{+1} then use % integer evaluation to actually do the mathematics. % In the case of an \texttt{n}-type comma-list, we could of course use % \cs{clist_map_function:nN}, but that is very slow, because it carefully % removes spaces. Instead, we loop manually, and skip blank items % (but not |{}|, hence the extra spaces). % \begin{macrocode} -\cs_new:Npn \clist_length:N #1 +\cs_new:Npn \clist_count:N #1 { \int_eval:n { 0 - \clist_map_function:NN #1 \clist_length_aux:n + \clist_map_function:NN #1 \@@_count:n } } -\cs_new:Npn \clist_length_aux:n #1 { +1 } -\cs_new:Npx \clist_length:n #1 +\cs_generate_variant:Nn \clist_count:N { c } +\cs_new:Npx \clist_count:n #1 { \exp_not:N \int_eval:n { 0 - \exp_not:N \clist_length_n_aux:w \c_space_tl + \exp_not:N \@@_count:w \c_space_tl #1 \exp_not:n { , \q_recursion_tail , \q_recursion_stop } } } -\cs_new:Npx \clist_length_n_aux:w #1 , +\cs_new:Npn \@@_count:n #1 { + \c_one } +\cs_new:Npx \@@_count:w #1 , { \exp_not:n { \exp_args:Nf \quark_if_recursion_tail_stop:n } {#1} \exp_not:N \tl_if_blank:nF {#1} { + \c_one } - \exp_not:N \clist_length_n_aux:w \c_space_tl + \exp_not:N \@@_count:w \c_space_tl } -\cs_generate_variant:Nn \clist_length:N { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\clist_item:Nn, \clist_item:cn} -% \begin{macro}[aux]{\clist_item_aux:nnNn} -% \begin{macro}[aux]{\clist_item_N_loop:nw} -% To avoid needing to test the end of the list at each step, -% we first compute the \meta{length} of the list. If the item number -% is less than $-\meta{length}$ or more than $\meta{length}-1$, -% the result is empty. If it is negative, but not less than $-\meta{length}$, -% add the \meta{length} to the item number before performing the loop. -% The loop itself is very simple, return the item if the counter -% reached zero, otherwise, decrease the counter and repeat. -% \begin{macrocode} -\cs_new:Npn \clist_item:Nn #1#2 - { - \exp_args:Nfo \clist_item_aux:nnNn - { \clist_length:N #1 } - #1 - \clist_item_N_loop:nw - {#2} - } -\cs_new:Npn \clist_item_aux:nnNn #1#2#3#4 - { - \int_compare:nNnTF {#4} < \c_zero - { - \int_compare:nNnTF {#4} < { - #1 } - { \use_none_delimit_by_q_stop:w } - { \exp_args:Nf #3 { \int_eval:n { #4 + #1 } } } - } - { - \int_compare:nNnTF {#4} < {#1} - { #3 {#4} } - { \use_none_delimit_by_q_stop:w } - } - #2, \q_stop - } -\cs_new:Npn \clist_item_N_loop:nw #1 #2, - { - \int_compare:nNnTF {#1} = \c_zero - { \use_i_delimit_by_q_stop:nw { \exp_not:n {#2} } } - { \exp_args:Nf \clist_item_N_loop:nw { \int_eval:n { #1 - 1 } } } - } -\cs_generate_variant:Nn \clist_item:Nn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\clist_item:nn} -% \begin{macro}[aux]{ -% \clist_item_n_aux:nw, -% \clist_item_n_loop:nw, -% \clist_item_n_end:n, -% \clist_item_n_strip:w} -% This starts in the same way as \cs{clist_item:Nn} by checking the length -% of the comma list. The final item should be space-trimmed before being -% brace-stripped, hence we insert a couple of odd-looking -% \cs{prg_do_nothing:} to avoid losing braces. Blank items are ignored. -% \begin{macrocode} -\cs_new:Npn \clist_item:nn #1#2 - { - \exp_args:Nf \clist_item_aux:nnNn - { \clist_length:n {#1} } - {#1} - \clist_item_n_aux:nw - {#2} - } -\cs_new:Npn \clist_item_n_aux:nw #1 - { \clist_item_n_loop:nw {#1} \prg_do_nothing: } -\cs_new:Npn \clist_item_n_loop:nw #1 #2, - { - \exp_args:No \tl_if_blank:nTF {#2} - { \clist_item_n_loop:nw {#1} \prg_do_nothing: } - { - \int_compare:nNnTF {#1} = \c_zero - { \exp_args:No \clist_item_n_end:n {#2} } - { - \exp_args:Nf \clist_item_n_loop:nw - { \int_eval:n { #1 - 1 } } - \prg_do_nothing: - } - } - } -\cs_new:Npn \clist_item_n_end:n #1 #2 \q_stop - { - \exp_after:wN \exp_after:wN \exp_after:wN \clist_item_n_strip:w - \tl_trim_spaces:n {#1} , - } -\cs_new:Npn \clist_item_n_strip:w #1 , { \exp_not:n {#1} } -% \end{macrocode} -% \end{macro} -% \end{macro} +% \subsection{Viewing comma lists} % -% \begin{macro} -% { -% \clist_set_from_seq:NN, \clist_set_from_seq:cN, -% \clist_set_from_seq:Nc, \clist_set_from_seq:cc -% } -% \UnitTested -% \begin{macro} -% { -% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN, -% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc -% } -% \UnitTested -% \begin{macro}[aux]{\clist_set_from_seq_aux:NNNN} -% \begin{macro}[aux]{\clist_wrap_item:n} -% Setting a comma list from a comma-separated list is done using a simple -% mapping. We wrap most items with \cs{exp_not:n}, and a comma. Items which -% contain a comma or a space are surrounded by an extra set of braces. The -% first comma must be removed, except in the case of an empty comma-list. +% \begin{macro}{\clist_show:N, \clist_show:c} +% \begin{macro}{\clist_show:n} +% Apply the general \cs{__msg_show_variable:Nnn}. In the case +% of an \texttt{n}-type comma-list, first store it +% in a scratch variable, then show that variable, +% omitting its name from the $4$-th argument. % \begin{macrocode} -\cs_new_protected:Npn \clist_set_from_seq:NN - { \clist_set_from_seq_aux:NNNN \clist_clear:N \tl_set:Nx } -\cs_new_protected:Npn \clist_gset_from_seq:NN - { \clist_set_from_seq_aux:NNNN \clist_gclear:N \tl_gset:Nx } -\cs_new_protected:Npn \clist_set_from_seq_aux:NNNN #1#2#3#4 +\cs_new_protected:Npn \clist_show:N #1 { - \seq_if_empty:NTF #4 - { #1 #3 } - { - #2 #3 - { - \exp_last_unbraced:Nf \use_none:n - { \seq_map_function:NN #4 \clist_wrap_item:n } - } - } + \__msg_show_variable:Nnn + #1 + { clist } + { \clist_map_function:NN #1 \__msg_show_item:n } } -\cs_new:Npn \clist_wrap_item:n #1 +\cs_new_protected:Npn \clist_show:n #1 { - , - \tl_if_empty:oTF { \clist_set_from_seq_aux:w #1 ~ , #1 ~ } - { \exp_not:n {#1} } - { \exp_not:n { {#1} } } + \clist_set:Nn \l_@@_internal_clist {#1} + \__msg_show_variable:Nnn + \l_@@_internal_clist + { clist } + { \clist_map_function:NN \l_@@_internal_clist \__msg_show_item:n } } -\cs_new:Npn \clist_set_from_seq_aux:w #1 , #2 ~ { } -\cs_generate_variant:Nn \clist_set_from_seq:NN { Nc } -\cs_generate_variant:Nn \clist_set_from_seq:NN { c , cc } -\cs_generate_variant:Nn \clist_gset_from_seq:NN { Nc } -\cs_generate_variant:Nn \clist_gset_from_seq:NN { c , cc } +\cs_generate_variant:Nn \clist_show:N { c } % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro} -% { -% \clist_const:Nn, \clist_const:cn, -% \clist_const:Nx, \clist_const:cx -% } -% Creating and initializing a constant comma list is done in a way -% similar to \cs{clist_set:Nn} and \cs{clist_gset:Nn}, being careful -% to strip spaces. -% \begin{macrocode} -\cs_new_protected:Npn \clist_const:Nn #1#2 - { \tl_const:Nx #1 { \clist_trim_spaces:n {#2} } } -\cs_generate_variant:Nn \clist_const:Nn { c , Nx , cx } -% \end{macrocode} -% \end{macro} +% \subsection{Scratch comma lists} % -% \begin{macro}[EXP, pTF]{\clist_if_empty:n} -% \begin{macro}[aux, EXP]{\clist_if_empty_n_aux:w} -% \begin{macro}[aux, EXP]{\clist_if_empty_n_aux:wNw} -% As usual, we insert a token (here |?|) before grabbing -% any argument: this avoids losing braces. The argument -% of \cs{tl_if_empty:oTF} is empty if |#1| is |?| followed -% by blank spaces (besides, this particular variant of -% the emptyness test is optimized). If the item of the -% comma list is blank, grab the next one. As soon as one -% item is non-blank, exit: the second auxiliary will grab -% \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. +% \begin{variable}{\l_tmpa_clist, \l_tmpb_clist} +% \begin{variable}{\g_tmpa_clist, \g_tmpb_clist} +% Temporary comma list variables. % \begin{macrocode} -\prg_new_conditional:Npnn \clist_if_empty:n #1 { p , T , F , TF } - { - \clist_if_empty_n_aux:w ? #1 - , \q_mark \prg_return_false: - , \q_mark \prg_return_true: - \q_stop - } -\cs_new:Npn \clist_if_empty_n_aux:w #1 , - { - \tl_if_empty:oTF { \use_none:nn #1 ? } - { \clist_if_empty_n_aux:w ? } - { \clist_if_empty_n_aux:wNw } - } -\cs_new:Npn \clist_if_empty_n_aux:wNw #1 \q_mark #2#3 \q_stop {#2} +\clist_new:N \l_tmpa_clist +\clist_new:N \l_tmpb_clist +\clist_new:N \g_tmpa_clist +\clist_new:N \g_tmpb_clist % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} +% \end{variable} +% \end{variable} % % \subsection{Deprecated interfaces} % @@ -1664,7 +1441,7 @@ % } % Since clist items are now always stripped from their surrounding % spaces, it is redundant to provide these functions. -% The \cs{clist_trim_spaces:n} function is now internal, +% The \cs{@@_trim_spaces:n} function is now internal, % deprecated for use outside the kernel. % \begin{macrocode} %<*deprecated> @@ -1676,6 +1453,38 @@ % \end{macrocode} % \end{macro} % +% Deprecated on 2012-05-10, for removal by 2012-08-31. +% +% \begin{macro}[pTF] +% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc} +% Simple copies from the token list variable material. +% \begin{macrocode} +\prg_new_eq_conditional:NNn \clist__if_eq:NN \tl_if_eq:NN { p , T , F , TF } +\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc { p , T , F , TF } +\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN { p , T , F , TF } +\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc { p , T , F , TF } +% \end{macrocode} +% \end{macro} +% +% Deprecated 2012-05-13 for removal by 2012-11-31. +% +% \begin{macro}{\clist_length:N, \clist_length:c, \clist_length:n} +% \begin{macrocode} +\cs_new_eq:NN \clist_length:N \clist_count:N +\cs_new_eq:NN \clist_length:n \clist_count:c +\cs_new_eq:NN \clist_length:c \clist_count:n +% \end{macrocode} +% \end{macro} +% +% Deprecated 2012-05-19 for removal by 2012-11-31. +% +% \begin{macro}{\clist_use:N, \clist_use:c} +% \begin{macrocode} +\cs_new_eq:NN \clist_use:N \tl_use:N +\cs_new_eq:NN \clist_use:c \tl_use:c +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} |