summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3clist.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3clist.dtx606
1 files changed, 380 insertions, 226 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
index b2c09e72e15..53823cde267 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
@@ -10,7 +10,7 @@
%%
%% http://www.latex-project.org/lppl.txt
%%
-%% This file is part of the "expl3 bundle" (The Work in LPPL)
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
@@ -36,7 +36,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3clist.dtx 2725 2011-09-05 18:53:03Z bruno $
+\GetIdInfo$Id: l3clist.dtx 2798 2011-09-10 15:42:13Z will $
{L3 Experimental comma separated lists}
%</driver|package>
%<*driver>
@@ -162,8 +162,7 @@
%
% \begin{function}{\clist_concat:NNN, \clist_concat:ccc}
% \begin{syntax}
-% \cs{clist_concat:NNN} \meta{comma list1} \meta{comma list2}
-% ~~\meta{comma list3}
+% \cs{clist_concat:NNN} \meta{comma list1} \meta{comma list2} \meta{comma list3}
% \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
@@ -174,8 +173,7 @@
%
% \begin{function}{\clist_gconcat:NNN, \clist_gconcat:ccc}
% \begin{syntax}
-% \cs{clist_gconcat:NNN} \meta{comma list1} \meta{comma list2}
-% ~~\meta{comma list3}
+% \cs{clist_gconcat:NNN} \meta{comma list1} \meta{comma list2} \meta{comma list3}
% \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
@@ -184,14 +182,47 @@
% \meta{comma list1}.
% \end{function}
%
-% \section{Appending items to comma lists}
+% \section{Adding data to comma lists}
%
-% \begin{function}{
-% \clist_put_left:Nn, \clist_put_left:NV,
-% \clist_put_left:No, \clist_put_left:Nx,
-% \clist_put_left:cn, \clist_put_left:cV,
-% \clist_put_left:co, \clist_put_left:cx
-% }
+% \begin{function}[added = 2011-09-06]
+% {
+% \clist_set:Nn, \clist_set:NV,
+% \clist_set:No, \clist_set:Nx,
+% \clist_set:cn, \clist_set:cV,
+% \clist_set:co, \clist_set:cx
+% }
+% \begin{syntax}
+% \cs{clist_set:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
+% \end{syntax}
+% Sets \meta{comma list} to contain the \meta{items},
+% removing any previous content from the variable.
+% Spaces are removed from both sides of each item.
+% The assignment is restricted to the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}[added = 2011-09-06]
+% {
+% \clist_gset:Nn, \clist_gset:NV,
+% \clist_gset:No, \clist_gset:Nx,
+% \clist_gset:cn, \clist_gset:cV,
+% \clist_gset:co, \clist_gset:cx
+% }
+% \begin{syntax}
+% \cs{clist_gset:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
+% \end{syntax}
+% Sets \meta{comma list} to contain the \meta{items},
+% removing any previous content from the variable.
+% Spaces are removed from both sides of each item.
+% The assignment is global.
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-05]
+% {
+% \clist_put_left:Nn, \clist_put_left:NV,
+% \clist_put_left:No, \clist_put_left:Nx,
+% \clist_put_left:cn, \clist_put_left:cV,
+% \clist_put_left:co, \clist_put_left:cx
+% }
% \begin{syntax}
% \cs{clist_put_left:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
% \end{syntax}
@@ -200,12 +231,13 @@
% The assignment is restricted to the current \TeX{} group.
% \end{function}
%
-% \begin{function}{
-% \clist_gput_left:Nn, \clist_gput_left:NV,
-% \clist_gput_left:No, \clist_gput_left:Nx,
-% \clist_gput_left:cn, \clist_gput_left:cV,
-% \clist_gput_left:co, \clist_gput_left:cx
-% }
+% \begin{function}[updated = 2011-09-05]
+% {
+% \clist_gput_left:Nn, \clist_gput_left:NV,
+% \clist_gput_left:No, \clist_gput_left:Nx,
+% \clist_gput_left:cn, \clist_gput_left:cV,
+% \clist_gput_left:co, \clist_gput_left:cx
+% }
% \begin{syntax}
% \cs{clist_gput_left:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
% \end{syntax}
@@ -214,12 +246,13 @@
% The assignment is global.
% \end{function}
%
-% \begin{function}{
-% \clist_put_right:Nn, \clist_put_right:NV,
-% \clist_put_right:No, \clist_put_right:Nx,
-% \clist_put_right:cn, \clist_put_right:cV,
-% \clist_put_right:co, \clist_put_right:cx
-% }
+% \begin{function}[updated = 2011-09-05]
+% {
+% \clist_put_right:Nn, \clist_put_right:NV,
+% \clist_put_right:No, \clist_put_right:Nx,
+% \clist_put_right:cn, \clist_put_right:cV,
+% \clist_put_right:co, \clist_put_right:cx
+% }
% \begin{syntax}
% \cs{clist_put_right:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
% \end{syntax}
@@ -228,12 +261,13 @@
% The assignment is restricted to the current \TeX{} group.
% \end{function}
%
-% \begin{function}{
-% \clist_gput_right:Nn, \clist_gput_right:NV,
-% \clist_gput_right:No, \clist_gput_right:Nx,
-% \clist_gput_right:cn, \clist_gput_right:cV,
-% \clist_gput_right:co, \clist_gput_right:cx
-% }
+% \begin{function}[updated = 2011-09-05]
+% {
+% \clist_gput_right:Nn, \clist_gput_right:NV,
+% \clist_gput_right:No, \clist_gput_right:Nx,
+% \clist_gput_right:cn, \clist_gput_right:cV,
+% \clist_gput_right:co, \clist_gput_right:cx
+% }
% \begin{syntax}
% \cs{clist_gput_right:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
% \end{syntax}
@@ -254,10 +288,10 @@
%
% \section{Modifying comma lists}
%
-% While comma lists are normally used as ordered lists, it may be
-% necessary to modify the content. The functions here may be used
-% to update comma lists, while retaining the order of the unaffected
-% entries.
+% While comma lists are normally used as ordered lists, it may be
+% necessary to modify the content. The functions here may be used
+% to update comma lists, while retaining the order of the unaffected
+% entries.
%
% \begin{function}{\clist_remove_duplicates:N, \clist_remove_duplicates:c}
% \begin{syntax}
@@ -295,7 +329,7 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}{\clist_remove_all:Nn, \clist_remove_all:cn}
+% \begin{function}[updated = 2011-09-06]{\clist_remove_all:Nn, \clist_remove_all:cn}
% \begin{syntax}
% \cs{clist_remove_all:Nn} \meta{comma list} \Arg{item}
% \end{syntax}
@@ -308,7 +342,7 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}{\clist_gremove_all:Nn, \clist_gremove_all:cn}
+% \begin{function}[updated = 2011-09-06]{\clist_gremove_all:Nn, \clist_gremove_all:cn}
% \begin{syntax}
% \cs{clist_gremove_all:Nn} \meta{comma list} \Arg{item}
% \end{syntax}
@@ -326,8 +360,7 @@
% \begin{function}[EXP,pTF]{\clist_if_empty:N, \clist_if_empty:c}
% \begin{syntax}
% \cs{clist_if_empty_p:N} \meta{comma list}
-% \cs{clist_if_empty:NTF} \meta{comma list}
-% ~~\Arg{true code} \Arg{false code}
+% \cs{clist_if_empty:NTF} \meta{comma list} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \meta{comma list} is empty (containing no items).
% \end{function}
@@ -336,27 +369,34 @@
% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc}
% \begin{syntax}
% \cs{clist_if_eq_p:NN} \Arg{clist1} \Arg{clist2}
-% \cs{clist_if_eq:NNTF} \Arg{clist1} \Arg{clist2} \Arg{true code}
-% ~~\Arg{false code}
+% \cs{clist_if_eq:NNTF} \Arg{clist1} \Arg{clist2} \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}[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{function}[updated = 2011-09-06, 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{syntax}
-% \cs{clist_if_in:NnTF} \meta{comma list} \Arg{item}
-% ~~\Arg{true code} \Arg{false code}
+% \cs{clist_if_in:NnTF} \meta{comma list} \Arg{item} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \meta{item} is present in the \meta{comma list}.
+% In the case of an \texttt{n}-type \meta{comma list},
+% spaces are stripped from each item, but braces are not removed.
+% Hence,
+% \begin{verbatim}
+% \clist_if_in:nnTF { a , {b}~ , {b} , c } { b } {true} {false}
+% \end{verbatim}
+% yields \texttt{false}.
% \begin{texnote}
% The \meta{item} may not contain |{|, |}|, or |#|
-% (assuming the usual \TeX{} category codes apply).
+% (assuming the usual \TeX{} category codes apply),
+% and should not contain |,| nor start or end with a space.
% \end{texnote}
% \end{function}
%
@@ -407,8 +447,7 @@
% \begin{function}
% {\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.}
+% \cs{clist_map_variable:NNn} \meta{comma list} \meta{tl~var.} \Arg{function using tl~var.}
% \end{syntax}
% Stores each entry in the \meta{comma list} in turn in the
% \meta{tl~var.}\ and applies the \meta{function using tl~var.}
@@ -437,7 +476,7 @@
% \end{verbatim}
% Use outside of a \cs{clist_map_\ldots} scenario will lead to low
% level \TeX{} errors.
-% \begin{texnote}^^A temporarily untrue, fixed next week.
+% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
% internal macro \cs{clist_break_point:n} before further items are taken
% from the input stream. This will depend on the design of the mapping
@@ -482,8 +521,6 @@
% 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.
%
-% \section{Comma lists as stacks}
-%
% \begin{function}{\clist_get:NN, \clist_get:cN}
% \begin{syntax}
% \cs{clist_get:NN} \meta{comma list} \meta{token list variable}
@@ -502,7 +539,7 @@
% \meta{comma list}. The \meta{token list variable} is assigned locally.
% \end{function}
%
-% \begin{function}{\clist_pop:NN, \clist_pop:cN}
+% \begin{function}[updated = 2011-09-06]{\clist_pop:NN, \clist_pop:cN}
% \begin{syntax}
% \cs{clist_pop:NN} \meta{comma list} \meta{token list variable}
% \end{syntax}
@@ -529,9 +566,10 @@
% \clist_push:cn, \clist_push:cV, \clist_push:co, \clist_push:cx
% }
% \begin{syntax}
-% \cs{clist_push:Nn} \meta{comma list} \Arg{item}
+% \cs{clist_push:Nn} \meta{comma list} \Arg{items}
% \end{syntax}
-% Adds the \Arg{item} to the top of the \meta{comma list}.
+% Adds the \Arg{items} to the top of the \meta{comma list}.
+% Spaces are removed from both sides of each item.
% The assignment is restricted to the current \TeX{} group.
% \end{function}
%
@@ -541,10 +579,12 @@
% \clist_gpush:cn, \clist_gpush:cV, \clist_gpush:co, \clist_gpush:cx
% }
% \begin{syntax}
-% \cs{clist_gpush:Nn} \meta{comma list} \Arg{item}
+% \cs{clist_gpush:Nn} \meta{comma list} \Arg{items}
% \end{syntax}
-% Pushes the \meta{item} onto the end of the top of the
-% \meta{comma list}. The assignment is global.
+% Pushes the \meta{items} onto the end of the top of the
+% \meta{comma list}.
+% Spaces are removed from both sides of each item.
+% The assignment is global.
% \end{function}
%
% \section{Viewing comma lists}
@@ -556,12 +596,29 @@
% Displays the entries in the \meta{comma list} in the terminal.
% \end{function}
%
+% \section{Scratch comma lists}
+%
+% \begin{variable}[added = 2011-09-06]{\l_tmpa_clist, \l_tmpb_clist}
+% Scratch comma lists for local assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}[added = 2011-09-06]{\g_tmpa_clist, \g_tmpb_clist}
+% Scratch comma lists for global assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% 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}[EXP]{\clist_length:N, \clist_length:c,\clist_length:n}
+% \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}
@@ -571,7 +628,8 @@
% \emph{i.e.}~every item in a \meta{comma list} is unique.
% \end{function}
%
-% \begin{function}[EXP]{\clist_item:Nn, \clist_item:cn, \clist_item:nn}
+% \begin{function}[updated = 2011-09-06, EXP]
+% {\clist_item:Nn, \clist_item:cn, \clist_item:nn}
% \begin{syntax}
% \cs{clist_item:Nn} \meta{comma list} \Arg{integer expression}
% \end{syntax}
@@ -585,7 +643,7 @@
% nothing.
% \end{function}
%
-% \begin{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
@@ -595,9 +653,10 @@
% \end{syntax}
% Sets the \meta{comma list} within the current \TeX{} group 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}
+% \begin{function}[updated = 2011-08-31]
% {
% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
@@ -607,38 +666,21 @@
% \end{syntax}
% Sets the \meta{comma list} globally to equal to the content of the
% \meta{sequence}.
+% Items which contain either spaces or commas are surrounded by braces.
% \end{function}
%
-% \section{Deprecated comma-list functions}
+% \section{Internal comma-list functions}
%
-% \begin{function}{\clist_trim_spaces:N, \clist_trim_spaces:c}
+% \begin{function}[added = 2011-07-09, rEXP]{\clist_trim_spaces:n}
% \begin{syntax}
-% \cs{clist_trim_spaces:N} \meta{comma list}
-% \end{syntax}
-% Removes leading and trailing spaces from each \meta{item} in the
-% \meta{comma list} within the current \TeX{} group. This space-removal
-% process takes place as described for \cs{tl_trim_spaces:n}.
-% \end{function}
-%
-% \begin{function}{\clist_gtrim_spaces:N, \clist_gtrim_spaces:c}
-% \begin{syntax}
-% \cs{clist_gtrim_spaces:N} \meta{comma list}
-% \end{syntax}
-% Removes leading and trailing spaces from each \meta{item} in the
-% \meta{comma list} globally. This space-removal
-% process takes place as described for \cs{tl_trim_spaces:n}.
-% \end{function}
-%
-% \begin{function}[rEXP]{\clist_trim_spaces:n}
-% \begin{syntax}
-% \cs{clist_trim_spaces:N} \meta{comma list}
+% \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.
+% input stream. This is used by the functions which add data
+% into a comma list.
% \end{function}
%
-%
% \end{documentation}
%
% \begin{implementation}
@@ -659,16 +701,20 @@
%</package>
% \end{macrocode}
%
-%^^A todo: provide users with \l_tmpa_clist and friends?
-%
-% \begin{variable}{\l_clist_tmpa_tl, \l_clist_tmpb_tl}
+% \begin{variable}{\l_clist_tmpa_tl}
% Scratch space for various internal uses.
% \begin{macrocode}
\tl_new:N \l_clist_tmpa_tl
-\tl_new:N \l_clist_tmpb_tl
% \end{macrocode}
% \end{variable}
%
+% \begin{macro}[aux]{\clist_tmp:w}
+% A temporary function for various purposes.
+% \begin{macrocode}
+\cs_new_protected:Npn \clist_tmp:w { }
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{Allocation and initialisation}
%
% \begin{macro}{\clist_new:N,\clist_new:c}
@@ -736,8 +782,7 @@
% \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 there is
-% the danger that |#1| may be the same as either |#2| or |#3|. Also,
+% Concatenating sequences 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}
@@ -749,16 +794,9 @@
{
#1 #2
{
- \clist_if_empty:NTF #3
- { \exp_not:o #4 }
- {
- \exp_not:o #3
- \clist_if_empty:NF #4
- {
- ,
- \exp_not:o #4
- }
- }
+ \exp_not:o #3
+ \clist_if_empty:NF #3 { \clist_if_empty:NF #4 { , } }
+ \exp_not:o #4
}
}
\cs_generate_variant:Nn \clist_concat:NNN { ccc }
@@ -770,13 +808,6 @@
%
% \subsection{Removing spaces around items}
%
-% \begin{macro}[aux]{\clist_tmp:w}
-% A temporary function for various purposes.
-% \begin{macrocode}
-\cs_new_protected:Npn \clist_tmp:w { }
-% \end{macrocode}
-% \end{macro}
-%
% \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}
@@ -851,9 +882,32 @@
% \end{macro}
% \end{macro}
%
+% \subsection{Adding data to comma lists}
%
-%
-% \subsection{Appending items to comma lists}
+% \begin{macro}
+% {
+% \clist_set:Nn, \clist_set:NV,
+% \clist_set:No, \clist_set:Nx,
+% \clist_set:cn, \clist_set:cV,
+% \clist_set:co, \clist_set:cx
+% }
+% \begin{macro}
+% {
+% \clist_gset:Nn, \clist_gset:NV,
+% \clist_gset:No, \clist_gset:Nx,
+% \clist_gset:cn, \clist_gset:cV,
+% \clist_gset:co, \clist_gset:cx
+% }
+% \begin{macrocode}
+\cs_new_protected:Npn \clist_set:Nn #1#2
+ { \tl_set:Nx #1 { \clist_trim_spaces:n {#2} } }
+\cs_new_protected:Npn \clist_gset:Nn #1#2
+ { \tl_gset:Nx #1 { \clist_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}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}
% {
@@ -862,7 +916,7 @@
% \clist_put_left:cn, \clist_put_left:cV,
% \clist_put_left:co, \clist_put_left:cx
% }
-%^^A \UnitTested
+% \UnitTested
% \begin{macro}
% {
% \clist_gput_left:Nn, \clist_gput_left:NV,
@@ -870,7 +924,7 @@
% \clist_gput_left:cn, \clist_gput_left:cV,
% \clist_gput_left:co, \clist_gput_left:cx
% }
-%^^A \UnitTested
+% \UnitTested
% Comma lists cannot hold empty values: there are therefore a couple
% of sanity checks to avoid accumulating commas.
% \begin{macrocode}
@@ -946,34 +1000,35 @@
% \UnitTested
% \begin{macro}{\clist_gpop:NN, \clist_gpop:cN}
% \UnitTested
-% \begin{macro}[aux]{\clist_pop_aux:NNN}
-% \begin{macro}[aux]{\clist_pop_aux:wNNN}
+% \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.
-%^^A broken for {a,{b,c}}, which unbraces {b,c}.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \clist_pop:NN
- { \clist_pop_aux:NNN \tl_set:Nn }
+ { \clist_pop_aux:NNN \tl_set:Nf }
\cs_new_protected_nopar:Npn \clist_gpop:NN
- { \clist_pop_aux:NNN \tl_gset:Nn }
+ { \clist_pop_aux:NNN \tl_gset:Nf }
\cs_new_protected_nopar:Npn \clist_pop_aux:NNN #1#2#3
- { \exp_after:wN \clist_pop_aux:wNNN #2 , \q_nil , \q_nil , \q_stop #1#2#3 }
-\cs_new_protected:Npn \clist_pop_aux:wNNN #1 , #2 , \q_nil , #3 \q_stop #4#5#6
{
+ \exp_after:wN \clist_pop_aux:wNNN #2 , \q_nil \q_stop #1#2#3
+ }
+\cs_new_protected:Npn \clist_pop_aux:wNNN #1 , #2 \q_stop #3#4#5
+ {
+ \tl_set:Nn #5 {#1}
\quark_if_nil:nTF {#2}
- { #4 #5 { } }
- { #4 #5 {#2} }
- \tl_set:Nn #6 {#1}
+ { #3 #4 { } }
+ { #3 #4 { \clist_pop_aux:w \exp_stop_f: #2 } }
}
+\cs_new_protected:Npn \clist_pop_aux:w #1 , \q_nil {#1}
\cs_generate_variant:Nn \clist_pop:NN { c }
\cs_generate_variant:Nn \clist_gpop:NN { 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,
@@ -1061,42 +1116,58 @@
% \UnitTested
% \begin{macro}[aux]{\clist_remove_all_aux:NNn}
% \begin{macro}[aux]{\clist_remove_all_aux:w}
-% Removing an item from a comma list is done without looping over
-% the entire list, as the performance of that approach is very bad for
-% long lists. Instead, a delimited function is needed. For this to work
-% correctly, there is a need to add an additional comma at the start of
-% the list, and to remove it again once the removal is complete. Of
-% course, the list can end up empty, which is the reason for the test
-% before copying back to the parent.
+% \begin{macro}[aux]{\clist_remove_all_aux:}
+% 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,
+% the \cs{q_mark} delimiter used is the one inserted by
+% \cs{clist_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}),
+% and lets \cs{use_none_delimit_by_q_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,
+% which we remove in a second assignment.
+% Two exceptions: if the clist lost all of its elements, the result
+% is empty, and we shouldn't remove anything; if the clist started up
+% empty, the first step happens to turn it into a single comma, and
+% the second step removes it.
% \begin{macrocode}
\cs_new_protected:Npn \clist_remove_all:Nn
- { \clist_remove_all_aux:NNn \clist_set_eq:NN }
+ { \clist_remove_all_aux:NNn \tl_set:Nx }
\cs_new_protected:Npn \clist_gremove_all:Nn
- { \clist_remove_all_aux:NNn \clist_gset_eq:NN }
+ { \clist_remove_all_aux:NNn \tl_gset:Nx }
\cs_new_protected:Npn \clist_remove_all_aux:NNn #1#2#3
{
+ \cs_set:Npn \clist_tmp:w ##1 , #3 ,
+ {
+ ##1
+ , \q_mark , \use_none_delimit_by_q_stop:w ,
+ \clist_remove_all_aux:
+ }
+ #1 #2
+ {
+ \exp_after:wN \clist_remove_all_aux:
+ #2 , \q_mark , #3 , \q_stop
+ }
\clist_if_empty:NF #2
{
- \clist_clear:N \l_clist_remove_clist
- \cs_set_protected:Npn \clist_remove_all_aux:w
- ##1 , #3 , ##2 \q_stop
+ #1 #2
{
- \tl_put_right:Nn \l_clist_remove_clist {##1}
- \quark_if_no_value:nF {##2}
- { \clist_remove_all_aux:w , ##2 \q_stop }
+ \exp_args:No \exp_not:o
+ { \exp_after:wN \use_none:n #2 }
}
- \exp_after:wN \clist_remove_all_aux:w
- \exp_after:wN , #2 , #3 , \q_no_value \q_stop
- \tl_if_empty:NF \l_clist_remove_clist
- {
- \exp_after:wN \tl_set:No \exp_after:wN
- \l_clist_remove_clist \exp_after:wN
- { \exp_after:wN \use_none:n \l_clist_remove_clist }
- }
- #1 #2 \l_clist_remove_clist
}
}
-\cs_new_protected:Npn \clist_remove_all_aux:w { }
+\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_generate_variant:Nn \clist_remove_all:Nn { c }
\cs_generate_variant:Nn \clist_gremove_all:Nn { c }
% \end{macrocode}
@@ -1104,10 +1175,17 @@
% \end{macro}
% \end{macro}
% \end{macro}
-%
+% \end{macro}
%
% \subsection{Comma list conditionals}
%
+% \begin{variable}{\l_clist_if_in_clist}
+% An internal comma list for \cs{clist_if_in:nn} conditionals.
+% \begin{macrocode}
+\clist_new:N \l_clist_if_in_clist
+% \end{macrocode}
+% \end{variable}
+%
% \begin{macro}[pTF]{\clist_if_empty:N, \clist_if_empty:c}
% \UnitTested
% Simple copies from the token list variable material.
@@ -1132,35 +1210,29 @@
% \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: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}
% \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 }
+\prg_new_protected_conditional:Npnn \clist_if_in:Nn #1#2 { T , F , TF }
{
- \cs_set_protected:Npn \clist_tmp:w ##1 , #2 , ##2##3 \q_stop
- {
- \if_meaning:w \q_no_value ##2
- \prg_return_false:
- \else:
- \prg_return_true:
- \fi:
- }
- \exp_last_unbraced:NNo \clist_tmp:w , #1 , #2 , \q_no_value \q_stop
+ \exp_args:No \clist_if_in_return:nn #1 {#2}
}
-\prg_new_protected_conditional:Npnn \clist_if_in:nn #1#2
- { T , F , TF }
+\prg_new_protected_conditional:Npnn \clist_if_in:nn #1#2 { T , F , TF }
{
- \cs_set_protected:Npn \clist_tmp:w ##1 , #2 , ##2##3 \q_stop
- {
- \if_meaning:w \q_no_value ##2
- \prg_return_false:
- \else:
- \prg_return_true:
- \fi:
- }
- \clist_tmp:w , #1 , #2 , \q_no_value \q_stop
+ \clist_set:Nn \l_clist_if_in_clist {#1}
+ \exp_args:No \clist_if_in_return:nn \l_clist_if_in_clist {#2}
+ }
+\cs_new_protected:Npn \clist_if_in_return:nn #1#2
+ {
+ \cs_set:Npn \clist_tmp:w ##1 ,#2, { }
+ \tl_if_empty:oTF
+ { \clist_tmp:w ,#1, {} {} ,#2, }
+ { \prg_return_false: } { \prg_return_true: }
}
\cs_generate_variant:Nn \clist_if_in:NnT { NV , No }
\cs_generate_variant:Nn \clist_if_in:NnT { c , cV , co }
@@ -1173,6 +1245,7 @@
\cs_generate_variant:Nn \clist_if_in:nnTF { nV , no }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \subsection{Mapping to comma lists}
%
@@ -1182,6 +1255,8 @@
% \UnitTested
% \begin{macro}[aux]{\clist_map_function_aux:Nw}
% Mapping to comma lists is pretty simple, if not massively efficient.
+% The auxiliary function \cs{clist_map_function_aux:Nw} is used
+% directly in \cs{clist_length:n}. Change with care.
% \begin{macrocode}
\cs_new_nopar:Npn \clist_map_function:NN #1#2
{
@@ -1316,7 +1391,7 @@
% \begin{macro}{\clist_map_break:}
% \UnitTested
% \begin{macro}{\clist_map_break:n}
-% Both are simple renaming.^^A todo: fix \clist_map_break:n (cf. seq).
+% Both are simple renaming.
% \begin{macrocode}
\cs_new_eq:NN \clist_map_break: \use_none_delimit_by_q_recursion_stop:w
\cs_new_eq:NN \clist_map_break:n \use_i_delimit_by_q_recursion_stop:nw
@@ -1367,6 +1442,20 @@
% \end{macro}
% \end{macro}
%
+% \subsection{Scratch comma lists}
+%
+% \begin{variable}{\l_tmpa_clist, \l_tmpb_clist}
+% \begin{variable}{\g_tmpa_tl, \g_tmpb_tl}
+% 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}
@@ -1375,7 +1464,11 @@
% 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
% integer evaluation to actually do the mathematics.
-%^^A todo: make a faster version avoiding \clist_map_function:nN?
+% 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 call \cs{clist_map_function_aux:Nw}
+% directly, and test for each item whether it is blank (hence should
+% be ignored).
% \begin{macrocode}
\cs_new:Npn \clist_length:N #1
{
@@ -1385,15 +1478,17 @@
\clist_map_function:NN #1 \clist_length_aux:n
}
}
+\cs_new:Npn \clist_length_aux:n #1 { +1 }
\cs_new:Npn \clist_length:n #1
{
\int_eval:n
{
0
- \clist_map_function:nN {#1} \clist_length_aux:n
+ \clist_map_function_aux:Nw \clist_length_n_aux:n #1
+ , \q_recursion_tail , \q_recursion_stop
}
}
-\cs_new:Npn \clist_length_aux:n #1 { +1 }
+\cs_new:Npn \clist_length_n_aux:n #1 { \tl_if_blank:nF {#1} {+1} }
\cs_generate_variant:Nn \clist_length:N { c }
% \end{macrocode}
% \end{macro}
@@ -1401,35 +1496,44 @@
% \end{macro}
%
% \begin{macro}{\clist_item:Nn, \clist_item:cn}
-% \begin{macro}{\clist_item:nn}
-% \begin{macro}[aux]{\clist_item_aux:nnn}
-% The idea here is to find the offset of the item from the left, then use
-% a loop to grab the correct item. If the resulting offset is too large,
-% then \cs{quark_if_recursion_stop:n} will be true,
-% terminating the loop and returning nothing at all.
+% \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_set_nopar:Npn \clist_item:Nn #1#2
- { \exp_args:No \clist_item:nn #1 {#2} }
-\cs_set:Npn \clist_item:nn #1#2
+\cs_new:Npn \clist_item:Nn #1#2
{
- \int_compare:nNnTF {#2} < \c_zero
+ \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 } } }
+ }
{
- \exp_args:Nf \clist_item_aux:nw
- { \int_eval:n { \clist_length:n {#1} + #2 } }
- #1 , \q_recursion_tail \q_recursion_stop
+ \int_compare:nNnTF {#4} < {#1}
+ { #3 {#4} }
+ { \use_none_delimit_by_q_stop:w }
}
- { \clist_item_aux:nw {#2} #1 , \q_recursion_tail \q_recursion_stop }
+ #2, \q_stop
}
-\cs_set:Npn \clist_item_aux:nw #1#2 , #3
+\cs_new:Npn \clist_item_N_loop:nw #1 #2,
{
\int_compare:nNnTF {#1} = \c_zero
- { \use_i_delimit_by_q_recursion_stop:nw {#2} }
- {
- \quark_if_recursion_tail_stop:n {#3}
- \exp_args:Nf \clist_item_aux:nw
- { \int_eval:n { #1 - 1 } }
- #3
- }
+ { \use_i_delimit_by_q_stop:nw {#2} }
+ { \exp_args:Nf \clist_item_N_loop:nw { \int_eval:n { #1 - 1 } } }
}
\cs_generate_variant:Nn \clist_item:Nn { c }
% \end{macrocode}
@@ -1437,6 +1541,51 @@
% \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 , {#1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}
% {
% \clist_set_from_seq:NN, \clist_set_from_seq:cN,
@@ -1450,31 +1599,31 @@
% }
% \UnitTested
% Setting a comma list from a comma-separated list is done using a simple
-% mapping. We wrap each item with braces, \cs{exp_not:n}, and a comma. The
+% 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{macrocode}
-\cs_new_protected:Npn \clist_set_from_seq:NN #1#2
- {
- \seq_if_empty:NTF #2
- { \clist_clear:N #1 }
- {
- \seq_push_item_def:n { , \exp_not:n {{##1}} }
- \tl_set:Nx #1
- { \exp_after:wN \use_none:n \tex_romannumeral:D -`\0 #2 }
- \seq_pop_item_def:
- }
- }
-\cs_new_protected:Npn \clist_gset_from_seq:NN #1#2
+\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
{
- \seq_if_empty:NTF #2
- { \clist_gclear:N #1 }
+ \seq_if_empty:NTF #4
+ { #1 #3 }
{
- \seq_push_item_def:n { , \exp_not:n {{##1}} }
- \tl_gset:Nx #1
- { \exp_after:wN \use_none:n \tex_romannumeral:D -`\0 #2 }
+ \seq_push_item_def:n
+ {
+ ,
+ \tl_if_empty:oTF { \clist_set_from_seq_aux:w ##1 ~ , ##1 ~ }
+ { \exp_not:n {##1} }
+ { \exp_not:n { {##1} } }
+ }
+ #2 #3 { \exp_last_unbraced:Nf \use_none:n #4 }
\seq_pop_item_def:
}
}
+\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 }
@@ -1491,8 +1640,10 @@
% \UnitTested
% These are old stack functions.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \clist_top:NN \clist_get:NN
\cs_new_eq:NN \clist_top:cN \clist_get:cN
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
@@ -1500,20 +1651,24 @@
% \UnitTested
% An older name for \cs{clist_remove_all:Nn}.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \clist_remove_element:Nn \clist_remove_all:Nn
\cs_new_eq:NN \clist_gremove_element:Nn \clist_gremove_all:Nn
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\clist_display:N, \clist_display:c}
% An older name for \cs{clist_show:N}.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \clist_display:N \clist_show:N
\cs_new_eq:NN \clist_display:c \clist_show:c
+%</deprecated>
% \end{macrocode}
% \end{macro}
-%
-% Deprecated on 2011-09-05, for removal by 2012-09-04.
+%
+% Deprecated on 2011-09-05, for removal by 2011-12-32.
%
% \begin{macro}
% {
@@ -1522,21 +1677,20 @@
% }
% 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,
+% deprecated for use outside the kernel.
% \begin{macrocode}
-\cs_new_protected:Npn \clist_trim_spaces:N #1
- { \tl_set:Nx #1 { \exp_args:No \clist_trim_spaces:n #1 } }
-\cs_new_protected:Npn \clist_gtrim_spaces:N #1
- { \tl_gset:Nx #1 { \exp_args:No \clist_trim_spaces:n #1 } }
+\cs_new_protected:Npn \clist_trim_spaces:N #1 { \clist_set:No #1 {#1} }
+\cs_new_protected:Npn \clist_gtrim_spaces:N #1 { \clist_gset:No #1 {#1} }
\cs_generate_variant:Nn \clist_trim_spaces:N { c }
\cs_generate_variant:Nn \clist_gtrim_spaces:N { c }
% \end{macrocode}
% \end{macro}
%
-%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
%
% \end{implementation}
%
-% \PrintIndex \ No newline at end of file
+% \PrintIndex