diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3clist.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3clist.dtx | 988 |
1 files changed, 551 insertions, 437 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3clist.dtx b/Master/texmf-dist/source/latex/expl3/l3clist.dtx index 0155c64f394..f875b7e0cbc 100644 --- a/Master/texmf-dist/source/latex/expl3/l3clist.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3clist.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3clist.dtx Copyright (C) 2005-2006 Frank Mittelbach, LaTeX3 project +%% File: l3clist.dtx Copyright (C) 2005-2008 Frank Mittelbach, LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} %</driver|package> %\fi -\GetIdInfo$Id: l3clist.dtx 745 2008-08-03 18:50:46Z morten $ +\GetIdInfo$Id: l3clist.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental comma separated lists} %\iffalse %<*driver> @@ -44,7 +44,7 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} @@ -61,9 +61,7 @@ % \date{\filedate} % \maketitle % -% -% -% \section{Comma lists} +% \begin{documentation} % % \LaTeX3 implements a data type called `clist (comma-lists)'. These % are special @@ -75,8 +73,8 @@ % part of the value). It is also possible to map functions on such % comma-lists so that they are executed for every item of the comma-list. % -% All functions that return items from a comma-list in some \m{tlp} assume -% that the \m{tlp} is local. See remarks below if you need a global +% All functions that return items from a comma-list in some \m{tl var.}~assume +% that the \m{tl var.}~is local. See remarks below if you need a global % returned value. % % The defined functions are not orthogonal in the sense that every @@ -89,7 +87,7 @@ % like "\clist_push:Nn" which has the same effect. Maybe one should % therefore remove the ``left'' functions totally. % -% \subsection{Functions} +% \section{Functions for creating/initialising comma-lists} % % \begin{function}{% % \clist_new:N | @@ -113,117 +111,153 @@ % These functions locally or globally clear <comma-list>. % \end{function} % +% \begin{function}{ \clist_clear_new:N | +% \clist_clear_new:c | +% \clist_gclear_new:N | +% \clist_gclear_new:c } +% \begin{syntax} +% "\clist_clear_new:N" <comma-list> +% \end{syntax} +% These functions locally or globally clear <comma-list> if it exists or +% otherwise allocates it. +% \end{function} +% +% \begin{function}{ \clist_set_eq:NN | +% \clist_set_eq:cN | +% \clist_set_eq:Nc | +% \clist_set_eq:cc } +% \begin{syntax} +% "\clist_set_eq:NN" <clist1> <clist2> +% \end{syntax} +% Function that locally makes <clist1> identical to <clist2>. +% \end{function} +% +% +% \begin{function}{ \clist_gset_eq:NN | +% \clist_gset_eq:cN | +% \clist_gset_eq:Nc | +% \clist_gset_eq:cc } +% \begin{syntax} +% "\clist_gset_eq:NN" <clist1> <clist2> +% \end{syntax} +% Function that globally makes <clist1> identical to <clist2>. +% \end{function} +% +% \section{Putting data in} +% % \begin{function}{% % \clist_put_left:Nn | +% \clist_put_left:NV | % \clist_put_left:No | % \clist_put_left:Nx | % \clist_put_left:cn | -% \clist_put_right:Nn | -% \clist_put_right:No | -% \clist_put_right:Nx | +% \clist_put_left:co | +% \clist_put_left:cV | % } % \begin{syntax} % "\clist_put_left:Nn" <comma-list> <token list> % \end{syntax} % Locally appends <token list> as a single item to the left -% or right of <comma-list>. <token list> might get expanded before -% appending. +% of <comma-list>. <token list> might get expanded before +% appending according to the variant used. % \end{function} % % \begin{function}{% -% \clist_gput_left:Nn | -% \clist_gput_right:Nn | -% \clist_gput_right:No | -% \clist_gput_right:cn | -% \clist_gput_right:co | -% \clist_gput_right:cc | +% \clist_put_right:Nn | +% \clist_put_right:No | +% \clist_put_right:NV | +% \clist_put_right:Nx | +% \clist_put_right:cn | +% \clist_put_right:co | +% \clist_put_right:cV | % } % \begin{syntax} -% "\clist_gput_left:Nn" <comma-list> <token list> +% "\clist_put_right:Nn" <comma-list> <token list> % \end{syntax} -% Globally appends <token list> as a single item to the left -% or right of <comma-list>. +% Locally appends <token list> as a single item to the right +% of <comma-list>. <token list> might get expanded before +% appending according to the variant used. % \end{function} % % \begin{function}{% -% \clist_get:NN | -% \clist_get:cN | +% \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 | % } % \begin{syntax} -% "\clist_get:NN" <comma-list> <tlp> +% "\clist_gput_left:Nn" <comma-list> <token list> % \end{syntax} -% Functions that locally assign the left-most item of <comma-list> to the -% token list pointer <tlp>. Item is not removed from <comma-list>! If you -% need a global return value you need to code something like this: -% \begin{quote} -% "\clist_get:NN" <comma-list> "\l_tmpa_tlp" \\ -% "\tlp_gset_eq:NN" <global tlp> "\l_tmpa_tlp" -% \end{quote} -% But if this kind of construction is used often enough a separate -% function should be provided. +% Globally appends <token list> as a single item to the +% right of <comma-list>. % \end{function} % % \begin{function}{% -% \clist_set_eq:NN +% \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 | % } % \begin{syntax} -% "\clist_set_eq:NN" <clist1> <clist2> +% "\clist_gput_right:Nn" <comma-list> <token list> % \end{syntax} -% Function that locally makes <clist1> identical to <clist2>. +% Globally appends <token list> as a single item to the +% right of <comma-list>. % \end{function} % +% \section{Getting data out} % -% \begin{function}{% -% \clist_gset_eq:NN | -% \clist_gset_eq:cN | -% \clist_gset_eq:Nc | -% \clist_gset_eq:cc -% } +% \begin{function}{ \clist_use:N | +% \clist_use:c } % \begin{syntax} -% "\clist_gset_eq:NN" <clist1> <clist2> +% "\clist_use:N" <clist> % \end{syntax} -% Function that globally makes <clist1> identical to <clist2>. +% Function that inserts the <clist> into the processing stream. Mainly +% useful if one knows what the <clist> contains, e.g., for displaying +% the content of template parameters. % \end{function} % -% -% \begin{function}{% -% \clist_concat:NNN | -% \clist_gconcat:NNN | -% \clist_gconcat:NNc | -% \clist_gconcat:ccc | -% } +% \begin{function}{ \clist_show:N | +% \clist_show:c } % \begin{syntax} -% "\clist_gconcat:NNN" <clist1> <clist2> <clist3> +% "\clist_show:N" <clist> % \end{syntax} -% Function that concatenates <clist2> and <clist3> and globally assigns the -% result to <clist1>. +% Function that pauses the compilation and displays <clist> in the terminal +% output and in the log file. (Usually used for diagnostic purposes.) % \end{function} % -% -% \begin{function}{% -% \clist_remove_duplicates:N | -% \clist_gremove_duplicates:N | -% } +% \begin{function}{ \clist_display:N | +% \clist_display:c } % \begin{syntax} -% "\clist_gremove_duplicates:N" <clist> +% "\clist_display:N" <clist> % \end{syntax} -% Function that removes any duplicate entries in <clist>. +% As with "\clist_show:N" but pretty prints the output one line per element. % \end{function} % -% \begin{function}{% -% \clist_use:N | -% \clist_use:c -% } +% \begin{function}{ \clist_get:NN | +% \clist_get:cN } % \begin{syntax} -% "\clist_use:N" <clist> +% "\clist_get:NN" <comma-list> <tl var.> % \end{syntax} -% Function that inserts the <clist> into the processing stream. Mainly -% useful if one knows what the <clist> contains, e.g., for displaying -% the content of template parameters. +% Functions that locally assign the left-most item of <comma-list> to the +% token list variable <tl var.>. Item is not removed from <comma-list>! If you +% need a global return value you need to code something like this: +% \begin{quote} +% "\clist_get:NN" <comma-list> "\l_tmpa_tl" \\ +% "\tl_gset_eq:NN" <global tl var.> "\l_tmpa_tl" +% \end{quote} +% But if this kind of construction is used often enough a separate +% function should be provided. % \end{function} % % -% \subsection{Mapping functions} +% \section{Mapping functions} % % % We provide three types of mapping functions, each with their own @@ -253,7 +287,7 @@ % \clist_map_inline:nn | % } % \begin{syntax} -% "\clist_map_inline:Nn" <comma-list> "{" <inline function> "}" +% "\clist_map_inline:Nn" <comma-list> \Arg{inline function} % \end{syntax} % Applies <inline function> (which should be the direct coding for a % function with one argument (i.e.\ use "##1" as the placeholder for @@ -269,7 +303,7 @@ % \clist_map_variable:nNn | % } % \begin{syntax} -% "\clist_map_variable:NNn" <comma-list> <temp-var> "{" <action> "}" +% "\clist_map_variable:NNn" <comma-list> <temp-var> \Arg{action} % \end{syntax} % Assigns <temp-var> to each element in <clist> and then executes % <action> which should contain <temp-var>. As the @@ -281,16 +315,16 @@ % \end{function} % % \begin{function}{% -% \clist_map_break:w | +% \clist_map_break: | % } % \begin{syntax} -% "\clist_map_break:w" +% "\clist_map_break:" % \end{syntax} % For breaking out of a loop. To be used inside "TF" type functions as % in the example below. % \begin{verbatim} -% \def_new:Npn \test_function:n #1 { -% \int_compare:nNnTF {#1}> 3 {\clist_map_break:w}{``#1''} +% \cs_new_nopar:Npn \test_function:n #1 { +% \intexpr_compare:nTF {#1 > 3} {\clist_map_break:}{``#1''} % } % \clist_map_function:nN {1,2,3,4,5,6,7,8}\test_function:n % \end{verbatim} @@ -298,9 +332,10 @@ % \end{function} % % -% \subsection{Predicates and conditionals} +% \section{Predicates and conditionals} % -% \begin{function}{\clist_if_empty_p:N} +% \begin{function}{ \clist_if_empty_p:N | +% \clist_if_empty_p:c } % \begin{syntax} % "\clist_if_empty_p:N" <comma-list> % \end{syntax} @@ -308,99 +343,87 @@ % contain any tokens. % \end{function} % -% \begin{function}{% -% \clist_if_empty:NTF | -% \clist_if_empty:cTF | -% \clist_if_empty:NF | -% \clist_if_empty:cF | -% } +% \begin{function}{ \clist_if_empty:N / (TF)(EXP) | +% \clist_if_empty:c / (TF)(EXP)} % \begin{syntax} -% "\clist_if_empty:NTF" <comma-list> "{" <true code> "}{" <false code> "}" +% "\clist_if_empty:NTF" <comma-list> \Arg{true code} \Arg{false code} % \end{syntax} % Set of conditionals that test whether or not a particular <comma-list> % is empty and if so executes either <true code> or <false code>. % \end{function} % -% \begin{function}{% -% \clist_if_eq:NNTF | -% } +% \begin{function}{ \clist_if_eq_p:NN / (EXP) | +% \clist_if_eq_p:cN / (EXP) | +% \clist_if_eq_p:Nc / (EXP) | +% \clist_if_eq_p:cc / (EXP) } % \begin{syntax} -% "\clist_if_eq:NNTF" <comma-list1> <comma-list2> "{" <true code> -% "}{" <false code> "}" +% "\clist_if_eq_p:N" <comma-list1> <comma-list2> +% \end{syntax} +% This predicate returns `true' if the two comma lists are identical. +% \end{function} +% +% \begin{function}{ \clist_if_eq:NN / (TF)(EXP) | +% \clist_if_eq:cN / (TF)(EXP) | +% \clist_if_eq:Nc / (TF)(EXP) | +% \clist_if_eq:cc / (TF)(EXP) } +% \begin{syntax} +% "\clist_if_eq:NNTF" <comma-list1> <comma-list2> \Arg{true code} \Arg{false code} % \end{syntax} % Check if <comma-list1> and <comma-list2> are equal and execute % either <true code> or <false code> accordingly. % \end{function} % -% \begin{function}{% -% \clist_if_in:NnTF | -% \clist_if_in:NoTF | -% \clist_if_in:cnTF | -% \clist_if_in:coTF | -% } +% \begin{function}{ \clist_if_in:Nn / (TF) | +% \clist_if_in:NV / (TF) | +% \clist_if_in:No / (TF) | +% \clist_if_in:cn / (TF) | +% \clist_if_in:cV / (TF) | +% \clist_if_in:co / (TF) } % \begin{syntax} -% "\clist_if_in:NnTF" <comma-list> "{" <item> "}{" <true code> "}{" -% <false code> "}" +% "\clist_if_in:NnTF" <comma-list> \Arg{item} \Arg{true code} \Arg{false code} % \end{syntax} % Function that tests if <item> is in <comma-list>. Depending on the result % either <true code> or <false code> is executed. % \end{function} % -% \subsection{Internal functions} +% \section{Higher level functions} % -% \begin{function}{\clist_if_empty_err:N} +% \begin{function}{ \clist_concat:NNN | +% \clist_concat:ccc | +% \clist_gconcat:NNN | +% \clist_gconcat:ccc } % \begin{syntax} -% "\clist_if_empty_err:N" <comma-list> +% "\clist_gconcat:NNN" <clist1> <clist2> <clist3> % \end{syntax} -% Signals an \LaTeX3 error if <comma-list> is empty. +% Function that concatenates <clist2> and <clist3> and locally or globally +% assigns the result to <clist1>. % \end{function} % -% \begin{function}{\clist_pop_aux:nnNN} +% +% \begin{function}{ \clist_remove_duplicates:N | +% \clist_gremove_duplicates:N } % \begin{syntax} -% "\clist_pop_aux:nnNN" <assign1> <assign2> <comma-list> <tlp> +% "\clist_gremove_duplicates:N" <clist> % \end{syntax} -% Function that assigns the left-most item of <comma-list> to <tlp> using -% <assign1> and assigns the tail to <comma-list> using <assign2>. This -% function could be used to implement a global return function. +% Function that removes any duplicate entries in <clist>. % \end{function} -% -% \begin{function}{% -% \clist_get_aux:w | -% \clist_pop_aux:w | -% \clist_pop_auxi:w | -% \clist_put_aux:NNnnNn | -% } -% \begin{syntax}\end{syntax} -% Functions used to implement put and get operations. They are not for -% meant for direct use. +% +% \begin{function}{ +% \clist_remove_element:Nn | +% \clist_gremove_element:Nn +%} +% \begin{syntax} +% "\clist_gremove_element:Nn" <clist> <element> +% \end{syntax} +% Function that removes <element> from <clist>, if present. +% \begin{texnote} +% This is similar in concept to \cs{@removeelement}, except that the +% syntax is clearer and the initial and final lists have the same +% name automatically. +% \end{texnote} % \end{function} % -% -% -% \begin{function}{% -% \clist_map_function_aux:Nw | -% \clist_map_inline_aux:Nw | -% \clist_map_variable_aux:Nnw | -% } -% \begin{syntax}\end{syntax} -% Internal helper functions for the <clist> mapping functions. -% \end{function} -% -% -% \begin{function}{% -% \clist_concat_aux:NNNN | -% \clist_remove_duplicates_aux:NN | -% \clist_remove_duplicates_aux:n | -% \l_clist_remove_duplicates_clist | -% } -% \begin{syntax}\end{syntax} -% Functions that help concatenate <clist>s and remove duplicate -% elements from a <clist>. -% \end{function} -% -% -% -% \subsection{Comma list Stacks} +% \section{Functions for `comma-list stacks'} % % Special comma-lists in \LaTeX3 are `stacks' with their usual operations % of `push', `pop', and `top'. They are internally implemented as @@ -409,14 +432,16 @@ % % \begin{function}{% % \clist_push:Nn | +% \clist_push:NV | % \clist_push:No | % \clist_push:cn | % \clist_gpush:Nn | +% \clist_gpush:NV | % \clist_gpush:No | % \clist_gpush:cn | % } % \begin{syntax} -% "\clist_push:Nn" <stack> "{" <token list> "}" +% "\clist_push:Nn" <stack> \Arg{token list} % \end{syntax} % Locally or globally pushes <token list> as a single item onto the % <stack>. <token list> might get expanded before the operation. @@ -429,10 +454,10 @@ % \clist_gpop:cN | % } % \begin{syntax} -% "\clist_pop:NN" <stack> <tlp> +% "\clist_pop:NN" <stack> <tl var.> % \end{syntax} % Functions that assign the top item of <stack> to the token -% list pointer <tlp> and removes it from <stack>! +% list variable <tl var.> and removes it from <stack>! % \end{function} % % \begin{function}{% @@ -440,38 +465,65 @@ % \clist_top:cN | % } % \begin{syntax} -% "\clist_top:NN" <stack> <tlp> +% "\clist_top:NN" <stack> <tl var.> % \end{syntax} % Functions that locally assign the top item of <stack> to the token -% list pointer <tlp>. Item is not removed from <stack>! +% list variable <tl var.>. Item is not removed from <stack>! % \end{function} % -% \StopEventually{} +% \section{Internal functions} % -% Use "clist" functions. +% \begin{function}{\clist_if_empty_err:N} +% \begin{syntax} +% "\clist_if_empty_err:N" <comma-list> +% \end{syntax} +% Signals an \LaTeX3 error if <comma-list> is empty. +% \end{function} % +% \begin{function}{\clist_pop_aux:nnNN} +% \begin{syntax} +% "\clist_pop_aux:nnNN" <assign1> <assign2> <comma-list> <tl var.> +% \end{syntax} +% Function that assigns the left-most item of <comma-list> to <tl var.> using +% <assign1> and assigns the tail to <comma-list> using <assign2>. This +% function could be used to implement a global return function. +% \end{function} % -% \subsection {The Implementation} +% \begin{function}{% +% \clist_get_aux:w | +% \clist_pop_aux:w | +% \clist_pop_auxi:w | +% \clist_put_aux:NNnnNn | +% } +% \begin{syntax}\end{syntax} +% Functions used to implement put and get operations. They are not for +% meant for direct use. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3clist} implementation} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%<package>\ProvidesExplPackage -%<package> {\filename}{\filedate}{\fileversion}{\filedescription} %<*package> -\NeedsTeXFormat{LaTeX2e} -%<!check>\RequirePackage{l3prg,l3quark} -%<check>\RequirePackage{l3chk} +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: %</package> %<*initex|package> % \end{macrocode} % +% \subsection{Allocation and initialisation} % % \begin{macro}{\clist_new:N} % \begin{macro}{\clist_new:c} % Comma-Lists are implemented using token lists. % \begin{macrocode} -\def_new:Npn \clist_new:N #1{\tlp_new:Nn #1{}} -\def_new:Npn \clist_new:c {\exp_args:Nc \clist_new:N} +\cs_new_eq:NN \clist_new:N \tl_new:N +\cs_generate_variant:Nn \clist_new:N {c} % \end{macrocode} % \end{macro} % \end{macro} @@ -482,10 +534,10 @@ % \begin{macro}{\clist_gclear:c} % Clearing a comma-list is the same as clearing a token list. % \begin{macrocode} -\let_new:NN \clist_clear:N \tlp_clear:N -\let_new:NN \clist_clear:c \tlp_clear:c -\let_new:NN \clist_gclear:N \tlp_gclear:N -\let_new:NN \clist_gclear:c \tlp_gclear:c +\cs_new_eq:NN \clist_clear:N \tl_clear:N +\cs_generate_variant:Nn \clist_clear:N {c} +\cs_new_eq:NN \clist_gclear:N \tl_gclear:N +\cs_generate_variant:Nn \clist_gclear:N {c} % \end{macrocode} % \end{macro} % \end{macro} @@ -493,24 +545,32 @@ % \end{macro} % % -% \begin{macro}{\clist_set_eq:NN} -% We can set one \meta{clist} equal to another. +% \begin{macro}{\clist_clear_new:N} +% \begin{macro}{\clist_clear_new:c} +% \begin{macro}{\clist_gclear_new:N} +% \begin{macro}{\clist_gclear_new:c} +% Clearing a comma-list is the same as clearing a token list. % \begin{macrocode} -\let_new:NN \clist_set_eq:NN \let:NN +\cs_new_eq:NN \clist_clear_new:N \tl_clear_new:N +\cs_generate_variant:Nn \clist_clear_new:N {c} +\cs_new_eq:NN \clist_gclear_new:N \tl_gclear_new:N +\cs_generate_variant:Nn \clist_gclear_new:N {c} % \end{macrocode} % \end{macro} -% +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_set_eq:NN} % \begin{macro}{\clist_set_eq:cN} % \begin{macro}{\clist_set_eq:Nc} % \begin{macro}{\clist_set_eq:cc} -% An of course globally which seems to be needed far more often. +% We can set one \meta{clist} equal to another. % \begin{macrocode} -\let_new:NN \clist_gset_eq:NN \glet:NN -\def_new:Npn \clist_gset_eq:cN {\exp_args:Nc \clist_gset_eq:NN} -\def_new:Npn \clist_gset_eq:Nc {\exp_args:NNc \clist_gset_eq:NN} -\def_new:Npn \clist_gset_eq:cc {\exp_args:Ncc \clist_gset_eq:NN} +\cs_new_eq:NN \clist_set_eq:NN \cs_set_eq:NN +\cs_new_eq:NN \clist_set_eq:cN \cs_set_eq:cN +\cs_new_eq:NN \clist_set_eq:Nc \cs_set_eq:Nc +\cs_new_eq:NN \clist_set_eq:cc \cs_set_eq:cc % \end{macrocode} % \end{macro} % \end{macro} @@ -518,33 +578,30 @@ % \end{macro} % % -% \begin{macro}{\clist_if_empty_p:N} -% A predicate which evaluates to |\c_true| iff the comma-list is empty. -% \begin{macrocode} -\let_new:NN \clist_if_empty_p:N \tlp_if_empty_p:N -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\clist_if_empty:NTF} -% \begin{macro}{\clist_if_empty:NT} -% \begin{macro}{\clist_if_empty:NF} -% \begin{macro}{\clist_if_empty:cTF} -% \begin{macro}{\clist_if_empty:cT} -% \begin{macro}{\clist_if_empty:cF} -% |\clist_if_empty:NTF|\m{clist}\m{true~case}\m{false~case} will check -% whether the \m{clist} is empty and then select one of the other -% arguments. |\clist_if_empty:cTF| turns its first argument into a -% control comma-list to get the name of the comma-list. +% \begin{macro}{\clist_gset_eq:NN} +% \begin{macro}{\clist_gset_eq:cN} +% \begin{macro}{\clist_gset_eq:Nc} +% \begin{macro}{\clist_gset_eq:cc} +% An of course globally which seems to be needed far more often. % \begin{macrocode} -\def_test_function_new:npn {clist_if_empty:N}#1{\if_meaning:NN#1\c_empty_tlp} -\def_new:Npn \clist_if_empty:cTF {\exp_args:Nc\clist_if_empty:NTF} -\def_new:Npn \clist_if_empty:cT {\exp_args:Nc\clist_if_empty:NT} -\def_new:Npn \clist_if_empty:cF {\exp_args:Nc\clist_if_empty:NF} +\cs_new_eq:NN \clist_gset_eq:NN \cs_gset_eq:NN +\cs_new_eq:NN \clist_gset_eq:cN \cs_gset_eq:cN +\cs_new_eq:NN \clist_gset_eq:Nc \cs_gset_eq:Nc +\cs_new_eq:NN \clist_gset_eq:cc \cs_gset_eq:cc % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% +% \subsection{Predicates and conditionals} +% +% \begin{macro}{\clist_if_empty_p:N,\clist_if_empty_p:c} +% \begin{macro}[TF]{\clist_if_empty:N,\clist_if_empty:c} +% \begin{macrocode} +\prg_new_eq_conditional:NNn \clist_if_empty:N \tl_if_empty:N {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_empty:c \tl_if_empty:c {p,TF,T,F} +% \end{macrocode} % \end{macro} % \end{macro} % @@ -552,154 +609,257 @@ % \begin{macro}{\clist_if_empty_err:N} % Signals an error if the comma-list is empty. % \begin{macrocode} -\def_new:Npn \clist_if_empty_err:N #1{ - \if_meaning:NN#1\c_empty_tlp - \tlp_clear:N \l_testa_tlp % catch prefixes - \err_latex_bug:x{Empty~comma-list~`\token_to_string:N#1'} - \fi:} +\cs_new_nopar:Npn \clist_if_empty_err:N #1 { + \if_meaning:w #1 \c_empty_tl + \tl_clear:N \l_testa_tl % catch prefixes + \msg_kernel_bug:x {Empty~comma-list~`\token_to_str:N #1'} + \fi: +} % \end{macrocode} % \end{macro} % -% \begin{macro}{\clist_if_eq:NNTF} -% As comma lists are token list pointers internally this is just an -% alias. +% \begin{macro}{\clist_if_eq_p:NN,\clist_if_eq_p:Nc, +% \clist_if_eq_p:cN,\clist_if_eq_p:cc} +% \begin{macro}[TF]{\clist_if_eq:NN,\clist_if_eq:cN, +% \clist_if_eq:Nc,\clist_if_eq:cc} +% Returns |\c_true| iff the two comma-lists are equal. % \begin{macrocode} -\let_new:NN \clist_if_eq:NNTF \tlp_if_eq:NNTF +\prg_new_eq_conditional:NNn \clist_if_eq:NN \tl_if_eq:NN {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc {p,TF,T,F} % \end{macrocode} -% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[TF]{\clist_if_in:Nn} +% \begin{macro}[TF]{\clist_if_in:NV,\clist_if_in:No,\clist_if_in:cn, +% \clist_if_in:cV,\clist_if_in:co} +% |\clist_if_in:NnTF| \m{clist}\m{item} \m{true~case} \m{false~case} +% will check whether \m{item} is in \m{clist} and then either execute +% the \m{true~case} or the \m{false~case}. \m{true~case} and +% \m{false~case} may contain incomplete |\if_charcode:w| +% statements. +% \begin{macrocode} +\prg_new_conditional:Nnn \clist_if_in:Nn {TF,T,F} { + \cs_set: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 +} +% \end{macrocode} +% \begin{macrocode} +\cs_generate_variant:Nn \clist_if_in:NnTF {NV,No,cn,cV,co} +\cs_generate_variant:Nn \clist_if_in:NnT {NV,No,cn,cV,co} +\cs_generate_variant:Nn \clist_if_in:NnF {NV,No,cn,cV,co} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsection{Retrieving data} +% +% \begin{macro}{\clist_use:N} +% \begin{macro}{\clist_use:c} +% Using a \meta{clist} is just executing it but +% if \m{clist} equals |\scan_stop:| it is probably stemming +% from a |\cs:w ... \cs_end:| that was created by mistake somewhere. +% \begin{macrocode} +\cs_new_nopar:Npn \clist_use:N #1 { + \if_meaning:w #1 \scan_stop: + \msg_kernel_bug:x { + Comma~list~ `\token_to_str:N #1'~ has~ an~ erroneous~ structure!} + \else: + \exp_after:wN #1 + \fi: +} +\cs_generate_variant:Nn \clist_use:N {c} +% \end{macrocode} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_get:NN} % \begin{macro}{\clist_get:cN} -% |\clist_get:NN |\zz{comma-list}\zz{cmd} defines \zz{cmd} to be the -% left-most element of \zz{comma-list}. +% \begin{macro}{\clist_get_aux:w} +% |\clist_get:NN |\meta{comma-list}\meta{cmd} defines \meta{cmd} to be the +% left-most element of \meta{comma-list}. % \begin{macrocode} -\def_new:Npn \clist_get:NN #1{ +\cs_new_nopar:Npn \clist_get:NN #1 { \clist_if_empty_err:N #1 - \exp_after:NN\clist_get_aux:w #1,\q_stop} + \exp_after:wN \clist_get_aux:w #1,\q_stop +} % \end{macrocode} % \begin{macrocode} -\def_new:Npn \clist_get_aux:w #1,#2\q_stop #3{\tlp_set:Nn #3{#1}} +\cs_new:Npn \clist_get_aux:w #1,#2\q_stop #3 { \tl_set:Nn #3{#1} } % \end{macrocode} % \begin{macrocode} -\def_new:Npn \clist_get:cN {\exp_args:Nc \clist_get:NN} +\cs_generate_variant:Nn \clist_get:NN {cN} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\clist_pop_aux:nnNN} % \begin{macro}{\clist_pop_aux:w} % \begin{macro}{\clist_pop_auxi:w} -% |\clist_pop_aux:nnNN| \zz{def$\sb1$} \zz{def$\sb2$} \zz{comma-list} -% \zz{cmd} assigns the left-most element of \zz{comma-list} to -% \zz{cmd} using \zz{def$\sb2$}, and assigns the tail of -% \zz{comma-list} to \zz{comma-list} using \zz{def$\sb1$}. +% |\clist_pop_aux:nnNN| \meta{def$\sb1$} \meta{def$\sb2$} \meta{comma-list} +% \meta{cmd} assigns the left-most element of \meta{comma-list} to +% \meta{cmd} using \meta{def$\sb2$}, and assigns the tail of +% \meta{comma-list} to \meta{comma-list} using \meta{def$\sb1$}. % \begin{macrocode} -\def_new:Npn \clist_pop_aux:nnNN #1#2#3{ +\cs_new:Npn \clist_pop_aux:nnNN #1#2#3 { \clist_if_empty_err:N #3 - \exp_after:NN\clist_pop_aux:w #3,\q_nil\q_stop #1#2#3} + \exp_after:wN \clist_pop_aux:w #3,\q_nil\q_stop #1#2#3 +} % \end{macrocode} +% After the assignmnets below, if there was only one element in the original +% clist, it now contains only |\q_nil|. % \begin{macrocode} -\def_new:Npn \clist_pop_aux:w #1,#2\q_stop #3#4#5#6{ - #4#6{#1} - #3#5{#2} +\cs_new:Npn \clist_pop_aux:w #1,#2\q_stop #3#4#5#6 { + #4 #6 {#1} + #3 #5 {#2} + \quark_if_nil:NTF #5 { #3 #5 {} }{ \clist_pop_auxi:w #2 #3#5 } +} % \end{macrocode} -% If there was only one element in the original clist, it now contains -% only |\q_nil|. % \begin{macrocode} - \quark_if_nil:NTF #5 - { #3#5{} } - { \clist_pop_auxi:w #2 #3#5 } -} +\cs_new:Npn \clist_pop_auxi:w #1,\q_nil #2#3 { #2#3{#1} } % \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\clist_show:N} +% \begin{macro}{\clist_show:c} % \begin{macrocode} -\def_new:Npn\clist_pop_auxi:w #1,\q_nil #2#3 {#2#3{#1}} +\cs_new_eq:NN \clist_show:N \tl_show:N +\cs_new_eq:NN \clist_show:c \tl_show:c % \end{macrocode} % \end{macro} % \end{macro} +% +% \begin{macro}{\clist_display:N} +% \begin{macro}{\clist_display:c} +% \begin{macrocode} +\cs_new_nopar:Npn \clist_display:N #1 { + \iow_term:x { Comma-list~\token_to_str:N #1~contains~ + the~elements~(without~outer~braces): } + \toks_clear:N \l_tmpa_toks + \clist_map_inline:Nn #1 { + \toks_if_empty:NF \l_tmpa_toks { + \toks_put_right:Nx \l_tmpa_toks {^^J>~} + } + \toks_put_right:Nx \l_tmpa_toks { + \iow_space: \iow_char:N \{ \exp_not:n {##1} \iow_char:N \} + } + } + \toks_show:N \l_tmpa_toks +} +\cs_generate_variant:Nn \clist_display:N {c} +% \end{macrocode} +% \end{macro} % \end{macro} % +% \subsection{Storing data} +% % \begin{macro}{\clist_put_aux:NNnnNn} % The generic put function. -% \begin{macrocode} -\def_new:Npn \clist_put_aux:NNnnNn #1#2#3#4#5#6{ -% \end{macrocode} % When adding we have to distinguish between an empty \meta{clist} % and one that contains at least one item (otherwise we accumulate % commas). -% \begin{macrocode} - \clist_if_empty:NTF#5 {#1 #5{#6}} -% \end{macrocode} +% % MH says: Perhaps we should make sure that empty arguments don't get % on the stack as that is probably a mistake. That's what I've -% implemented here. Since |\tlist_if_empty:nF| is expandable prefixes +% implemented here. Since |\tl_if_empty:nF| is expandable prefixes % are still allowed. % \begin{macrocode} - { \tlist_if_empty:nF {#6}{ #2 #5{#3#6#4} } } +\cs_new:Npn \clist_put_aux:NNnnNn #1#2#3#4#5#6 { + \clist_if_empty:NTF #5 { #1 #5 {#6} } { + \tl_if_empty:nF {#6} { #2 #5{#3#6#4} } + } } % \end{macrocode} % \end{macro} +% % \begin{macro}{\clist_put_left:Nn} +% \begin{macro}{\clist_put_left:NV} % \begin{macro}{\clist_put_left:No} % \begin{macro}{\clist_put_left:Nx} % \begin{macro}{\clist_put_left:cn} +% \begin{macro}{\clist_put_left:cV} +% \begin{macro}{\clist_put_left:co} % The operations for adding to the left. % \begin{macrocode} -\def_new:Npn \clist_put_left:Nn { - \clist_put_aux:NNnnNn \tlp_set:Nn \tlp_put_left:Nn {} , +\cs_new_nopar:Npn \clist_put_left:Nn { + \clist_put_aux:NNnnNn \tl_set:Nn \tl_put_left:Nn {} , } -\def_new:Npn \clist_put_left:cn {\exp_args:Nc \clist_put_left:Nn} -\def_new:Npn \clist_put_left:No {\exp_args:NNo\clist_put_left:Nn} -\def_new:Npn \clist_put_left:Nx {\exp_args:Nnx\clist_put_left:Nn} +\cs_generate_variant:Nn \clist_put_left:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}{\clist_gput_left:Nn} +% \begin{macro}{\clist_gput_left:NV} +% \begin{macro}{\clist_gput_left:No} +% \begin{macro}{\clist_gput_left:Nx} +% \begin{macro}{\clist_gput_left:cn} +% \begin{macro}{\clist_gput_left:cV} +% \begin{macro}{\clist_gput_left:co} % Global versions. % \begin{macrocode} -\def_new:Npn \clist_gput_left:Nn { - \clist_put_aux:NNnnNn \tlp_gset:Nn \tlp_gput_left:Nn {} , +\cs_new_nopar:Npn \clist_gput_left:Nn { + \clist_put_aux:NNnnNn \tl_gset:Nn \tl_gput_left:Nn {} , } +\cs_generate_variant:Nn \clist_gput_left:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_put_right:Nn} -% \begin{macro}{\clist_put_right:cn} +% \begin{macro}{\clist_put_right:NV} % \begin{macro}{\clist_put_right:No} % \begin{macro}{\clist_put_right:Nx} +% \begin{macro}{\clist_put_right:cn} +% \begin{macro}{\clist_put_right:cV} +% \begin{macro}{\clist_put_right:co} % Adding something to the right side is almost the same. % \begin{macrocode} -\def_new:Npn \clist_put_right:Nn { - \clist_put_aux:NNnnNn \tlp_set:Nn \tlp_put_right:Nn , {} +\cs_new_nopar:Npn \clist_put_right:Nn { + \clist_put_aux:NNnnNn \tl_set:Nn \tl_put_right:Nn , {} } -\def_new:Npn \clist_put_right:cn {\exp_args:Nc \clist_put_right:Nn} -\def_new:Npn \clist_put_right:No {\exp_args:Nno\clist_put_right:Nn} -\def_new:Npn \clist_put_right:Nx {\exp_args:Nnx\clist_put_right:Nn} +\cs_generate_variant:Nn \clist_put_right:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_gput_right:Nn} +% \begin{macro}{\clist_gput_right:NV} % \begin{macro}{\clist_gput_right:No} +% \begin{macro}{\clist_gput_right:Nx} % \begin{macro}{\clist_gput_right:cn} +% \begin{macro}{\clist_gput_right:cV} % \begin{macro}{\clist_gput_right:co} -% \begin{macro}{\clist_gput_right:cc} -% \begin{macro}{\clist_gput_right:NC} -% An here the global variants. +% And here the global variants. % \begin{macrocode} -\def_new:Npn \clist_gput_right:Nn { - \clist_put_aux:NNnnNn \tlp_gset:Nn \tlp_gput_right:Nn , {} +\cs_new_nopar:Npn \clist_gput_right:Nn { + \clist_put_aux:NNnnNn \tl_gset:Nn \tl_gput_right:Nn , {} } -\def_new:Npn \clist_gput_right:No {\exp_args:NNo \clist_gput_right:Nn} -\def_new:Npn \clist_gput_right:cn {\exp_args:Nc \clist_gput_right:Nn} -\def_new:Npn \clist_gput_right:co {\exp_args:Nco \clist_gput_right:Nn} -\def_new:Npn \clist_gput_right:cc {\exp_args:Ncc \clist_gput_right:Nn} -% \end{macrocode} -% \begin{macrocode} -\def_new:Npn \clist_gput_right:NC {\exp_args:NNC \clist_gput_right:Nn} +\cs_generate_variant:Nn \clist_gput_right:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} % \end{macro} @@ -707,36 +867,42 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% +% +% \subsection{Mapping} % -% \begin{macro}{\clist_map_function:nN} -% \begin{macro}{\clist_map_function:cN} % \begin{macro}{\clist_map_function:NN} -% |\clist_map_function:NN| \zz{comma-list} \zz{cmd} applies \zz{cmd} to each -% element of \zz{comma-list}, from left to right. +% \begin{macro}{\clist_map_function:cN} +% \begin{macro}{\clist_map_function:nN} +% |\clist_map_function:NN| \meta{comma-list} \meta{cmd} applies \meta{cmd} to each +% element of \meta{comma-list}, from left to right. % \begin{macrocode} -\def_new:Npn \clist_map_function:NN #1#2{ - \clist_if_empty:NF #1 - { - \exp_after:NN \clist_map_function_aux:Nw - \exp_after:NN #2 #1 , \q_recursion_tail , \q_recursion_stop +\cs_new_nopar:Npn \clist_map_function:NN #1#2 { + \clist_if_empty:NF #1 { + \exp_after:wN \clist_map_function_aux:Nw + \exp_after:wN #2 #1 , \q_recursion_tail , \q_recursion_stop } } -\def_new:Npn \clist_map_function:cN{\exp_args:Nc\clist_map_function:NN} -\def_new:Npn \clist_map_function:nN #1#2{ - \tlist_if_blank:nF {#1} - { \clist_map_function_aux:Nw #2 #1 , \q_recursion_tail , \q_recursion_stop } +\cs_generate_variant:Nn \clist_map_function:NN {cN} +% \end{macrocode} +% \begin{macrocode} +\cs_new:Npn \clist_map_function:nN #1#2 { + \tl_if_blank:nF {#1} { + \clist_map_function_aux:Nw #2 #1 , \q_recursion_tail , \q_recursion_stop + } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\clist_map_function_aux:Nw} +% \begin{macro}[aux]{\clist_map_function_aux:Nw} % The general loop. Tests if we hit the first stop marker and exits if % we did. If we didn't, place the function "#1" in front of the % element "#2", which is surrounded by braces. % \begin{macrocode} -\def_long_new:Npn \clist_map_function_aux:Nw #1#2,{ +\cs_new:Npn \clist_map_function_aux:Nw #1#2,{ \quark_if_recursion_tail_stop:n{#2} #1{#2} \clist_map_function_aux:Nw #1 @@ -744,11 +910,11 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\clist_map_break:w} +% \begin{macro}{\clist_map_break:} % The break statement is easy. Same as in other modules, gobble % everything up to the special recursion stop marker. % \begin{macrocode} -\let_new:NN \clist_map_break:w \use_none_delimit_by_q_recursion_stop:w +\cs_new_eq:NN \clist_map_break: \use_none_delimit_by_q_recursion_stop:w % \end{macrocode} % \end{macro} % @@ -769,31 +935,28 @@ % every operation globally. % \begin{macrocode} \int_new:N \g_clist_inline_level_int -\def_long_new:Npn \clist_map_inline:Nn #1#2{ - \clist_if_empty:NF #1 - { +\cs_new:Npn \clist_map_inline:Nn #1#2 { + \clist_if_empty:NF #1 { \int_gincr:N \g_clist_inline_level_int - \gdef_long:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} + \cs_gset:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} ##1{#2} % \end{macrocode} -% Recall that the |E| in |\exp_args:NcE| means `single token expanded -% once and no braces added'. It is a lot more efficient to carry over +% It is a lot more efficient to carry over % the special function rather than constructing the same csname over % and over again, so we just do it once. We reuse % |\clist_map_function_aux:Nw| for the actual loop. % \begin{macrocode} - \exp_args:NcE \clist_map_function_aux:Nw + \exp_last_unbraced:NcV \clist_map_function_aux:Nw {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} #1 , \q_recursion_tail , \q_recursion_stop \int_gdecr:N \g_clist_inline_level_int } } -\def_new:Npn \clist_map_inline:cn{\exp_args:Nc\clist_map_inline:Nn} -\def_long_new:Npn \clist_map_inline:nn #1#2{ - \tlist_if_empty:nF {#1} - { +\cs_generate_variant:Nn \clist_map_inline:Nn {c} +\cs_new:Npn \clist_map_inline:nn #1#2 { + \tl_if_empty:nF {#1} { \int_gincr:N \g_clist_inline_level_int - \gdef_long:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} + \cs_gset:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} ##1{#2} \exp_args:Nc \clist_map_function_aux:Nw {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} @@ -810,76 +973,78 @@ % \begin{macro}{\clist_map_variable:nNn} % \begin{macro}{\clist_map_variable:NNn} % \begin{macro}{\clist_map_variable:cNn} -% |\clist_map:NNn| \zz{comma-list} \zz{temp} \zz{action} assigns -% \zz{temp} to each element and executes \zz{action}. +% |\clist_map_variable:NNn| \meta{comma-list} \meta{temp} \meta{action} assigns +% \meta{temp} to each element and executes \meta{action}. % \begin{macrocode} -\def_new:Npn \clist_map_variable:nNn #1#2#3{ - \tlist_if_empty:nF{#1} - { +\cs_new:Npn \clist_map_variable:nNn #1#2#3 { + \tl_if_empty:nF {#1} { \clist_map_variable_aux:Nnw #2 {#3} #1 , \q_recursion_tail , \q_recursion_stop } } -\def_new:Npn \clist_map_variable:NNn {\exp_args:No \clist_map_variable:nNn} -\def_new:Npn \clist_map_variable:cNn {\exp_args:Nc \clist_map_variable:NNn} +% \end{macrocode} +% Something for v/V +% \begin{macrocode} +\cs_new_nopar:Npn \clist_map_variable:NNn {\exp_args:No \clist_map_variable:nNn} +\cs_generate_variant:Nn\clist_map_variable:NNn {cNn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\clist_map_variable_aux:Nnw} +% \begin{macro}[aux]{\clist_map_variable_aux:Nnw} % The general loop. Assign the temp variable |#1| to the current item % |#3| and then check if that's the stop marker. If it is, break the % loop. If not, execute the action |#2| and continue. % \begin{macrocode} -\def_new:Npn \clist_map_variable_aux:Nnw #1#2#3,{ - \def:Npn #1{#3} +\cs_new:Npn \clist_map_variable_aux:Nnw #1#2#3,{ + \cs_set_nopar:Npn #1{#3} \quark_if_recursion_tail_stop:N #1 #2 \clist_map_variable_aux:Nnw #1{#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}{\clist_concat_aux:NNNN} -% \begin{macro}{\clist_concat:NNN} -% \begin{macro}{\clist_gconcat:NNN} -% \begin{macro}{\clist_gconcat:NNc} -% \begin{macro}{\clist_gconcat:ccc} +% \subsection{Higher level functions} +% +% \begin{macro}[aux]{\clist_concat_aux:NNNN} +% \begin{macro}{\clist_concat:NNN,\clist_concat:ccc} +% \begin{macro}{\clist_gconcat:NNN,\clist_gconcat:ccc} % |\clist_gconcat:NNN| \m{clist~1} \m{clist~2} \m{clist~3} will globally % assign \m{clist~1} the concatenation of \m{clist~2} and % \m{clist~3}. +% +% Again the situation is a bit more complicated because of the use +% of commas between items, so if either list is empty we have to avoid +% adding a comma. % \begin{macrocode} -\def_new:Npn \clist_concat_aux:NNNN #1#2#3#4{ +\cs_new_nopar:Npn \clist_concat_aux:NNNN #1#2#3#4 { \toks_set:No \l_tmpa_toks {#3} \toks_set:No \l_tmpb_toks {#4} #1 #2 { \toks_use:N \l_tmpa_toks -% \end{macrocode} -% Again the situation is a bit more complicated because of the use -% of commas between items, so if either list is empty we have to avoid -% adding a comma. -% \begin{macrocode} - \toks_if_empty:NF \l_tmpa_toks {\toks_if_empty:NF \l_tmpb_toks ,} + \toks_if_empty:NF \l_tmpa_toks { \toks_if_empty:NF \l_tmpb_toks , } \toks_use:N \l_tmpb_toks } } -\def_new:Npn \clist_concat:NNN {\clist_concat_aux:NNNN \tlp_set:Nx} -\def_new:Npn \clist_gconcat:NNN {\clist_concat_aux:NNNN \tlp_gset:Nx} +\cs_new_nopar:Npn \clist_concat:NNN { \clist_concat_aux:NNNN \tl_set:Nx } +\cs_new_nopar:Npn \clist_gconcat:NNN { \clist_concat_aux:NNNN \tl_gset:Nx } +\cs_generate_variant:Nn \clist_concat:NNN {ccc} +\cs_generate_variant:Nn \clist_gconcat:NNN {ccc} % \end{macrocode} -% And the usual versions. -% \begin{macrocode} -\def_new:Npn \clist_gconcat:NNc{\exp_args:Nnnc\clist_gconcat:NNN} -\def_new:Npn \clist_gconcat:ccc{\exp_args:Nccc\clist_gconcat:NNN} -% \end{macrocode} -% \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% +% +% \begin{macro}[aux]{\l_clist_remove_clist} +% A common scratch space for the removal routines. +% \begin{macrocode} +\clist_new:N \l_clist_remove_clist +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\clist_remove_duplicates_aux:NN} -% \begin{macro}{\clist_remove_duplicates_aux:n} +% \begin{macro}[aux]{\clist_remove_duplicates_aux:NN} +% \begin{macro}[aux]{\clist_remove_duplicates_aux:n} % \begin{macro}{\clist_remove_duplicates:N} % \begin{macro}{\clist_gremove_duplicates:N} % Removing duplicate entries in a \meta{clist} is fairly straight @@ -887,23 +1052,24 @@ % from left to right. For each element check if the element is % already present in the list. % \begin{macrocode} -\def:Npn \clist_remove_duplicates_aux:NN #1#2 { - \clist_clear:N \l_clist_remove_duplicates_clist +\cs_new:Nn \clist_remove_duplicates_aux:NN { + \clist_clear:N \l_clist_remove_clist \clist_map_function:NN #2 \clist_remove_duplicates_aux:n - #1 #2 \l_clist_remove_duplicates_clist + #1 #2 \l_clist_remove_clist } -\def:Npn \clist_remove_duplicates_aux:n #1 { - \clist_if_in:NnTF \l_clist_remove_duplicates_clist {#1} {} - {\clist_put_right:Nn \l_clist_remove_duplicates_clist {#1}} +\cs_new:Nn \clist_remove_duplicates_aux:n { + \clist_if_in:NnF \l_clist_remove_clist {#1} { + \clist_put_right:Nn \l_clist_remove_clist {#1} + } } % \end{macrocode} % The high level functions are just for telling if it should be a % local or global setting. % \begin{macrocode} -\def_new:Npn \clist_remove_duplicates:N { +\cs_new_nopar:Npn \clist_remove_duplicates:N { \clist_remove_duplicates_aux:NN \clist_set_eq:NN } -\def_new:Npn \clist_gremove_duplicates:N { +\cs_new_nopar:Npn \clist_gremove_duplicates:N { \clist_remove_duplicates_aux:NN \clist_gset_eq:NN } % \end{macrocode} @@ -911,67 +1077,38 @@ % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\l_clist_remove_duplicates_clist} -% \begin{macrocode} -\clist_new:N \l_clist_remove_duplicates_clist -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\clist_use:N} -% \begin{macro}{\clist_use:c} -% Using a \meta{clist} is just executing it but\dots -% \begin{macrocode} -\def_new:Npn \clist_use:N #1 { - \if_meaning:NN #1 \scan_stop: -% \end{macrocode} -% \dots\ if \m{clist} equals |\scan_stop:| it is probably stemming -% from a |\cs:w ... \cs_end:| that was created by mistake somewhere. +% +%\begin{macro}{\clist_remove_element:Nn} +%\begin{macro}{\clist_gremove_element:Nn} +%\begin{macro}[aux]{\clist_remove_element_aux:NNn} +%\begin{macro}[aux]{\clist_remove_element_aux:n} +% The same general idea is used for removing elements: the parent +% functions just set things up for the internal ones. % \begin{macrocode} - \err_latex_bug:x {Comma~list~ `\token_to_string:N #1'~ - has~ an~ erroneous~ structure!} - \else: - \exp_after:NN #1 - \fi: +\cs_new_nopar:Npn \clist_remove_element:Nn { + \clist_remove_element_aux:NNn \clist_set_eq:NN } -\def_new:Npn \clist_use:c {\exp_args:Nc \clist_use:N} -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\clist_if_in:NnTF} -% \begin{macro}{\clist_if_in:NoTF} -% \begin{macro}{\clist_if_in:cnTF} -% \begin{macro}{\clist_if_in:coTF} -% |\clist_if_in:NnTF| \m{clist}\m{item} \m{true~case} \m{false~case} -% will check whether \m{item} is in \m{clist} and then either execute -% the \m{true~case} or the \m{false~case}. \m{true~case} and -% \m{false~case} may contain incomplete |\if_charcode:w| -% statements. -% \begin{macrocode} -\def_new:Npn \clist_if_in:NnTF #1#2{ - \def:Npn \tmp:w ##1 ,#2, ##2##3\q_stop{ - \if_meaning:NN\q_no_value##2 - \exp_after:NN\use_arg_ii:nn - \else: - \exp_after:NN\use_arg_i:nn - \fi: +\cs_new_nopar:Npn \clist_gremove_element:Nn { + \clist_remove_element_aux:NNn \clist_gset_eq:NN +} +\cs_new:Nn \clist_remove_element_aux:NNn { + \clist_clear:N \l_clist_remove_clist + \cs_set:Nn \clist_remove_element_aux:n { + \tl_if_eq:nnF {#3} {##1} { + \clist_put_right:Nn \l_clist_remove_clist {##1} + } } - \exp_after:NN \tmp:w - \exp_after:NN , #1, #2, \q_no_value \q_stop + \clist_map_function:NN #2 \clist_remove_element_aux:n + #1 #2 \l_clist_remove_clist } -\def_new:Npn \clist_if_in:NoTF {\exp_args:NNo \clist_if_in:NnTF} -\def_new:Npn \clist_if_in:coTF {\exp_args:Nco \clist_if_in:NnTF} -\def_new:Npn \clist_if_in:cnTF {\exp_args:Nc \clist_if_in:NnTF} +\cs_new:Nn \clist_remove_element_aux:n { } % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} % -% -% \subsubsection{Stack operations} +% \subsection{Stack operations} % % We build stacks from comma-lists, but here we put the % specific functions together. @@ -979,6 +1116,7 @@ % % \begin{macro}{\clist_push:Nn} % \begin{macro}{\clist_push:No} +% \begin{macro}{\clist_push:NV} % \begin{macro}{\clist_push:cn} % \begin{macro}{\clist_pop:NN} % \begin{macro}{\clist_pop:cN} @@ -986,22 +1124,25 @@ % `push' and `pop'. In most cases they are nothing more then new % names for old functions. % \begin{macrocode} -\let_new:NN \clist_push:Nn \clist_put_left:Nn -\let_new:NN \clist_push:No \clist_put_left:No -\let_new:NN \clist_push:cn \clist_put_left:cn -\def_new:Npn \clist_pop:NN {\clist_pop_aux:nnNN \tlp_set:Nn \tlp_set:Nn} -\def_new:Npn \clist_pop:cN {\exp_args:Nc \clist_pop:NN} +\cs_new_eq:NN \clist_push:Nn \clist_put_left:Nn +\cs_new_eq:NN \clist_push:NV \clist_put_left:NV +\cs_new_eq:NN \clist_push:No \clist_put_left:No +\cs_new_eq:NN \clist_push:cn \clist_put_left:cn +\cs_new_nopar:Npn \clist_pop:NN {\clist_pop_aux:nnNN \tl_set:Nn \tl_set:Nn} +\cs_generate_variant:Nn \clist_pop:NN {cN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % % % \begin{macro}{\clist_gpush:Nn} % \begin{macro}{\clist_gpush:No} +% \begin{macro}{\clist_gpush:NV} % \begin{macro}{\clist_gpush:cn} % \begin{macro}{\clist_gpop:NN} % \begin{macro}{\clist_gpop:cN} @@ -1010,12 +1151,17 @@ % here more often. In case of |\clist_gpop:NN| the value is % nevertheless returned locally. % \begin{macrocode} -\let_new:NN \clist_gpush:Nn \clist_gput_left:Nn -\def_new:Npn \clist_gpush:No {\exp_args:NNo \clist_gpush:Nn} -\def_new:Npn \clist_gpush:cn {\exp_args:Nc \clist_gpush:Nn} -\def_new:Npn \clist_gpop:NN {\clist_pop_aux:nnNN \tlp_gset:Nn \tlp_set:Nn} -\def_new:Npn \clist_gpop:cN {\exp_args:Nc \clist_gpop:NN} +\cs_new_eq:NN \clist_gpush:Nn \clist_gput_left:Nn +\cs_new_eq:NN \clist_gpush:NV \clist_gput_left:NV +\cs_new_eq:NN \clist_gpush:No \clist_gput_left:No +\cs_generate_variant:Nn \clist_gpush:Nn {cn} % \end{macrocode} +% +% \begin{macrocode} +\cs_new_nopar:Npn \clist_gpop:NN {\clist_pop_aux:nnNN \tl_gset:Nn \tl_set:Nn} +\cs_generate_variant:Nn \clist_gpop:NN {cN} +% \end{macrocode} +% \end{macro} % \end{macro} % \end{macro} % \end{macro} @@ -1028,58 +1174,26 @@ % Looking at the top element of the stack without removing it is % done with this operation. % \begin{macrocode} -\let_new:NN \clist_top:NN \clist_get:NN -\let_new:NN \clist_top:cN \clist_get:cN +\cs_new_eq:NN \clist_top:NN \clist_get:NN +\cs_new_eq:NN \clist_top:cN \clist_get:cN % \end{macrocode} % \end{macro} % \end{macro} % -% -% Show token usage: % \begin{macrocode} %</initex|package> +% \end{macrocode} +% +% Show token usage: +% \begin{macrocode} %<*showmemory> %\showMemUsage %</showmemory> % \end{macrocode} % +% \end{implementation} +% \PrintIndex % % -% \endinput -% -% $Log$ -% Revision 1.16 2006/07/30 15:45:46 morten -% Made \clist_map_inline:Nn and variants nestable plus a little cleanup. -% -% Revision 1.15 2006/03/20 18:26:34 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.14 2006/01/04 01:32:09 morten -% Minor changes to code to reflect changes in l3tlp. -% -% Revision 1.13 2005/12/27 09:52:51 morten -% Minor changes plus changed RCS information retrieval -% -% Revision 1.12 2005/10/27 23:14:49 morten -% Improved loops. -% -% Revision 1.11 2005/04/12 16:45:22 morten -% Enabled put operations. Added function that removes duplicate entries (mostly for -% use after concatenating to clists) -% -% Revision 1.10 2005/04/12 13:22:13 morten -% Mostly cosmetic changes. \clist_gconcat:NNN reprogrammed using "proper" methods, \clist_put_right:Nn likewise. -% -% Revision 1.9 2005/03/22 23:26:54 morten -% Fix error message -% -% Revision 1.8 2005/03/16 22:36:43 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.7 2005/03/11 21:36:36 braams -% Fixed the use of RCS information; -% Fixed a few documentation typos; added \StopEventually -% Replaced \ifx by \if_meaning:NN, \c_if_empty_toks became \c_empty_toks -% but needs further work according to Morten % +% \endinput |