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/l3tl.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/l3tl.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3tl.dtx | 1450 |
1 files changed, 672 insertions, 778 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index 51fcddc242e..08d2630523d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -35,8 +35,8 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3tl.dtx 3490 2012-03-04 01:00:53Z bruno $ - {L3 Experimental token lists} +\GetIdInfo$Id: l3tl.dtx 3986 2012-07-15 19:23:51Z joseph $ + {L3 Token lists} %</driver|package> %<*driver> \documentclass[full]{l3doc} @@ -148,10 +148,23 @@ % \tl_gset_eq:NN, \tl_gset_eq:cN, \tl_gset_eq:Nc, \tl_gset_eq:cc % } % \begin{syntax} -% \cs{tl_set_eq:NN} \meta{tl~var1} \meta{tl~var2} +% \cs{tl_set_eq:NN} \meta{tl~var_1} \meta{tl~var_2} % \end{syntax} -% Sets the content of \meta{tl~var1} equal to that of -% \meta{tl~var2}. +% Sets the content of \meta{tl~var_1} equal to that of +% \meta{tl~var_2}. +% \end{function} +% +% \begin{function}[added = 2012-05-18] +% { +% \tl_concat:NNN, \tl_concat:ccc, +% \tl_gconcat:NNN, \tl_gconcat:ccc +% } +% \begin{syntax} +% \cs{tl_concat:NNN} \meta{tl~var_1} \meta{tl~var_2} \meta{tl~var_3} +% \end{syntax} +% Concatenates the content of \meta{tl~var_2} and \meta{tl~var_3} +% together and saves the result in \meta{tl~var_1}. The \meta{tl~var_2} +% will be placed at the left side of the new token list. % \end{function} % % \begin{function}[EXP, pTF, added=2012-03-03]{\tl_if_exist:N, \tl_if_exist:c} @@ -363,23 +376,21 @@ % (\emph{i.e.}~contains no tokens at all). % \end{function} % -% \begin{function}[EXP,pTF] -% {\tl_if_empty:n, \tl_if_empty:V, \tl_if_empty:o, \tl_if_empty:x} +% \begin{function}[added = 2012-05-24, updated = 2012-06-05, EXP,pTF] +% {\tl_if_empty:n, \tl_if_empty:V, \tl_if_empty:o} % \begin{syntax} % \cs{tl_if_empty_p:n} \Arg{token list} % \cs{tl_if_empty:nTF} \Arg{token list} \Arg{true code} \Arg{false code} % \end{syntax} % Tests if the \meta{token list} is entirely empty % (\emph{i.e.}~contains no tokens at all). -% All versions of these functions are fully expandable -% (including those involving an \texttt{x}-type expansion). % \end{function} % % \begin{function}[EXP,pTF] % {\tl_if_eq:NN, \tl_if_eq:Nc, \tl_if_eq:cN, \tl_if_eq:cc} % \begin{syntax} -% \cs{tl_if_eq_p:NN} \Arg{tl var1} \Arg{tl var2} -% \cs{tl_if_eq:NNTF} \Arg{tl var1} \Arg{tl var2} \Arg{true code} \Arg{false code} +% \cs{tl_if_eq_p:NN} \Arg{tl var_1} \Arg{tl var_2} +% \cs{tl_if_eq:NNTF} \Arg{tl var_1} \Arg{tl var_2} \Arg{true code} \Arg{false code} % \end{syntax} % Compares the content of two \meta{token list variables} and % is logically \texttt{true} if the two contain the same list of @@ -395,9 +406,9 @@ % % \begin{function}[TF]{\tl_if_eq:nn} % \begin{syntax} -% \cs{tl_if_eq:nnTF} \meta{token list1} \Arg{token list2} \Arg{true code} \Arg{false code} +% \cs{tl_if_eq:nnTF} \meta{token list_1} \Arg{token list_2} \Arg{true code} \Arg{false code} % \end{syntax} -% Tests if \meta{token list1} and \meta{token list2} are equal, both in +% Tests if \meta{token list_1} and \meta{token list_2} are equal, both in % respect of character codes and category codes. % \end{function} % @@ -414,9 +425,9 @@ % \begin{function}[TF] % {\tl_if_in:nn, \tl_if_in:Vn, \tl_if_in:on, \tl_if_in:no} % \begin{syntax} -% \cs{tl_if_in:nnTF} \Arg{token list1} \Arg{token list2} \Arg{true code} \Arg{false code} +% \cs{tl_if_in:nnTF} \Arg{token list_1} \Arg{token list_2} \Arg{true code} \Arg{false code} % \end{syntax} -% Tests if <token list2> is found inside <token list1>. +% Tests if <token list_2> is found inside <token list_1>. % The \meta{token list} cannot contain the tokens |{|, |}| or |#| % (assuming the usual \TeX{} category codes apply). % \end{function} @@ -430,8 +441,8 @@ % Tests if the content of the \meta{tl~var} consists of a single item, % \emph{i.e.}~is either a single normal token (excluding spaces, % and brace tokens) or a single brace group, surrounded by optional -% spaces on both sides. In other words, such a token list has length -% $1$ according to \cs{tl_length:N}. +% spaces on both sides. In other words, such a token list has token count +% $1$ according to \cs{tl_count:N}. % \end{function} % % \begin{function}[updated = 2011-08-13, EXP,pTF]{\tl_if_single:n} @@ -442,22 +453,33 @@ % Tests if the token list has exactly one item, \emph{i.e.}~is either % a single normal token or a single brace group, surrounded by % optional spaces on both sides. In other words, such a token list -% has length $1$ according to \cs{tl_length:n}. +% has token count $1$ according to \cs{tl_count:n}. % \end{function} % -% \begin{function}[added = 2011-08-11,EXP,pTF]{\tl_if_single_token:n} +% \begin{function}[added = 2012-06-03, EXP]{\tl_case:Nnn, \tl_case:cnn} % \begin{syntax} -% \cs{tl_if_single_token_p:n} \Arg{token list} -% \cs{tl_if_single_token:nTF} \Arg{token list} \Arg{true code} \Arg{false code} +% \cs{tl_case:Nnn} \meta{test token list variable} \\ +% ~~"{" \\ +% ~~~~\meta{token list variable case_1} \Arg{code case_1} \\ +% ~~~~\meta{token list variable case_2} \Arg{code case_2} \\ +% ~~~~\ldots \\ +% ~~~~\meta{token list variable case_n} \Arg{code case_n} \\ +% ~~"}" \\ +% ~~\Arg{else code} % \end{syntax} -% Tests if the token list consists of exactly one token, \emph{i.e.}~is -% either a single space character or a single \enquote{normal} token. -% Token groups (|{|\ldots|}|) are not single tokens. +% This function compares the \meta{test token list variable} in turn +% with each of the \meta{token list variable cases}. If the two +% are equal (as described for +% \cs{tl_if_eq:nnTF} +% then the associated \meta{code} is left in the input +% stream. If none of the tests are \texttt{true} then the +% \texttt{else code} will be left in the input stream. % \end{function} % % \section{Mapping to token lists} % -% \begin{function}[rEXP]{\tl_map_function:NN, \tl_map_function:cN} +% \begin{function}[updated = 2012-06-29, rEXP] +% {\tl_map_function:NN, \tl_map_function:cN} % \begin{syntax} % \cs{tl_map_function:NN} \meta{tl~var} \meta{function} % \end{syntax} @@ -468,7 +490,7 @@ % \texttt{n}-type arguments. See also \cs{tl_map_function:nN}. % \end{function} % -% \begin{function}[rEXP]{\tl_map_function:nN} +% \begin{function}[updated = 2012-06-29, rEXP]{\tl_map_function:nN} % \begin{syntax} % \cs{tl_map_function:nN} \meta{token list} \meta{function} % \end{syntax} @@ -479,7 +501,8 @@ % \texttt{n}-type arguments. See also \cs{tl_map_function:NN}. % \end{function} % -% \begin{function}{\tl_map_inline:Nn, \tl_map_inline:cn} +% \begin{function}[updated = 2012-06-29] +% {\tl_map_inline:Nn, \tl_map_inline:cn} % \begin{syntax} % \cs{tl_map_inline:Nn} \meta{tl~var} \Arg{inline function} % \end{syntax} @@ -489,7 +512,7 @@ % inside another. See also \cs{tl_map_function:Nn}. % \end{function} % -% \begin{function}{\tl_map_inline:nn} +% \begin{function}[updated = 2012-06-29]{\tl_map_inline:nn} % \begin{syntax} % \cs{tl_map_inline:nn} \meta{token list} \Arg{inline function} % \end{syntax} @@ -499,7 +522,8 @@ % inside another. See also \cs{tl_map_function:nn}. % \end{function} % -% \begin{function}{\tl_map_variable:NNn, \tl_map_variable:cNn} +% \begin{function}[updated = 2012-06-29] +% {\tl_map_variable:NNn, \tl_map_variable:cNn} % \begin{syntax} % \cs{tl_map_variable:NNn} \meta{tl~var} \meta{variable} \Arg{function} % \end{syntax} @@ -510,7 +534,7 @@ % \cs{tl_map_inline:Nn}. % \end{function} % -% \begin{function}{\tl_map_variable:nNn} +% \begin{function}[updated = 2012-06-29]{\tl_map_variable:nNn} % \begin{syntax} % \cs{tl_map_variable:nNn} \meta{token list} \meta{variable} \Arg{function} % \end{syntax} @@ -521,7 +545,7 @@ % \cs{tl_map_inline:nn}. % \end{function} % -% \begin{function}[rEXP]{\tl_map_break:} +% \begin{function}[updated = 2012-06-29, rEXP]{\tl_map_break:} % \begin{syntax} % \cs{tl_map_break:} % \end{syntax} @@ -540,6 +564,40 @@ % \end{verbatim} % Use outside of a \cs{tl_map_\ldots} scenario will lead low % level \TeX{} errors. +% \begin{texnote} +% When the mapping is broken, additional tokens may be inserted by the +% 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}[updated = 2012-06-29, rEXP]{\tl_map_break:n} +% \begin{syntax} +% \cs{tl_map_break:n} \Arg{tokens} +% \end{syntax} +% Used to terminate a \cs{tl_map_\ldots} function before all +% entries in the \meta{token list variable} have been processed, inserting +% the \meta{tokens} after the mapping has ended. This will +% normally take place within a conditional statement, for example +% \begin{verbatim} +% \tl_map_inline:Nn \l_my_tl +% { +% \str_if_eq:nnTF { #1 } { bingo } +% { \tl_map_break:n { <tokens> } } +% { +% % Do something useful +% } +% } +% \end{verbatim} +% Use outside of a \cs{tl_map_\ldots} scenario will lead to low +% level \TeX{} errors. +% \begin{texnote} +% When the mapping is broken, additional tokens may be inserted by the +% 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} % % \section{Using token lists} @@ -564,7 +622,8 @@ % in the input stream. Note that this function requires only a single % expansion. % \begin{texnote} -% This is the \eTeX{} primitive \tn{detokenize}. +% This is the \eTeX{} primitive \tn{detokenize}. Hence its argument +% \emph{must} be given within braces. % \end{texnote} % \end{function} % @@ -580,28 +639,28 @@ % % \section{Working with the content of token lists} % -% \begin{function}[updated = 2011-08-13, EXP] -% {\tl_length:n, \tl_length:V, \tl_length:o} +% \begin{function}[added = 2012-05-13, EXP] +% {\tl_count:n, \tl_count:V, \tl_count:o} % \begin{syntax} -% \cs{tl_length:n} \Arg{tokens} +% \cs{tl_count:n} \Arg{tokens} % \end{syntax} % Counts the number of \meta{items} in \meta{tokens} and leaves this % information in the input stream. Unbraced tokens count as one % element as do each token group (|{|\ldots|}|). This process will % ignore any unprotected spaces within \meta{tokens}. See also -% \cs{tl_length:N}. This function requires three expansions, +% \cs{tl_count:N}. This function requires three expansions, % giving an \meta{integer denotation}. % \end{function} % -% \begin{function}[updated = 2011-08-13, EXP]{\tl_length:N, \tl_length:c} +% \begin{function}[added = 2012-05-13, EXP]{\tl_count:N, \tl_count:c} % \begin{syntax} -% \cs{tl_length:N} \Arg{tl~var} +% \cs{tl_count:N} \Arg{tl~var} % \end{syntax} % Counts the number of token groups in the \meta{tl~var} % and leaves this information in the input stream. Unbraced tokens % count as one element as do each token group (|{|\ldots|}|). This % process will ignore any unprotected spaces within \meta{tokens}. -% See also \cs{tl_length:n}. This function requires three expansions, +% See also \cs{tl_count:n}. This function requires three expansions, % giving an \meta{integer denotation}. % \end{function} % @@ -611,8 +670,8 @@ % \cs{tl_reverse:n} \Arg{token list} % \end{syntax} % Reverses the order of the \meta{items} in the \meta{token list}, -% so that \meta{item1}\meta{item2}\meta{item3} \ldots \meta{item$_n$} -% becomes \meta{item$_n$}\ldots \meta{item3}\meta{item2}\meta{item1}. +% so that \meta{item_1}\meta{item_2}\meta{item_3} \ldots \meta{item_n} +% becomes \meta{item_n}\ldots \meta{item_3}\meta{item_2}\meta{item_1}. % This process will preserve unprotected space within the % \meta{token list}. Tokens are not reversed within braced token % groups, which keep their outer set of braces. @@ -633,8 +692,8 @@ % \cs{tl_reverse:N} \Arg{tl~var} % \end{syntax} % Reverses the order of the \meta{items} stored in \meta{tl~var}, so -% that \meta{item1}\meta{item2}\meta{item3} \ldots \meta{item$_n$} -% becomes \meta{item$_n$}\ldots \meta{item3}\meta{item2}\meta{item1}. +% that \meta{item_1}\meta{item_2}\meta{item_3} \ldots \meta{item_n} +% becomes \meta{item_n}\ldots \meta{item_3}\meta{item_2}\meta{item_1}. % This process will preserve unprotected spaces within the % \meta{token list variable}. Braced token groups are copied without % reversing the order of tokens, but keep the outer set of braces. @@ -646,8 +705,8 @@ % \cs{tl_reverse_items:n} \Arg{token list} % \end{syntax} % Reverses the order of the \meta{items} stored in \meta{tl~var}, -% so that \Arg{item_1}\Arg{item_2}\Arg{item_3} \ldots \Arg{item$_n$} -% becomes \Arg{item$_n$} \ldots{} \Arg{item_3}\Arg{item_2}\Arg{item_1}. +% so that \Arg{item_1}\Arg{item_2}\Arg{item_3} \ldots \Arg{item_n} +% becomes \Arg{item_n} \ldots{} \Arg{item_3}\Arg{item_2}\Arg{item_1}. % This process will remove any unprotected space within the % \meta{token list}. Braced token groups are copied without % reversing the order of tokens, and keep the outer set of braces. @@ -662,14 +721,14 @@ % \end{texnote} % \end{function} % -% \begin{function}[added = 2011-07-09, updated = 2011-08-13, EXP] +% \begin{function}[added = 2011-07-09, updated = 2012-06-25, EXP] % {\tl_trim_spaces:n} % \begin{syntax} % \cs{tl_trim_spaces:n} \meta{token list} % \end{syntax} % Removes any leading and trailing explicit space characters % from the \meta{token list} and leaves the result in the input -% stream. This process requires two expansions. +% stream. % \begin{texnote} % The result is returned within the \tn{unexpanded} % primitive (\cs{exp_not:n}), which means that the token @@ -793,78 +852,75 @@ % nothing is left in the input stream. % \end{function} % -% \begin{function}[updated = 2011-08-10, EXP,pTF]{\tl_if_head_eq_catcode:nN} +% \begin{function}[updated = 2012-07-09, EXP, pTF]{\tl_if_head_eq_catcode:nN} % \begin{syntax} % \cs{tl_if_head_eq_catcode_p:nN} \Arg{token list} \meta{test token} % \cs{tl_if_head_eq_catcode:nNTF} \Arg{token list} \meta{test token} % ~~\Arg{true code} \Arg{false code} % \end{syntax} -% Tests if the first \meta{token} in the \meta{token list} has the same -% category code as the \meta{test token}. In the case where -% \meta{token list} is empty, its head is considered to be \cs{q_nil}, -% and the test will be true if \meta{test token} is a control sequence. +% Tests if the first \meta{token} in the \meta{token list} has the +% same category code as the \meta{test token}. In the case where the +% \meta{token list} is empty, the test will always be \texttt{false}. % \end{function} % -% \begin{function}[updated = 2011-08-10, EXP,pTF] +% \begin{function}[updated = 2012-07-09, EXP, pTF] % {\tl_if_head_eq_charcode:nN, \tl_if_head_eq_charcode:fN} % \begin{syntax} % \cs{tl_if_head_eq_charcode_p:nN} \Arg{token list} \meta{test token} % \cs{tl_if_head_eq_charcode:nNTF} \Arg{token list} \meta{test token} % ~~\Arg{true code} \Arg{false code} % \end{syntax} -% Tests if the first \meta{token} in the \meta{token list} has the same -% character code as the \meta{test token}. In the case where -% \meta{token list} is empty, its head is considered to be \cs{q_nil}, -% and the test will be true if \meta{test token} is a control sequence. +% Tests if the first \meta{token} in the \meta{token list} has the +% same character code as the \meta{test token}. In the case where the +% \meta{token list} is empty, the test will always be \texttt{false}. % \end{function} % -% \begin{function}[updated = 2011-08-10, EXP,pTF]{\tl_if_head_eq_meaning:nN} +% \begin{function}[updated = 2012-07-09, EXP, pTF]{\tl_if_head_eq_meaning:nN} % \begin{syntax} % \cs{tl_if_head_eq_meaning_p:nN} \Arg{token list} \meta{test token} % \cs{tl_if_head_eq_meaning:nNTF} \Arg{token list} \meta{test token} % ~~\Arg{true code} \Arg{false code} % \end{syntax} -% Tests if the first \meta{token} in the \meta{token list} has the same -% meaning as the \meta{test token}. In the case where \meta{token list} -% is empty, its head is considered to be \cs{q_nil}, and the test will -% be true if \meta{test token} has the same meaning as \cs{q_nil}. +% Tests if the first \meta{token} in the \meta{token list} has the +% same meaning as the \meta{test token}. In the case where +% \meta{token list} is empty, the test will always be \texttt{false}. % \end{function} % -% \begin{function}[updated = 2011-08-11, EXP,pTF]{\tl_if_head_group:n} +% \begin{function}[added = 2012-07-08, EXP, pTF]{\tl_if_head_is_group:n} % \begin{syntax} -% \cs{tl_if_head_group_p:n} \Arg{token list} -% \cs{tl_if_head_group:nTF} \Arg{token list} \Arg{true code} \Arg{false code} +% \cs{tl_if_head_is_group_p:n} \Arg{token list} +% \cs{tl_if_head_is_group:nTF} \Arg{token list} \Arg{true code} \Arg{false code} % \end{syntax} % Tests if the first \meta{token} in the \meta{token list} % is an explicit begin-group character (with category code~1 % and any character code), in other words, if the \meta{token list} -% starts with a brace group. In particular, the test is false +% starts with a brace group. In particular, the test is \texttt{false} % if the \meta{token list} starts with an implicit token such as % \cs{c_group_begin_token}, or if it empty. % This function is useful to implement actions on token lists on % a token by token basis. % \end{function} % -% \begin{function}[added = 2011-08-11,EXP,pTF]{\tl_if_head_N_type:n} +% \begin{function}[added = 2012-07-08, EXP, pTF]{\tl_if_head_is_N_type:n} % \begin{syntax} -% \cs{tl_if_head_N_type_p:n} \Arg{token list} -% \cs{tl_if_head_N_type:nTF} \Arg{token list} \Arg{true code} \Arg{false code} +% \cs{tl_if_head_is_N_type_p:n} \Arg{token list} +% \cs{tl_if_head_is_N_type:nTF} \Arg{token list} \Arg{true code} \Arg{false code} % \end{syntax} % Tests if the first \meta{token} in the \meta{token list} % is a normal \texttt{N}-type argument. In other words, % it is neither an explicit space character (with category code~10 % and character code~32) nor an explicit begin-group character % (with category code~1 and any character code). An empty -% argument yields false, as it does not have a \enquote{normal} +% argument yields \texttt{false}, as it does not have a \enquote{normal} % first token. % This function is useful to implement actions on token lists on % a token by token basis. % \end{function} % -% \begin{function}[updated = 2011-08-11,EXP,pTF]{\tl_if_head_space:n} +% \begin{function}[updated = 2012-07-08, EXP, pTF]{\tl_if_head_is_space:n} % \begin{syntax} -% \cs{tl_if_head_space_p:n} \Arg{token list} -% \cs{tl_if_head_space:nTF} \Arg{token list} \Arg{true code} \Arg{false code} +% \cs{tl_if_head_is_space_p:n} \Arg{token list} +% \cs{tl_if_head_is_space:nTF} \Arg{token list} \Arg{true code} \Arg{false code} % \end{syntax} %^^A We need to add a discussion of %^^A explicit vs implicit tokens somewhere in the doc. @@ -872,7 +928,7 @@ % is an explicit space character (with category code~$10$ % and character code~$32$). If \meta{token list} starts with % an implicit token such as \cs{c_space_token}, the test -% will yield false, as well as if the argument is empty. +% will yield \texttt{false}, as well as if the argument is empty. % This function is useful to implement actions on token lists on % a token by token basis. % \begin{texnote} @@ -942,89 +998,22 @@ % code and so should only be used for short-term storage. % \end{variable} % -% \section{Experimental token list functions} -% -% \begin{function}[added = 2012-01-08, EXP]{\tl_reverse_tokens:n} -% \begin{syntax} -% \cs{tl_reverse_tokens:n} \Arg{tokens} -% \end{syntax} -% This function, which works directly on \TeX{} tokens, reverses -% the order of the \meta{tokens}: the first will be the last and -% the last will become first. Spaces are preserved. The reversal -% also operates within brace groups, but the braces themselves -% are not exchanged, as this would lead to an unbalanced token -% list. For instance, \cs{tl_reverse_tokens:n} |{a~{b()}}| -% leaves |{)(b}~a| in the input stream. This function requires -% two steps of expansion. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the token -% list will not expand further when appearing in an x-type -% argument expansion. -% \end{texnote} -% \end{function} -% -% \begin{function}[added = 2011-08-11, EXP]{\tl_length_tokens:n} -% \begin{syntax} -% \cs{tl_length_tokens:n} \Arg{tokens} -% \end{syntax} -% Counts the number of \TeX{} tokens in the \meta{tokens} and leaves -% this information in the input stream. Every token, including spaces and -% braces, contributes one to the total; thus for instance, the length of -% |a~{bc}| is $6$. -% This function requires three expansions, -% giving an \meta{integer denotation}. -% \end{function} -% -% \begin{function}[added = 2012-01-08, EXP] -% {\tl_expandable_uppercase:n,\tl_expandable_lowercase:n} -% \begin{syntax} -% \cs{tl_expandable_uppercase:n} \Arg{tokens} -% \cs{tl_expandable_lowercase:n} \Arg{tokens} -% \end{syntax} -% The \cs{tl_expandable_uppercase:n} function works through all of -% the \meta{tokens}, replacing characters in the range |a|--|z| -% (with arbitrary category code) by the corresponding letter -% in the range |A|--|Z|, with category code $11$ (letter). Similarly, -% \cs{tl_expandable_lowercase:n} replaces characters in the range -% |A|--|Z| by letters in the range |a|--|z|, and leaves other tokens -% unchanged. This function requires two steps of expansion. -% \begin{texnote} -% Begin-group and end-group characters are normalized and become -% |{| and |}|, respectively. -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the token -% list will not expand further when appearing in an x-type -% argument expansion. -% \end{texnote} -% \end{function} +% \section{Internal functions} % -% \begin{function}[added = 2011-11-21, updated = 2012-01-08, EXP] -% {\tl_item:nn, \tl_item:Nn, \tl_item:cn} +% \begin{function}{\__tl_trim_spaces:nn} % \begin{syntax} -% \cs{tl_item:nn} \Arg{token list} \Arg{integer expression} +% \cs{__tl_trim_spaces:nn} |{ \q_mark| \meta{token list} |}| \Arg{continuation} % \end{syntax} -% Indexing items in the \meta{token list} from $0$ on the left, this -% function will evaluate the \meta{integer expression} and leave the -% appropriate item from the \meta{token list} in the input stream. -% If the \meta{integer expression} is negative, indexing occurs from -% the right of the token list, starting at $-1$ for the right-most item. -% If the index is out of bounds, then thr function expands 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} +% This function removes all leading and trailing explicit space +% characters from the \meta{token list}, and expands to the +% \meta{continuation}, followed by a brace group containing +% \cs{use_none:n} \cs{q_mark} \meta{trimmed token list}. For +% instance, \cs{tl_trim_spaces:n} is implemented by taking the +% \meta{continuation} to be \cs{exp_not:o}, and the \texttt{o}-type +% expansion removes the \cs{q_mark}. This function is also used in +% \pkg{l3clist}. % \end{function} % -% \section{Internal functions} -% -% \begin{variable}{\q_tl_act_mark,\q_tl_act_stop} -% Quarks which are only used for the particular purposes of -% \cs{tl_act_...} functions. -% \end{variable} -% % \end{documentation} % % \begin{implementation} @@ -1036,10 +1025,14 @@ % \end{macrocode} % % \begin{macrocode} +%<@@=tl> +% \end{macrocode} +% +% \begin{macrocode} %<*package> \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} -\package_check_loaded_expl: +\__expl_package_check: %</package> % \end{macrocode} % @@ -1055,7 +1048,7 @@ % \begin{macrocode} \cs_new_protected:Npn \tl_new:N #1 { - \chk_if_free_cs:N #1 + \__chk_if_free_cs:N #1 \cs_gset_eq:NN #1 \c_empty_tl } \cs_generate_variant:Nn \tl_new:N { c } @@ -1067,12 +1060,12 @@ % \begin{macrocode} \cs_new_protected:Npn \tl_const:Nn #1#2 { - \chk_if_free_cs:N #1 + \__chk_if_free_cs:N #1 \cs_gset_nopar:Npx #1 { \exp_not:n {#2} } } \cs_new_protected:Npn \tl_const:Nx #1#2 { - \chk_if_free_cs:N #1 + \__chk_if_free_cs:N #1 \cs_gset_nopar:Npx #1 {#2} } \cs_generate_variant:Nn \tl_const:Nn { c } @@ -1134,6 +1127,20 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\tl_concat:NNN, \tl_concat:ccc} +% \begin{macro}{\tl_gconcat:NNN, \tl_gconcat:ccc} +% Concatenating token lists is easy. +% \begin{macrocode} +\cs_new_protected:Npn \tl_concat:NNN #1#2#3 + { \tl_set:Nx #1 { \exp_not:o {#2} \exp_not:o {#3} } } +\cs_new_protected:Npn \tl_gconcat:NNN #1#2#3 + { \tl_gset:Nx #1 { \exp_not:o {#2} \exp_not:o {#3} } } +\cs_generate_variant:Nn \tl_concat:NNN { ccc } +\cs_generate_variant:Nn \tl_gconcat:NNN { ccc } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}[pTF]{\tl_if_exist:N, \tl_if_exist:c} % Copies of the \texttt{cs} functions defined in \pkg{l3basics}. % \begin{macrocode} @@ -1148,6 +1155,37 @@ % \end{macrocode} % \end{macro} % +% \subsection{Constant token lists} +% +% \begin{variable}{\c_job_name_tl} +% Inherited from the \LaTeX3 name for the primitive: this needs to +% actually contain the text of the job name rather than the name of +% the primitive, of course. \LuaTeX{} does not quote file names containing +% spaces, whereas \pdfTeX{} and \XeTeX{} do. So there may be a correction to +% make in the \LuaTeX{} case. +% \begin{macrocode} +%<*initex> +\tex_everyjob:D \exp_after:wN + { + \tex_the:D \tex_everyjob:D + \luatex_if_engine:T + { + \lua_now:x + { dofile ( assert ( kpse.find_file ("lualatexquotejobname.lua" ) ) ) } + } + } +%</initex> +\tl_const:Nx \c_job_name_tl { \tex_jobname:D } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\c_space_tl} +% A space as a token list (as opposed to as a character). +% \begin{macrocode} +\tl_const:Nn \c_space_tl { ~ } +% \end{macrocode} +% \end{variable} +% % \subsection{Adding to token list variables} % % \begin{macro} @@ -1273,7 +1311,7 @@ % % \subsection{Reassigning token list category codes} % -% \begin{variable}{\c_tl_rescan_marker_tl} +% \begin{variable}{\c_@@_rescan_marker_tl} % The rescanning code needs a special token list containing the same % character with two different category codes. This is set up here, % while the detail is described below. @@ -1286,7 +1324,7 @@ \tex_lowercase:D { \group_end: - \tl_const:Nn \c_tl_rescan_marker_tl { A B } + \tl_const:Nn \c_@@_rescan_marker_tl { A B } } % \end{macrocode} % \end{variable} @@ -1302,8 +1340,8 @@ % \tl_gset_rescan:cnn, \tl_gset_rescan:cno, \tl_gset_rescan:cnx % } % \begin{macro}{\tl_rescan:nn} -% \begin{macro}[aux]{\tl_set_rescan_aux:NNnn} -% \begin{macro}[aux]{\tl_rescan_aux:w} +% \begin{macro}[aux]{\@@_set_rescan:NNnn} +% \begin{macro}[aux]{\@@_rescan:w} % The idea here is to deal cleanly with the problem that % \tn{scantokens} treats the argument as a file, and without % the correct settings a \TeX{} error occurs: @@ -1322,15 +1360,15 @@ % \enquote{unprintable}. % \begin{macrocode} \cs_new_protected_nopar:Npn \tl_set_rescan:Nnn - { \tl_set_rescan_aux:NNnn \tl_set:Nn } + { \@@_set_rescan:NNnn \tl_set:Nn } \cs_new_protected_nopar:Npn \tl_gset_rescan:Nnn - { \tl_set_rescan_aux:NNnn \tl_gset:Nn } + { \@@_set_rescan:NNnn \tl_gset:Nn } \cs_new_protected_nopar:Npn \tl_rescan:nn - { \tl_set_rescan_aux:NNnn \prg_do_nothing: \use:n } -\cs_new_protected:Npn \tl_set_rescan_aux:NNnn #1#2#3#4 + { \@@_set_rescan:NNnn \prg_do_nothing: \use:n } +\cs_new_protected:Npn \@@_set_rescan:NNnn #1#2#3#4 { \group_begin: - \exp_args:No \etex_everyeof:D { \c_tl_rescan_marker_tl \exp_not:N } + \exp_args:No \etex_everyeof:D { \c_@@_rescan_marker_tl \exp_not:N } \tex_endlinechar:D \c_minus_one \tex_newlinechar:D \c_minus_one #3 @@ -1339,7 +1377,7 @@ \group_end: #1 \exp_not:N #2 { - \exp_after:wN \tl_rescan_aux:w + \exp_after:wN \@@_rescan:w \exp_after:wN \prg_do_nothing: \etex_scantokens:D {#4} } @@ -1347,8 +1385,8 @@ } \use:x { - \cs_new:Npn \exp_not:N \tl_rescan_aux:w ##1 - \c_tl_rescan_marker_tl + \cs_new:Npn \exp_not:N \@@_rescan:w ##1 + \c_@@_rescan_marker_tl { \exp_not:N \exp_not:o { ##1 } } } \cs_generate_variant:Nn \tl_set_rescan:Nnn { Nno , Nnx } @@ -1380,21 +1418,21 @@ % \begin{macro}{\tl_greplace_all:Nnn, \tl_greplace_all:cnn} % \begin{macro}{\tl_replace_once:Nnn, \tl_replace_once:cnn} % \begin{macro}{\tl_greplace_once:Nnn, \tl_greplace_once:cnn} -% \begin{macro}[aux]{\tl_replace_aux:NNNnn, \tl_replace_aux_ii:w} -% \begin{macro}[aux]{\tl_replace_all_aux:, \tl_replace_once_aux:} -% \begin{macro}[aux]{\tl_replace_once_aux_end:w} -% All of the replace functions are based on \cs{tl_replace_aux:NNNnn}, +% \begin{macro}[aux]{\@@_replace:NNNnn, \@@_replace:w} +% \begin{macro}[aux]{\@@_replace_all:, \@@_replace_once:} +% \begin{macro}[aux]{\@@_replace_once_end:w} +% All of the replace functions are based on \cs{@@_replace:NNNnn}, % whose arguments are: \meta{function}, \cs{tl_(g)set:Nx}, \meta{tl~var}, % \meta{search tokens}, \meta{replacement tokens}. % \begin{macrocode} \cs_new_protected_nopar:Npn \tl_replace_once:Nnn - { \tl_replace_aux:NNNnn \tl_replace_once_aux: \tl_set:Nx } + { \@@_replace:NNNnn \@@_replace_once: \tl_set:Nx } \cs_new_protected_nopar:Npn \tl_greplace_once:Nnn - { \tl_replace_aux:NNNnn \tl_replace_once_aux: \tl_gset:Nx } + { \@@_replace:NNNnn \@@_replace_once: \tl_gset:Nx } \cs_new_protected_nopar:Npn \tl_replace_all:Nnn - { \tl_replace_aux:NNNnn \tl_replace_all_aux: \tl_set:Nx } + { \@@_replace:NNNnn \@@_replace_all: \tl_set:Nx } \cs_new_protected_nopar:Npn \tl_greplace_all:Nnn - { \tl_replace_aux:NNNnn \tl_replace_all_aux: \tl_gset:Nx } + { \@@_replace:NNNnn \@@_replace_all: \tl_gset:Nx } \cs_generate_variant:Nn \tl_replace_once:Nnn { c } \cs_generate_variant:Nn \tl_greplace_once:Nnn { c } \cs_generate_variant:Nn \tl_replace_all:Nnn { c } @@ -1402,34 +1440,34 @@ % \end{macrocode} % The idea is easier to understand by considering the case of % \cs{tl_replace_all:Nnn}. The replacement happens within an -% \texttt{x}-type expansion. We use an auxiliary function \cs{tl_tmp:w}, +% \texttt{x}-type expansion. We use an auxiliary function \cs{@@_tmp:w}, % which essentially replaces the next \meta{search tokens} by % \meta{replacement tokens}. To avoid runaway arguments, -% we expand something like \cs{tl_tmp:w} \meta{token list} \cs{q_mark} +% we expand something like \cs{@@_tmp:w} \meta{token list} \cs{q_mark} % \meta{search tokens} \cs{q_stop}, repeating until the end. How do we % detect that we have reached the last occurrence of \meta{search tokens}? % The last replacement is characterized by the fact that the argument of -% \cs{tl_tmp:w} contains \cs{q_mark}. In the code below, -% \cs{tl_replace_aux_ii:w} takes an argument delimited by \cs{q_mark}, +% \cs{@@_tmp:w} contains \cs{q_mark}. In the code below, +% \cs{@@_replace:w} takes an argument delimited by \cs{q_mark}, % and removes the following token. Before we reach the end, this gobbles % \cs{q_mark} \cs{use_none_delimit_by_q_stop:w} which appear in the -% definition of \cs{tl_tmp:w}, and leaves the \meta{replacement tokens}, +% definition of \cs{@@_tmp:w}, and leaves the \meta{replacement tokens}, % passed to \cs{exp_not:n}, to be included in the \texttt{x}-expanding % definition. At the end, the first \cs{q_mark} is within the argument -% of \cs{tl_tmp:w}, and \cs{tl_replace_aux_ii:w} gobbles the second +% of \cs{@@_tmp:w}, and \cs{@@_replace:w} gobbles the second % \cs{q_mark} as well, leaving \cs{use_none_delimit_by_q_stop:w}, % which ends the recursion cleanly. % \begin{macrocode} -\cs_new_protected:Npn \tl_replace_aux:NNNnn #1#2#3#4#5 +\cs_new_protected:Npn \@@_replace:NNNnn #1#2#3#4#5 { \tl_if_empty:nTF {#4} { - \msg_kernel_error:nnx { tl } { empty-search-pattern } + \__msg_kernel_error:nnx { kernel } { empty-search-pattern } { \tl_to_str:n {#5} } } { \group_align_safe_begin: - \cs_set:Npx \tl_tmp:w ##1##2 #4 + \cs_set:Npx \@@_tmp:w ##1##2 #4 { ##2 \exp_not:N \q_mark @@ -1445,12 +1483,12 @@ } } } -\cs_new:Npn \tl_replace_aux_ii:w #1 \q_mark #2 { \exp_not:o {#1} } +\cs_new:Npn \@@_replace:w #1 \q_mark #2 { \exp_not:o {#1} } % \end{macrocode} -% The first argument of \cs{tl_tmp:w} is responsible for repeating +% The first argument of \cs{@@_tmp:w} is responsible for repeating % the replacement in the case of \texttt{replace_all}, and stopping % it early for \texttt{replace_once}. Note also that we build -% \cs{tl_tmp:w} within an \texttt{x}-expansion so that the +% \cs{@@_tmp:w} within an \texttt{x}-expansion so that the % \meta{replacement tokens} can contain |#|. The second % \cs{exp_not:n} ensures that the \meta{replacement tokens} % are not expanded by \cs{tl_(g)set:Nx}. @@ -1460,17 +1498,17 @@ % ensure that we don't lose braces in case the tokens between two % occurrences of the \meta{search tokens} form a brace group. % \begin{macrocode} -\cs_new:Npn \tl_replace_all_aux: +\cs_new_nopar:Npn \@@_replace_all: { - \exp_after:wN \tl_replace_aux_ii:w - \tl_tmp:w \tl_replace_all_aux: \prg_do_nothing: + \exp_after:wN \@@_replace:w + \@@_tmp:w \@@_replace_all: \prg_do_nothing: } -\cs_new_nopar:Npn \tl_replace_once_aux: +\cs_new_nopar:Npn \@@_replace_once: { - \exp_after:wN \tl_replace_aux_ii:w - \tl_tmp:w { \tl_replace_once_aux_end:w \prg_do_nothing: } \prg_do_nothing: + \exp_after:wN \@@_replace:w + \@@_tmp:w { \@@_replace_once_end:w \prg_do_nothing: } \prg_do_nothing: } -\cs_new:Npn \tl_replace_once_aux_end:w #1 \q_mark #2 \q_stop +\cs_new:Npn \@@_replace_once_end:w #1 \q_mark #2 \q_stop { \exp_not:o {#1} } % \end{macrocode} % \end{macro} @@ -1511,7 +1549,7 @@ % \subsection{Token list conditionals} % % \begin{macro}[pTF]{\tl_if_blank:n,\tl_if_blank:V,\tl_if_blank:o} -% \begin{macro}[aux]{\tl_if_blank_p_aux:NNw} +% \begin{macro}[aux]{\@@_if_blank_p:NNw} % \TeX{} skips spaces when reading a non-delimited arguments. Thus, % a \meta{token list} is blank if and only if \cs{use_none:n} % \meta{token list} |?| is empty. For performance reasons, we hard-code @@ -1525,7 +1563,7 @@ % while \tn{escapechar} is a space or is unprintable. % \begin{macrocode} \prg_new_conditional:Npnn \tl_if_blank:n #1 { p , T , F , TF } - { \tl_if_empty_return:o { \use_none:n #1 ? } } + { \@@_if_empty_return:o { \use_none:n #1 ? } } \cs_generate_variant:Nn \tl_if_blank_p:n { V } \cs_generate_variant:Nn \tl_if_blank:nT { V } \cs_generate_variant:Nn \tl_if_blank:nF { V } @@ -1561,14 +1599,15 @@ % \begin{macro}[pTF]{\tl_if_empty:n,\tl_if_empty:V} % It would be tempting to just use |\if_meaning:w \q_nil #1 \q_nil| as % a test since this works really well. However, it fails on a token -% list starting with |\q_nil| of course but more troubling is the -% case where argument is a complete conditional such as |\if_true:| -% a |\else:| b |\fi:| because then |\if_true:| is used by -% |\if_meaning:w|, the test turns out false, the |\else:| executes -% the false branch, the |\fi:| ends it and the |\q_nil| at the end +% list starting with \cs{q_nil} of course but more troubling is the +% case where argument is a complete conditional such as \cs{if_true:} +% a \cs{else:} b \cs{fi:} because then \cs{if_true:} is used by +% \cs{if_meaning:w}, the test turns out \texttt{false}, the \cs{else:} +% executes the \texttt{false} branch, the \cs{fi:} ends it and the +% \cs{q_nil} at the end % starts executing\dots{} A safer route is to convert the entire % token list into harmless characters first and then compare -% that. This way the test will even accept |\q_nil| as the first +% that. This way the test will even accept \cs{q_nil} as the first % token. % \begin{macrocode} \prg_new_conditional:Npnn \tl_if_empty:n #1 { p , TF , T , F } @@ -1587,8 +1626,8 @@ % \end{macro} % % \begin{macro}[pTF]{\tl_if_empty:o} -% \begin{macro}[EXP,aux]{\tl_if_empty_return:o} -% The auxiliary function \cs{tl_if_empty_return:o} is for use +% \begin{macro}[EXP,aux]{\@@_if_empty_return:o} +% The auxiliary function \cs{@@_if_empty_return:o} is for use % in conditionals on token lists, which mostly reduce to testing % if a given token list is empty after applying a simple function % to it. @@ -1598,7 +1637,7 @@ % Note that this works because \cs{tl_to_str:n} expands tokens % that follow until reading a catcode $1$ (begin-group) token. % \begin{macrocode} -\cs_new:Npn \tl_if_empty_return:o #1 +\cs_new:Npn \@@_if_empty_return:o #1 { \exp_after:wN \if_meaning:w \exp_after:wN \q_nil \tl_to_str:n \exp_after:wN {#1} \q_nil @@ -1608,7 +1647,7 @@ \fi: } \prg_new_conditional:Npnn \tl_if_empty:o #1 { p , TF , T , F } - { \tl_if_empty_return:o {#1} } + { \@@_if_empty_return:o {#1} } % \end{macrocode} % \end{macro} % \end{macro} @@ -1670,10 +1709,10 @@ % % \begin{macro}[TF]{\tl_if_in:nn, \tl_if_in:Vn, \tl_if_in:on, \tl_if_in:no} % Once more, the test relies on \cs{tl_to_str:n} for robustness. -% The function \cs{tl_tmp:w} removes tokens until the first occurrence +% The function \cs{@@_tmp:w} removes tokens until the first occurrence % of |#2|. If this does not appear in |#1|, then the final |#2| is removed, % leaving an empty token list. Otherwise some tokens remain, and the -% test is false. See \cs{tl_if_empty:n(TF)} for details on +% test is \texttt{false}. See \cs{tl_if_empty:n(TF)} for details on % the emptyness test. % % Special care is needed to treat correctly cases like @@ -1685,8 +1724,8 @@ % \begin{macrocode} \prg_new_protected_conditional:Npnn \tl_if_in:nn #1#2 { T , F , TF } { - \cs_set:Npn \tl_tmp:w ##1 #2 { } - \tl_if_empty:oTF { \tl_tmp:w #1 {} {} #2 } + \cs_set:Npn \@@_tmp:w ##1 #2 { } + \tl_if_empty:oTF { \@@_tmp:w #1 {} {} #2 } { \prg_return_false: } { \prg_return_true: } } \cs_generate_variant:Nn \tl_if_in:nnT { V , o , no } @@ -1695,27 +1734,73 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP,pTF]{\tl_if_single:N} +% Expand the token list and feed it to \cs{tl_if_single:n}. +% \begin{macrocode} +\cs_new:Npn \tl_if_single_p:N { \exp_args:No \tl_if_single_p:n } +\cs_new:Npn \tl_if_single:NT { \exp_args:No \tl_if_single:nT } +\cs_new:Npn \tl_if_single:NF { \exp_args:No \tl_if_single:nF } +\cs_new:Npn \tl_if_single:NTF { \exp_args:No \tl_if_single:nTF } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,pTF]{\tl_if_single:n} +% A token list has exactly one item if it is either a single +% token surrounded by optional explicit spaces, or a single brace +% group surrounded by optional explicit spaces. The naive +% version of this test would do \cs{use_none:n} |#1|, and +% test if the result is empty. However, this will fail when +% the token list is empty. Furthermore, it does not allow optional +% trailing spaces. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_single:n #1 { p , T , F , TF } + { \__str_if_eq_x_return:nn { \exp_not:o { \use_none:nn #1 ?? } } {?} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\tl_case:Nnn, \tl_case:cnn} +% \begin{macro}[aux, EXP]{\@@_case:Nw} +% \begin{macro}[aux, EXP]{\@@_case_end:nw} +% \begin{macrocode} +\cs_new:Npn \tl_case:Nnn #1#2#3 + { + \tex_romannumeral:D + \@@_case:Nw #1 #2 #1 {#3} \q_recursion_stop + } +\cs_new:Npn \@@_case:Nw #1#2#3 + { + \tl_if_eq:NNTF #1 #2 + { \@@_case_end:nw {#3} } + { \@@_case:Nw #1 } + } +\cs_generate_variant:Nn \tl_case:Nnn { c } +\cs_new_eq:NN \@@_case_end:nw \__prg_case_end:nw +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% % \subsection{Mapping to token lists} % % \begin{macro}{\tl_map_function:nN} % \begin{macro}{\tl_map_function:NN, \tl_map_function:cN} -% \begin{macro}[aux]{\tl_map_function_aux:Nn} +% \begin{macro}[aux]{\@@_map_function:Nn} % Expandable loop macro for token lists. These have the advantage of not % needing to test if the argument is empty, because if it is, the stop % marker will be read immediately and the loop terminated. % \begin{macrocode} \cs_new:Npn \tl_map_function:nN #1#2 { - \tl_map_function_aux:Nn #2 #1 + \@@_map_function:Nn #2 #1 \q_recursion_tail - \prg_break_point:n { } + \__prg_break_point:Nn \tl_map_break: { } } \cs_new_nopar:Npn \tl_map_function:NN { \exp_args:No \tl_map_function:nN } -\cs_new:Npn \tl_map_function_aux:Nn #1#2 +\cs_new:Npn \@@_map_function:Nn #1#2 { - \quark_if_recursion_tail_break:n {#2} - #1 {#2} \tl_map_function_aux:Nn #1 + \__quark_if_recursion_tail_break:nN {#2} \tl_map_break: + #1 {#2} \@@_map_function:Nn #1 } \cs_generate_variant:Nn \tl_map_function:NN { c } % \end{macrocode} @@ -1726,19 +1811,18 @@ % \begin{macro}{\tl_map_inline:nn} % \begin{macro}{\tl_map_inline:Nn, \tl_map_inline:cn} % The inline functions are straight forward by now. We use a little -% trick with the counter \cs{g_prg_map_int} to make -% them nestable. We can also make use of \cs{tl_map_function_aux:Nn} +% trick with the counter \cs{g__prg_map_int} to make +% them nestable. We can also make use of \cs{@@_map_function:Nn} % from before. % \begin{macrocode} \cs_new_protected:Npn \tl_map_inline:nn #1#2 { - \int_gincr:N \g_prg_map_int - \cs_gset:cpn { tl_map_inline_ \int_use:N \g_prg_map_int :n } - ##1 {#2} - \exp_args:Nc \tl_map_function_aux:Nn - { tl_map_inline_ \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_args:Nc \@@_map_function:Nn + { __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 \tl_map_break: { \int_gdecr:N \g__prg_map_int } } \cs_new_protected:Npn \tl_map_inline:Nn { \exp_args:No \tl_map_inline:nn } @@ -1749,25 +1833,25 @@ % % \begin{macro}{\tl_map_variable:nNn} % \begin{macro}{\tl_map_variable:NNn, \tl_map_variable:cNn} -% \begin{macro}[aux]{\tl_map_variable_aux:Nnn} +% \begin{macro}[aux]{\@@_map_variable:Nnn} % \cs{tl_map_variable:nNn} \meta{token list} \meta{temp} \meta{action} % assigns % \meta{temp} to each element and executes \meta{action}. % \begin{macrocode} \cs_new_protected:Npn \tl_map_variable:nNn #1#2#3 { - \tl_map_variable_aux:Nnn #2 {#3} #1 + \@@_map_variable:Nnn #2 {#3} #1 \q_recursion_tail - \prg_break_point:n { } + \__prg_break_point:Nn \tl_map_break: { } } \cs_new_protected_nopar:Npn \tl_map_variable:NNn { \exp_args:No \tl_map_variable:nNn } -\cs_new_protected:Npn \tl_map_variable_aux:Nnn #1#2#3 +\cs_new_protected:Npn \@@_map_variable:Nnn #1#2#3 { \tl_set:Nn #1 {#3} - \quark_if_recursion_tail_break:N #1 + \__quark_if_recursion_tail_break:NN #1 \tl_map_break: \use:n {#2} - \tl_map_variable_aux:Nnn #1 {#2} + \@@_map_variable:Nnn #1 {#2} } \cs_generate_variant:Nn \tl_map_variable:NNn { c } % \end{macrocode} @@ -1777,10 +1861,12 @@ % % \begin{macro}{\tl_map_break:} % \begin{macro}{\tl_map_break:n} -% The break statements are simply copies. +% The break statements use the general \cs{__prg_map_break:Nn}. % \begin{macrocode} -\cs_new_eq:NN \tl_map_break: \prg_map_break: -\cs_new_eq:NN \tl_map_break:n \prg_map_break:n +\cs_new_nopar:Npn \tl_map_break: + { \__prg_map_break:Nn \tl_map_break: { } } +\cs_new_nopar:Npn \tl_map_break:n + { \__prg_map_break:Nn \tl_map_break: } % \end{macrocode} % \end{macro} % \end{macro} @@ -1811,7 +1897,7 @@ \cs_new:Npn \tl_use:N #1 { \tl_if_exist:NTF #1 {#1} - { \msg_expandable_kernel_error:nnn { kernel } { bad-var } {#1} } + { \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#1} } } \cs_generate_variant:Nn \tl_use:N { c } % \end{macrocode} @@ -1819,54 +1905,54 @@ % % \subsection{Working with the contents of token lists} % -% \begin{macro}{\tl_length:n, \tl_length:V, \tl_length:o} -% \begin{macro}{\tl_length:N, \tl_length:c} -% \begin{macro}[aux]{\tl_length_aux:n} +% \begin{macro}{\tl_count:n, \tl_count:V, \tl_count:o} +% \begin{macro}{\tl_count:N, \tl_count:c} +% \begin{macro}[aux]{\@@_count:n} % Count number of elements within a token list or token list % variable. Brace groups within the list are read as a single % element. Spaces are ignored. -% \cs{tl_length_aux:n} grabs the element and replaces it by |+1|. +% \cs{@@_count:n} grabs the element and replaces it by |+1|. % The |0| to ensure it works on an empty list. % \begin{macrocode} -\cs_new:Npn \tl_length:n #1 +\cs_new:Npn \tl_count:n #1 { \int_eval:n - { 0 \tl_map_function:nN {#1} \tl_length_aux:n } + { 0 \tl_map_function:nN {#1} \@@_count:n } } -\cs_new:Npn \tl_length:N #1 +\cs_new:Npn \tl_count:N #1 { \int_eval:n - { 0 \tl_map_function:NN #1 \tl_length_aux:n } + { 0 \tl_map_function:NN #1 \@@_count:n } } -\cs_new:Npn \tl_length_aux:n #1 { + \c_one } -\cs_generate_variant:Nn \tl_length:n { V , o } -\cs_generate_variant:Nn \tl_length:N { c } +\cs_new:Npn \@@_count:n #1 { + \c_one } +\cs_generate_variant:Nn \tl_count:n { V , o } +\cs_generate_variant:Nn \tl_count:N { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\tl_reverse_items:n} -% \begin{macro}[aux]{\tl_reverse_items_aux:nwNwn} -% \begin{macro}[aux]{\tl_reverse_items_aux:wn} +% \begin{macro}[aux]{\@@_reverse_items:nwNwn} +% \begin{macro}[aux]{\@@_reverse_items:wn} % Reversal of a token list is done by taking one item at a time % and putting it after \cs{q_stop}. % \begin{macrocode} \cs_new:Npn \tl_reverse_items:n #1 { - \tl_reverse_items_aux:nwNwn #1 ? - \q_mark \tl_reverse_items_aux:nwNwn - \q_mark \tl_reverse_items_aux:wn + \@@_reverse_items:nwNwn #1 ? + \q_mark \@@_reverse_items:nwNwn + \q_mark \@@_reverse_items:wn \q_stop { } } -\cs_new:Npn \tl_reverse_items_aux:nwNwn #1 #2 \q_mark #3 #4 \q_stop #5 +\cs_new:Npn \@@_reverse_items:nwNwn #1 #2 \q_mark #3 #4 \q_stop #5 { #3 #2 - \q_mark \tl_reverse_items_aux:nwNwn - \q_mark \tl_reverse_items_aux:wn + \q_mark \@@_reverse_items:nwNwn + \q_mark \@@_reverse_items:wn \q_stop { {#1} #5 } } -\cs_new:Npn \tl_reverse_items_aux:wn #1 \q_stop #2 +\cs_new:Npn \@@_reverse_items:wn #1 \q_stop #2 { \exp_not:o { \use_none:nn #2 } } % \end{macrocode} % \end{macro} @@ -1879,78 +1965,237 @@ % \tl_trim_spaces:N, \tl_trim_spaces:c, % \tl_gtrim_spaces:N, \tl_gtrim_spaces:c % } +% Trimming spaces from around the input is deferred to an internal +% function whose first argument is the token list to trim, augmented +% by an initial \cs{q_mark}, and whose second argument is a +% \meta{continuation}, which will receive as a braced argument +% \cs{use_none:n} \cs{q_mark} \meta{trimmed token list}. In the case +% at hand, we take \cs{exp_not:o} as our continuation, so that space +% trimming will behave correctly within an \texttt{x}-type expansion. +% \begin{macrocode} +\cs_new:Npn \tl_trim_spaces:n #1 + { \@@_trim_spaces:nn { \q_mark #1 } \exp_not:o } +\cs_new_protected:Npn \tl_trim_spaces:N #1 + { \tl_set:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } } +\cs_new_protected:Npn \tl_gtrim_spaces:N #1 + { \tl_gset:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } } +\cs_generate_variant:Nn \tl_trim_spaces:N { c } +\cs_generate_variant:Nn \tl_gtrim_spaces:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\@@_trim_spaces:nn} % \begin{macro}[aux] % { -% \tl_trim_spaces_aux_i:w, \tl_trim_spaces_aux_ii:w -% \tl_trim_spaces_aux_iii:w, \tl_trim_spaces_aux_iv:w +% \@@_trim_spaces_i:w, \@@_trim_spaces_ii:w +% \@@_trim_spaces_iii:w, \@@_trim_spaces_iv:w % } % Trimming spaces from around the input is done using delimited % arguments and quarks, and to get spaces at odd places in the -% definitions, we nest those in \cs{tl_tmp:w}, which then receives +% definitions, we nest those in \cs{@@_tmp:w}, which then receives % a single space as its argument: |#1| is \verb*+ +. -% Removing leading spaces is done with \cs{tl_trim_spaces_aux_i:w}, +% Removing leading spaces is done with \cs{@@_trim_spaces_i:w}, % which loops until \cs{q_mark}\verb*+ + matches the end of the token % list: then |##1| is the token list and |##3| is -% \cs{tl_trim_spaces_aux_ii:w}. This hands the relevant tokens to the -% loop \cs{tl_trim_spaces_aux_iii:w}, responsible for trimming +% \cs{@@_trim_spaces_ii:w}. This hands the relevant tokens to the +% loop \cs{@@_trim_spaces_iii:w}, responsible for trimming % trailing spaces. The end is reached when \verb*+ + \cs{q_nil} % matches the one present in the definition of \cs{tl_trim_spacs:n}. -% Then \cs{tl_trim_spaces_aux_iv:w} puts the token list into a group, -% as the argument of the initial \tn{unexpanded}. -% The \tn{unexpanded} here is used so that space trimming will -% behave correctly within an \texttt{x}-type expansion. -% -% Some of the auxiliaries used in this code are also used -% in the \pkg{l3clist} module. Change with care. +% Then \cs{@@_trim_spaces_iv:w} puts the token list into a group, +% with \cs{use_none:n} placed there to gobble a lingering \cs{q_mark}, +% and feeds this to the \meta{continuation}. % \begin{macrocode} -\cs_set:Npn \tl_tmp:w #1 +\cs_set:Npn \@@_tmp:w #1 { - \cs_new:Npn \tl_trim_spaces:n ##1 + \cs_new:Npn \@@_trim_spaces:nn ##1 { - \etex_unexpanded:D - \tl_trim_spaces_aux_i:w - \q_mark + \@@_trim_spaces_i:w ##1 \q_nil \q_mark #1 { } - \q_mark \tl_trim_spaces_aux_ii:w - \tl_trim_spaces_aux_iii:w + \q_mark \@@_trim_spaces_ii:w + \@@_trim_spaces_iii:w #1 \q_nil - \tl_trim_spaces_aux_iv:w - \q_stop + \@@_trim_spaces_iv:w + \q_stop } - \cs_new:Npn \tl_trim_spaces_aux_i:w ##1 \q_mark #1 ##2 \q_mark ##3 + \cs_new:Npn \@@_trim_spaces_i:w ##1 \q_mark #1 ##2 \q_mark ##3 { ##3 - \tl_trim_spaces_aux_i:w + \@@_trim_spaces_i:w \q_mark ##2 \q_mark #1 {##1} } - \cs_new:Npn \tl_trim_spaces_aux_ii:w ##1 \q_mark \q_mark ##2 + \cs_new:Npn \@@_trim_spaces_ii:w + \@@_trim_spaces_i:w \q_mark \q_mark ##1 { - \tl_trim_spaces_aux_iii:w - ##2 + \@@_trim_spaces_iii:w + ##1 } - \cs_new:Npn \tl_trim_spaces_aux_iii:w ##1 #1 \q_nil ##2 + \cs_new:Npn \@@_trim_spaces_iii:w ##1 #1 \q_nil ##2 { ##2 ##1 \q_nil - \tl_trim_spaces_aux_iii:w + \@@_trim_spaces_iii:w } - \cs_new:Npn \tl_trim_spaces_aux_iv:w ##1 \q_nil ##2 \q_stop - { \exp_after:wN { \use_none:n ##1 } } + \cs_new:Npn \@@_trim_spaces_iv:w ##1 \q_nil ##2 \q_stop ##3 + { ##3 { \use_none:n ##1 } } } -\tl_tmp:w { ~ } -\cs_new_protected:Npn \tl_trim_spaces:N #1 - { \tl_set:Nx #1 { \exp_after:wN \tl_trim_spaces:n \exp_after:wN {#1} } } -\cs_new_protected:Npn \tl_gtrim_spaces:N #1 - { \tl_gset:Nx #1 { \exp_after:wN \tl_trim_spaces:n \exp_after:wN {#1} } } -\cs_generate_variant:Nn \tl_trim_spaces:N { c } -\cs_generate_variant:Nn \tl_gtrim_spaces:N { c } +\@@_tmp:w { ~ } % \end{macrocode} % \end{macro} % \end{macro} +% +% \subsection{Token by token changes} +% +% \begin{variable}{\q__@@_act_mark,\q__@@_act_stop} +% The \cs{tl_act} functions may be applied to any token list. +% Hence, we use two private quarks, to allow any token, even quarks, +% in the token list.^^A in particular critical for future \::e. +% Only \cs{q__@@_act_mark} and \cs{q__@@_act_stop} may not appear +% in the token lists manipulated by \cs{@@_act:NNNnn} functions. The quarks +% are effectively defined in \pkg{l3quark}. +% \end{variable} +% +% \begin{macro}[EXP,int]{\@@_act:NNNnn} +% \begin{macro}[EXP,aux]{\@@_act_output:n, \@@_act_reverse_output:n} +% \begin{macro}[EXP,aux]{\@@_act_loop:w} +% \begin{macro}[EXP,aux]{\@@_act_normal:NwnNNN} +% \begin{macro}[EXP,aux]{\@@_act_group:nwnNNN} +% \begin{macro}[EXP,aux]{\@@_act_space:wwnNNN} +% \begin{macro}[EXP,aux]{\@@_act_end:w} +% To help control the expansion, \cs{@@_act:NNNnn} should always +% be proceeded by \tn{romannumeral} and ends by producing \cs{c_zero} +% once the result has been obtained. Then loop over tokens, +% groups, and spaces in |#5|. The marker \cs{q__@@_act_mark} +% is used both to avoid losing outer braces and to detect the +% end of the token list more easily. The result is stored +% as an argument for the dummy function \cs{@@_act_result:n}. +% \begin{macrocode} +\cs_new:Npn \@@_act:NNNnn #1#2#3#4#5 + { + \group_align_safe_begin: + \@@_act_loop:w #5 \q__@@_act_mark \q__@@_act_stop + {#4} #1 #2 #3 + \@@_act_result:n { } + } +% \end{macrocode} +% In the loop, we check how the token list begins and act +% accordingly. In the \enquote{normal} case, we may have +% reached \cs{q__@@_act_mark}, the end of the list. Then +% leave \cs{c_zero} and the result in the input stream, +% to terminate the expansion of \tn{romannumeral}. +% Otherwise, apply the relevant function to the +% \enquote{arguments}, |#3| +% and to the head of the token list. Then repeat the loop. +% The scheme is the same if the token list starts with a +% group or with a space. Some extra work is needed to +% make \cs{@@_act_space:wwnNNN} gobble the space. +% \begin{macrocode} +\cs_new:Npn \@@_act_loop:w #1 \q__@@_act_stop + { + \tl_if_head_is_N_type:nTF {#1} + { \@@_act_normal:NwnNNN } + { + \tl_if_head_is_group:nTF {#1} + { \@@_act_group:nwnNNN } + { \@@_act_space:wwnNNN } + } + #1 \q__@@_act_stop + } +\cs_new:Npn \@@_act_normal:NwnNNN #1 #2 \q__@@_act_stop #3#4 + { + \if_meaning:w \q__@@_act_mark #1 + \exp_after:wN \@@_act_end:wn + \fi: + #4 {#3} #1 + \@@_act_loop:w #2 \q__@@_act_stop + {#3} #4 + } +\cs_new:Npn \@@_act_end:wn #1 \@@_act_result:n #2 + { \group_align_safe_end: \c_zero #2 } +\cs_new:Npn \@@_act_group:nwnNNN #1 #2 \q__@@_act_stop #3#4#5 + { + #5 {#3} {#1} + \@@_act_loop:w #2 \q__@@_act_stop + {#3} #4 #5 + } +\exp_last_unbraced:NNo + \cs_new:Npn \@@_act_space:wwnNNN \c_space_tl #1 \q__@@_act_stop #2#3#4#5 + { + #5 {#2} + \@@_act_loop:w #1 \q__@@_act_stop + {#2} #3 #4 #5 + } +% \end{macrocode} +% Typically, the output is done to the right of what was already output, +% using \cs{@@_act_output:n}, but for the \cs{@@_act_reverse} functions, +% it should be done to the left. +% \begin{macrocode} +\cs_new:Npn \@@_act_output:n #1 #2 \@@_act_result:n #3 + { #2 \@@_act_result:n { #3 #1 } } +\cs_new:Npn \@@_act_reverse_output:n #1 #2 \@@_act_result:n #3 + { #2 \@@_act_result:n { #1 #3 } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\tl_reverse:n, \tl_reverse:o, \tl_reverse:V} +% \begin{macro}[EXP,aux]{\@@_reverse_normal:nN} +% \begin{macro}[EXP,aux]{\@@_reverse_group_preserve:nn} +% \begin{macro}[EXP,aux]{\@@_reverse_space:n} +% The goal here is to reverse without losing spaces nor braces. +% This is done using the general internal function \cs{@@_act:NNNnn}. +% Spaces and \enquote{normal} tokens are output on the left of the current +% output. Grouped tokens are output to the left but without any reversal +% within the group. All of the internal functions here drop one argument: +% this is needed by \cs{@@_act:NNNnn} when changing case (to record +% which direction the change is in), but not when reversing the tokens. +% \begin{macrocode} +\cs_new:Npn \tl_reverse:n #1 + { + \etex_unexpanded:D \exp_after:wN + { + \tex_romannumeral:D + \@@_act:NNNnn + \@@_reverse_normal:nN + \@@_reverse_group_preserve:nn + \@@_reverse_space:n + { } + {#1} + } + } +\cs_generate_variant:Nn \tl_reverse:n { o , V } +\cs_new:Npn \@@_reverse_normal:nN #1#2 + { \@@_act_reverse_output:n {#2} } +\cs_new:Npn \@@_reverse_group_preserve:nn #1#2 + { \@@_act_reverse_output:n { {#2} } } +\cs_new:Npn \@@_reverse_space:n #1 + { \@@_act_reverse_output:n { ~ } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_reverse:N, \tl_reverse:c, \tl_greverse:N, \tl_greverse:c} +% This reverses the list, leaving \cs{exp_stop_f:} in front, +% which stops the \texttt{f}-expansion. +% \begin{macrocode} +\cs_new_protected:Npn \tl_reverse:N #1 + { \tl_set:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } } +\cs_new_protected:Npn \tl_greverse:N #1 + { \tl_gset:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } } +\cs_generate_variant:Nn \tl_reverse:N { c } +\cs_generate_variant:Nn \tl_greverse:N { c } +% \end{macrocode} % \end{macro} % % \subsection{The first token from a token list} @@ -1959,6 +2204,7 @@ % \begin{macro}{\tl_head:w} % \begin{macro}{\tl_tail:N, \tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f} % \begin{macro}{\tl_tail:w} +% \begin{macro}[aux]{\@@_tail:w} % These functions pick up either the head or the tail of a list. The % empty brace groups in \cs{tl_head:n} and \cs{tl_tail:n} ensure that % a blank argument gives an empty result. The result is returned within @@ -1969,8 +2215,8 @@ \cs_new:Npn \tl_head:n #1 { \etex_unexpanded:D \exp_after:wN { \tl_head:w #1 { } \q_stop } } \cs_new:Npn \tl_tail:n #1 - { \etex_unexpanded:D \tl_tail_aux:w #1 \q_mark { } \q_mark \q_stop } -\cs_new:Npn \tl_tail_aux:w #1 #2 \q_mark #3 \q_stop { {#2} } + { \etex_unexpanded:D \@@_tail:w #1 \q_mark { } \q_mark \q_stop } +\cs_new:Npn \@@_tail:w #1 #2 \q_mark #3 \q_stop { {#2} } \cs_new_nopar:Npn \tl_head:N { \exp_args:No \tl_head:n } \cs_generate_variant:Nn \tl_head:n { V , v , f } \cs_new_nopar:Npn \tl_tail:N { \exp_args:No \tl_tail:n } @@ -1980,46 +2226,47 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\str_head:n, \str_tail:n} -% \begin{macro}[aux]{\str_head_aux:w} -% \begin{macro}[aux]{\str_tail_aux:w} +% \begin{macro}[aux]{\__str_head:w} +% \begin{macro}[aux]{\__str_tail:w} % After \cs{tl_to_str:n}, we have a list of character tokens, % all with category code 12, except the space, which has category % code 10. Directly using \cs{tl_head:w} would thus lose leading spaces. % Instead, we take an argument delimited by an explicit space, and % then only use \cs{tl_head:w}. If the string started with a -% space, then the argument of \cs{str_head_aux:w} is empty, and +% space, then the argument of \cs{__str_head:w} is empty, and % the function correctly returns a space character. Otherwise, % it returns the first token of |#1|, which is the first token % of the string. If the string is empty, we return an empty result. % % To remove the first character of \cs{tl_to_str:n} |{#1}|, % we test it using \cs{if_charcode:w} \cs{scan_stop:}, -% always false for characters. If the argument was non-empty, -% then \cs{str_tail_aux:w} returns everything until the first +% always \texttt{false} for characters. If the argument was non-empty, +% then \cs{__str_tail:w} returns everything until the first % \texttt{X} (with category code letter, no risk of confusing % with the user input). If the argument was empty, the first % \texttt{X} is taken by \cs{if_charcode:w}, and nothing % is returned. We use \texttt{X} as a \meta{marker}, rather than % a quark because the test \cs{if_charcode:w} \cs{scan_stop:} -% \meta{marker} has to be false. +% \meta{marker} has to be \texttt{false}. % \begin{macrocode} \cs_new:Npn \str_head:n #1 { - \exp_after:wN \str_head_aux:w + \exp_after:wN \__str_head:w \tl_to_str:n {#1} { { } } ~ \q_stop } -\cs_new:Npn \str_head_aux:w #1 ~ % +\cs_new:Npn \__str_head:w #1 ~ % { \tl_head:w #1 { ~ } } \cs_new:Npn \str_tail:n #1 { - \exp_after:wN \str_tail_aux:w + \exp_after:wN \__str_tail:w \reverse_if:N \if_charcode:w \scan_stop: \tl_to_str:n {#1} X X \q_stop } -\cs_new:Npn \str_tail_aux:w #1 X #2 \q_stop { \fi: #1 } +\cs_new:Npn \__str_tail:w #1 X #2 \q_stop { \fi: #1 } % \end{macrocode} % \end{macro} % \end{macro} @@ -2029,32 +2276,39 @@ % \begin{macro}[pTF]{\tl_if_head_eq_charcode:nN} % \begin{macro}[pTF]{\tl_if_head_eq_charcode:fN} % \begin{macro}[pTF]{\tl_if_head_eq_catcode:nN} -% Accessing the first token of a token list is tricky in two cases: -% when it has category code $1$ (begin-group token), or when it is -% an explicit space, with category code $10$ and character code $32$. -% -% Forgetting temporarily about this issue we would use the -% following test in \cs{tl_if_head_eq_charcode:nN}. Here, -% an empty |#1| argument yields \cs{q_nil}, otherwise the -% first token of the token list. +% Accessing the first token of a token list is tricky in three cases: +% when it has category code $1$ (begin-group token), when it is an +% explicit space, with category code $10$ and character code $32$, or +% when the token list is empty (obviously). +% +% Forgetting temporarily about this issue we would use the following +% test in \cs{tl_if_head_eq_charcode:nN}. Here, \cs{tl_head:w} yields +% the first token of the token list, then passed to \cs{exp_not:N}. % \begin{verbatim} % \if_charcode:w % \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop % \exp_not:N #2 % \end{verbatim} -% The special cases are detected using \cs{tl_if_head_N_type:n} -% (the extra |?| takes care of empty arguments). -% In those cases, the first token is a character, and -% since we only care about its character code, we can -% use \cs{str_head:n} to access it (this works even if -% it is a space character). +% The two first special cases are detected by testing if the token +% list starts with an \texttt{N}-type token (the extra |?| sends empty +% token lists to the \texttt{true} branch of this test). In those +% cases, the first token is a character, and since we only care about +% its character code, we can use \cs{str_head:n} to access it (this +% works even if it is a space character). An empty argument will +% result in \cs{tl_head:w} leaving two tokens: |?| which is taken in +% the \cs{if_charcode:w} test, and \cs{use_none:nn}, which ensures +% that \cs{prg_return_false:} is returned regardless of whether the +% charcode test was \texttt{true} or \texttt{false}. % \begin{macrocode} \prg_new_conditional:Npnn \tl_if_head_eq_charcode:nN #1#2 { p , T , F , TF } { \if_charcode:w \exp_not:N #2 - \tl_if_head_N_type:nTF { #1 ? } - { \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop } + \tl_if_head_is_N_type:nTF { #1 ? } + { + \exp_after:wN \exp_not:N + \tl_head:w #1 { ? \use_none:nn } \q_stop + } { \str_head:n {#1} } \prg_return_true: \else: @@ -2066,20 +2320,26 @@ \cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { f } \cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { f } % \end{macrocode} -% For \cs{tl_if_head_eq_catcode:nN}, again we detect special -% cases with a \cs{tl_if_head_N_type}. Then we need to test -% if the first token is a begin-group token or an explicit -% space token, and produce the relevant token, either -% \cs{c_group_begin_token} or \cs{c_space_token}. +% For \cs{tl_if_head_eq_catcode:nN}, again we detect special cases +% with a \cs{tl_if_head_is_N_type:n}. Then we need to test if the +% first token is a begin-group token or an explicit space token, and +% produce the relevant token, either \cs{c_group_begin_token} or +% \cs{c_space_token}. Again, for an empty argument, a hack is used, +% removing \cs{prg_return_true:} and \cs{else:} with \cs{use_none:nn} +% in case the catcode test with the (arbitrarily chosen) |?| is +% \texttt{true}. % \begin{macrocode} \prg_new_conditional:Npnn \tl_if_head_eq_catcode:nN #1 #2 { p , T , F , TF } { \if_catcode:w \exp_not:N #2 - \tl_if_head_N_type:nTF { #1 ? } - { \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop } + \tl_if_head_is_N_type:nTF { #1 ? } { - \tl_if_head_group:nTF {#1} + \exp_after:wN \exp_not:N + \tl_head:w #1 { ? \use_none:nn } \q_stop + } + { + \tl_if_head_is_group:nTF {#1} { \c_group_begin_token } { \c_space_token } } @@ -2089,29 +2349,34 @@ \fi: } % \end{macrocode} -% For \cs{tl_if_head_eq_meaning:nN}, again, detect special cases. -% In the normal case, use \cs{tl_head:w}, with no \cs{exp_not:N} -% this time, since \cs{if_meaning:w} causes no expansion. +% For \cs{tl_if_head_eq_meaning:nN}, again, detect special cases. In +% the normal case, use \cs{tl_head:w}, with no \cs{exp_not:N} this +% time, since \cs{if_meaning:w} causes no expansion. With an empty +% argument, the test is \texttt{true}, and \cs{use_none:nnn} removes +% |#2| and the usual \cs{prg_return_true:} and \cs{else:}. % In the special cases, we know that the first token is a character, % hence \cs{if_charcode:w} and \cs{if_catcode:w} together are enough. % We combine them in some order, hopefully faster than the reverse. +% Tests are not nested because the arguments may contain unmatched +% primitive conditionals. % \begin{macrocode} \prg_new_conditional:Npnn \tl_if_head_eq_meaning:nN #1#2 { p , T , F , TF } { - \tl_if_head_N_type:nTF { #1 ? } - { \tl_if_head_eq_meaning_aux_normal:nN } - { \tl_if_head_eq_meaning_aux_special:nN } + \tl_if_head_is_N_type:nTF { #1 ? } + { \@@_if_head_eq_meaning_normal:nN } + { \@@_if_head_eq_meaning_special:nN } {#1} #2 } -\cs_new:Npn \tl_if_head_eq_meaning_aux_normal:nN #1 #2 +\cs_new:Npn \@@_if_head_eq_meaning_normal:nN #1 #2 { - \exp_after:wN \if_meaning:w \tl_head:w #1 \q_nil \q_stop #2 + \exp_after:wN \if_meaning:w + \tl_head:w #1 { ?? \use_none:nnn } \q_stop #2 \prg_return_true: \else: \prg_return_false: \fi: } -\cs_new:Npn \tl_if_head_eq_meaning_aux_special:nN #1 #2 +\cs_new:Npn \@@_if_head_eq_meaning_special:nN #1 #2 { \if_charcode:w \str_head:n {#1} \exp_not:N #2 \exp_after:wN \use:n @@ -2121,7 +2386,7 @@ \fi: { \if_catcode:w \exp_not:N #2 - \tl_if_head_group:nTF {#1} + \tl_if_head_is_group:nTF {#1} { \c_group_begin_token } { \c_space_token } \prg_return_true: @@ -2136,7 +2401,7 @@ % \end{macro} % \end{macro} % -% \begin{macro}[pTF]{\tl_if_head_N_type:n} +% \begin{macro}[pTF]{\tl_if_head_is_N_type:n} % The first token of a token list can be either an N-type argument, % a begin-group token (catcode 1), or an explicit space token % (catcode 10 and charcode 32). These two cases are characterized @@ -2145,16 +2410,16 @@ % string representation). The extra brace group covers the case of % an empty argument, whose head is not \enquote{normal}. % \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_head_N_type:n #1 { p , T , F , TF } +\prg_new_conditional:Npnn \tl_if_head_is_N_type:n #1 { p , T , F , TF } { - \str_if_eq_return:xx + \__str_if_eq_x_return:nn { \exp_not:o { \use:n #1 { } } } { \exp_not:n { #1 { } } } } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP,pTF]{\tl_if_head_group:n} +% \begin{macro}[EXP,pTF]{\tl_if_head_is_group:n} % Pass the first token of |#1| through \cs{token_to_str:N}, % then check for the brace balance. The extra \texttt{?} % caters for an empty argument.\footnote{Bruno: this could @@ -2163,7 +2428,7 @@ % to happen in one step of expansion, keeping the token % list brace balanced at all times.} % \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_head_group:n #1 { p , T , F , TF } +\prg_new_conditional:Npnn \tl_if_head_is_group:n #1 { p , T , F , TF } { \if_catcode:w * \exp_after:wN \use_none:n @@ -2181,22 +2446,22 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP,pTF]{\tl_if_head_space:n} -% \begin{macro}[EXP,aux]{\tl_if_head_space_aux:w} +% \begin{macro}[EXP,pTF]{\tl_if_head_is_space:n} +% \begin{macro}[EXP,aux]{\@@_if_head_is_space:w} % If the first token of the token list is an explicit space, i.e., % a character token with character code $32$ and category code $10$, -% then this test will be \meta{true}. It is \meta{false} if the token +% then this test will be \texttt{true}. It is \texttt{false} if the token % list is empty, if the first token is an implicit space token, % such as \cs{c_space_token}, or any token other than an explicit space. % The slightly convoluted approach with \tn{romannumeral} ensures that % each expansion step gives a balanced token list. % \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_head_space:n #1 { p , T , F , TF } +\prg_new_conditional:Npnn \tl_if_head_is_space:n #1 { p , T , F , TF } { \tex_romannumeral:D \if_false: { \fi: - \tl_if_head_space_aux:w ? #1 ? ~ } + \@@_if_head_is_space:w ? #1 ? ~ } } -\cs_new:Npn \tl_if_head_space_aux:w #1 ~ +\cs_new:Npn \@@_if_head_is_space:w #1 ~ { \tl_if_empty:oTF { \use_none:n #1 } { \exp_after:wN \c_zero \exp_after:wN \prg_return_true: } @@ -2225,37 +2490,6 @@ % \end{macrocode} %\end{macro} % -% \subsection{Constant token lists} -% -% \begin{variable}{\c_job_name_tl} -% Inherited from the \LaTeX3 name for the primitive: this needs to -% actually contain the text of the job name rather than the name of -% the primitive, of course. \LuaTeX{} does not quote file names containing -% spaces, whereas \pdfTeX{} and \XeTeX{} do. So there may be a correction to -% make in the \LuaTeX{} case. -% \begin{macrocode} -%<*initex> -\tex_everyjob:D \exp_after:wN - { - \tex_the:D \tex_everyjob:D - \luatex_if_engine:T - { - \lua_now:x - { dofile ( assert ( kpse.find_file ("lualatexquotejobname.lua" ) ) ) } - } - } -%</initex> -\tl_const:Nx \c_job_name_tl { \tex_jobname:D } -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\c_space_tl} -% A space as a token list (as opposed to as a character). -% \begin{macrocode} -\tl_const:Nn \c_space_tl { ~ } -% \end{macrocode} -% \end{variable} -% % \subsection{Scratch token lists} % % \begin{variable}{\g_tmpa_tl, \g_tmpb_tl} @@ -2279,398 +2513,6 @@ % \end{macrocode} % \end{variable} % -% \subsection{Experimental functions} -% -% \begin{macro}[EXP]{\str_if_eq_return:xx} -% It turns out that we often need to compare a token list -% with the result of applying some function to it, and -% return with \cs{prg_return_true/false:}. This test is -% similar to \cs{str_if_eq:nnTF}, but hard-coded for speed. -% \begin{macrocode} -\cs_new:Npn \str_if_eq_return:xx #1 #2 - { - \if_int_compare:w \pdftex_strcmp:D {#1} {#2} = \c_zero - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP,pTF]{\tl_if_single:N} -% Expand the token list and feed it to \cs{tl_if_single:n}. -% \begin{macrocode} -\cs_new:Npn \tl_if_single_p:N { \exp_args:No \tl_if_single_p:n } -\cs_new:Npn \tl_if_single:NT { \exp_args:No \tl_if_single:nT } -\cs_new:Npn \tl_if_single:NF { \exp_args:No \tl_if_single:nF } -\cs_new:Npn \tl_if_single:NTF { \exp_args:No \tl_if_single:nTF } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP,pTF]{\tl_if_single:n} -% A token list has exactly one item if it is either a single -% token surrounded by optional explicit spaces, or a single brace -% group surrounded by optional explicit spaces. The naive -% version of this test would do \cs{use_none:n} |#1|, and -% test if the result is empty. However, this will fail when -% the token list is empty. Furthermore, it does not allow optional -% trailing spaces. -% \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_single:n #1 { p , T , F , TF } - { \str_if_eq_return:xx { \exp_not:o { \use_none:nn #1 ?? } } {?} } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP,pTF]{\tl_if_single_token:n} -% There are four cases: empty token list, token list starting with -% a normal token, with a brace group, or with a space token. -% If the token list starts with a normal token, remove it -% and check for emptyness. Otherwise, compare with a single -% space, only case where we have a single token. -% \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_single_token:n #1 { p , T , F , TF } - { - \tl_if_head_N_type:nTF {#1} - { \str_if_eq_return:xx { \exp_not:o { \use_none:n #1 } } { } } - { \str_if_eq_return:xx { \exp_not:n {#1} } { ~ } } - } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\q_tl_act_mark,\q_tl_act_stop} -% The \cs{tl_act} functions may be applied to any token list. -% Hence, we use two private quarks, to allow any token, even quarks, -% in the token list.^^A in particular critical for future \::e. -% Only \cs{q_tl_act_mark} and \cs{q_tl_act_stop} may not appear -% in the token lists manipulated by \cs{tl_act} functions. The quarks -% are effectively defined in \pkg{l3quark}. -% \end{variable} -% -% \begin{macro}[EXP]{\tl_act:NNNnn,\tl_act_aux:NNNnn} -% \begin{macro}[EXP]{\tl_act_output:n,\tl_act_reverse_output:n, -% \tl_act_group_recurse:Nnn} -% \begin{macro}[EXP,aux]{\tl_act_loop:w,\tl_act_normal:NwnNNN, -% \tl_act_group:nwnNNN,\tl_act_space:wwnNNN,\tl_act_end:w} -% To help control the expansion, \cs{tl_act:NNNnn} starts with -% \tn{romannumeral} and ends by producing \cs{c_zero} -% once the result has been obtained. Then loop over tokens, -% groups, and spaces in |#5|. The marker \cs{q_tl_act_mark} -% is used both to avoid losing outer braces and to detect the -% end of the token list more easily. The result is stored -% as an argument for the dummy function \cs{tl_act_result:n}. -% \begin{macrocode} -\cs_new:Npn \tl_act:NNNnn { \tex_romannumeral:D \tl_act_aux:NNNnn } -\cs_new:Npn \tl_act_aux:NNNnn #1 #2 #3 #4 #5 - { - \group_align_safe_begin: - \tl_act_loop:w #5 \q_tl_act_mark \q_tl_act_stop - {#4} #1 #2 #3 - \tl_act_result:n { } - } -% \end{macrocode} -% In the loop, we check how the token list begins and act -% accordingly. In the \enquote{normal} case, we may have -% reached \cs{q_tl_act_mark}, the end of the list. Then -% leave \cs{c_zero} and the result in the input stream, -% to terminate the expansion of \tn{romannumeral}. -% Otherwise, apply the relevant function to the -% \enquote{arguments}, |#3| -% and to the head of the token list. Then repeat the loop. -% The scheme is the same if the token list starts with a -% group or with a space. Some extra work is needed to -% make \cs{tl_act_space:wwnNNN} gobble the space. -% \begin{macrocode} -\cs_new:Npn \tl_act_loop:w #1 \q_tl_act_stop - { - \tl_if_head_N_type:nTF {#1} - { \tl_act_normal:NwnNNN } - { - \tl_if_head_group:nTF {#1} - { \tl_act_group:nwnNNN } - { \tl_act_space:wwnNNN } - } - #1 \q_tl_act_stop - } -\cs_new:Npn \tl_act_normal:NwnNNN #1 #2 \q_tl_act_stop #3#4 - { - \if_meaning:w \q_tl_act_mark #1 - \exp_after:wN \tl_act_end:wn - \fi: - #4 {#3} #1 - \tl_act_loop:w #2 \q_tl_act_stop - {#3} #4 - } -\cs_new:Npn \tl_act_end:wn #1 \tl_act_result:n #2 - { \group_align_safe_end: \c_zero #2 } -\cs_new:Npn \tl_act_group:nwnNNN #1 #2 \q_tl_act_stop #3#4#5 - { - #5 {#3} {#1} - \tl_act_loop:w #2 \q_tl_act_stop - {#3} #4 #5 - } -\exp_last_unbraced:NNo - \cs_new:Npn \tl_act_space:wwnNNN \c_space_tl #1 \q_tl_act_stop #2#3#4#5 - { - #5 {#2} - \tl_act_loop:w #1 \q_tl_act_stop - {#2} #3 #4 #5 - } -% \end{macrocode} -% Typically, the output is done to the right of what was already output, -% using \cs{tl_act_output:n}, but for the \cs{tl_act_reverse} functions, -% it should be done to the left. -% \begin{macrocode} -\cs_new:Npn \tl_act_output:n #1 #2 \tl_act_result:n #3 - { #2 \tl_act_result:n { #3 #1 } } -\cs_new:Npn \tl_act_reverse_output:n #1 #2 \tl_act_result:n #3 - { #2 \tl_act_result:n { #1 #3 } } -% \end{macrocode} -% In many applications of \cs{tl_act:NNNnn}, we need to recursively -% apply some transformation within brace groups, then output. In this -% code, |#1| is the output function, |#2| is the transformation, -% which should expand in two steps, and |#3| is the group. -% \begin{macrocode} -\cs_new:Npn \tl_act_group_recurse:Nnn #1#2#3 - { - \exp_args:Nf #1 - { \exp_after:wN \exp_after:wN \exp_after:wN { #2 {#3} } } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\tl_reverse_tokens:n} -% \begin{macro}[EXP,aux]{\tl_act_reverse_normal:nN, -% \tl_act_reverse_group:nn, \tl_act_reverse_space:n} -% The goal is to reverse a token list. This is done by feeding -% \cs{tl_act_aux:NNNnn} three functions, an empty fourth argument -% (we don't use it for \cs{tl_act_reverse_tokens:n}), and as -% a fifth argument the token list to be reversed. -% Spaces and normal tokens are output to the left of the current -% output. For groups, we must recursively apply -% \cs{tl_act_reverse_tokens:n} to the group, and output, still -% on the left. Note that in all three cases, we throw one argument -% away: this \meta{parameter} is where for instance the -% upper/lowercasing action stores the information of whether it -% is uppercasing or lowercasing. -% \begin{macrocode} -\cs_new:Npn \tl_reverse_tokens:n #1 - { - \etex_unexpanded:D \exp_after:wN - { - \tex_romannumeral:D - \tl_act_aux:NNNnn - \tl_act_reverse_normal:nN - \tl_act_reverse_group:nn - \tl_act_reverse_space:n - { } - {#1} - } - } -\cs_new:Npn \tl_act_reverse_space:n #1 - { \tl_act_reverse_output:n {~} } -\cs_new:Npn \tl_act_reverse_normal:nN #1 #2 - { \tl_act_reverse_output:n {#2} } -\cs_new:Npn \tl_act_reverse_group:nn #1 - { - \tl_act_group_recurse:Nnn - \tl_act_reverse_output:n - { \tl_reverse_tokens:n } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\tl_reverse:n,\tl_reverse:o,\tl_reverse:V} -% \begin{macro}[EXP,aux]{\tl_reverse_group_preserve:nn} -% The goal here is to reverse without losing spaces nor braces. -% The only difference with \cs{tl_reverse_tokens:n} is that -% we now simply output groups without entering them. -% \begin{macrocode} -\cs_new:Npn \tl_reverse:n #1 - { - \etex_unexpanded:D \exp_after:wN - { - \tex_romannumeral:D - \tl_act_aux:NNNnn - \tl_act_reverse_normal:nN - \tl_act_reverse_group_preserve:nn - \tl_act_reverse_space:n - { } - {#1} - } - } -\cs_new:Npn \tl_act_reverse_group_preserve:nn #1 #2 - { \tl_act_reverse_output:n { {#2} } } -\cs_generate_variant:Nn \tl_reverse:n { o , V } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\tl_reverse:N, \tl_reverse:c, \tl_greverse:N, \tl_greverse:c} -% This reverses the list, leaving \cs{exp_stop_f:} in front, -% which stops the \texttt{f}-expansion. -% \begin{macrocode} -\cs_new_protected:Npn \tl_reverse:N #1 - { \tl_set:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } } -\cs_new_protected:Npn \tl_greverse:N #1 - { \tl_gset:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } } -\cs_generate_variant:Nn \tl_reverse:N { c } -\cs_generate_variant:Nn \tl_greverse:N { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\tl_length_tokens:n} -% \begin{macro}[EXP,aux]{\tl_act_length_normal:nN, -% \tl_act_length_group:nn,\tl_act_length_space:n} -% The length is computed through an \cs{int_eval:n} construction. -% Each \texttt{1+} is output to the \emph{left}, into the integer -% expression, and the sum is ended by the \cs{c_zero} inserted by -% \cs{tl_act_end:wn}. Somewhat a hack. -% \begin{macrocode} -\cs_new:Npn \tl_length_tokens:n #1 - { - \int_eval:n - { - \tl_act_aux:NNNnn - \tl_act_length_normal:nN - \tl_act_length_group:nn - \tl_act_length_space:n - { } - {#1} - } - } -\cs_new:Npn \tl_act_length_normal:nN #1 #2 { 1 + } -\cs_new:Npn \tl_act_length_space:n #1 { 1 + } -\cs_new:Npn \tl_act_length_group:nn #1 #2 - { 2 + \tl_length_tokens:n {#2} + } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{variable}{\c_tl_act_uppercase_tl, \c_tl_act_lowercase_tl} -% These constants contain the correspondance between lowercase -% and uppercase letters, in the form |aAbBcC...| and |AaBbCc...| -% respectively. -% \begin{macrocode} -\tl_const:Nn \c_tl_act_uppercase_tl - { - aA bB cC dD eE fF gG hH iI jJ kK lL mM - nN oO pP qQ rR sS tT uU vV wW xX yY zZ - } -\tl_const:Nn \c_tl_act_lowercase_tl - { - Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm - Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz - } -% \end{macrocode} -% \end{variable} -% -% \begin{macro}[EXP]{\tl_expandable_uppercase:n,\tl_expandable_lowercase:n} -% \begin{macro}[EXP,aux]{\tl_act_case_normal:nN, -% \tl_act_case_group:nn,\tl_act_case_space:n} -% The only difference between uppercasing and lowercasing is -% the table of correspondance that is used. As for other -% token list actions, we feed \cs{tl_act_aux:NNNnn} three -% functions, and this time, we use the \meta{parameters} -% argument to carry which case-changing we are applying. -% A space is simply output. A normal token is compared -% to each letter in the alphabet using \cs{str_if_eq:nn} -% tests, and converted if necessary to upper/lowercase, -% before being output. For a group, we must perform the -% conversion within the group (the \cs{exp_after:wN} trigger -% \tn{romannumeral}, which expands fully to give the -% converted group), then output. -% \begin{macrocode} -\cs_new:Npn \tl_expandable_uppercase:n #1 - { - \etex_unexpanded:D \exp_after:wN - { - \tex_romannumeral:D - \tl_act_case_aux:nn { \c_tl_act_uppercase_tl } {#1} - } - } -\cs_new:Npn \tl_expandable_lowercase:n #1 - { - \etex_unexpanded:D \exp_after:wN - { - \tex_romannumeral:D - \tl_act_case_aux:nn { \c_tl_act_lowercase_tl } {#1} - } - } -\cs_new:Npn \tl_act_case_aux:nn - { - \tl_act_aux:NNNnn - \tl_act_case_normal:nN - \tl_act_case_group:nn - \tl_act_case_space:n - } -\cs_new:Npn \tl_act_case_space:n #1 { \tl_act_output:n {~} } -\cs_new:Npn \tl_act_case_normal:nN #1 #2 - { - \exp_args:Nf \tl_act_output:n - { - \exp_args:NNo \prg_case_str:nnn #2 {#1} - { \exp_stop_f: #2 } - } - } -\cs_new:Npn \tl_act_case_group:nn #1 #2 - { - \exp_after:wN \tl_act_output:n \exp_after:wN - { \exp_after:wN { \tex_romannumeral:D \tl_act_case_aux:nn {#1} {#2} } } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\tl_item:nn, \tl_item:Nn, \tl_item:cn} -% \begin{macro}[aux]{\tl_item_aux:nn} -% 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_tail_stop:n} terminates the loop, and returns -% nothing at all. -% \begin{macrocode} -\cs_new:Npn \tl_item:nn #1#2 - { - \exp_args:Nf \tl_item_aux:nn - { - \int_eval:n - { - \int_compare:nNnT {#2} < \c_zero - { \tl_length:n {#1} + } - #2 - } - } - #1 - \q_recursion_tail - \prg_break_point:n { } - } -\cs_new:Npn \tl_item_aux:nn #1#2 - { - \quark_if_recursion_tail_break:n {#2} - \int_compare:nNnTF {#1} = \c_zero - { \tl_map_break:n { \exp_not:n {#2} } } - { \exp_args:Nf \tl_item_aux:nn { \int_eval:n { #1 - 1 } } } - } -\cs_new_nopar:Npn \tl_item:Nn { \exp_args:No \tl_item:nn } -\cs_generate_variant:Nn \tl_item:Nn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[pTF]{\tl_if_empty:x} -% We can test expandably the emptyness of an expanded token list -% thanks to the primitive \tn{pdfstrcmp} which expands its argument: -% a token list is empty if and only if its string representation is -% empty. -% \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_empty:x #1 { p , T , F , TF } - { \str_if_eq_return:xx { } {#1} } -% \end{macrocode} -% \end{macro} -% % \subsection{Deprecated functions} % % \begin{macro}{\tl_new:Nn, \tl_new:cn, \tl_new:Nx} @@ -2751,11 +2593,11 @@ % Another renaming job. % \begin{macrocode} %<*deprecated> -\cs_new_eq:NN \tl_elt_count:n \tl_length:n -\cs_new_eq:NN \tl_elt_count:V \tl_length:V -\cs_new_eq:NN \tl_elt_count:o \tl_length:o -\cs_new_eq:NN \tl_elt_count:N \tl_length:N -\cs_new_eq:NN \tl_elt_count:c \tl_length:c +\cs_new_eq:NN \tl_elt_count:n \tl_count:n +\cs_new_eq:NN \tl_elt_count:V \tl_count:V +\cs_new_eq:NN \tl_elt_count:o \tl_count:o +\cs_new_eq:NN \tl_elt_count:N \tl_count:N +\cs_new_eq:NN \tl_elt_count:c \tl_count:c %</deprecated> % \end{macrocode} % \end{macro} @@ -2782,6 +2624,58 @@ % \end{macro} % \end{macro} % +% Deprecated on 2012-05-13 for removal by 2012-08-31. +% +% \begin{macro}{\tl_length_tokens:n} +% \begin{macrocode} +\cs_new_eq:NN \tl_length_tokens:n \tl_count_tokens:n +% \end{macrocode} +% \end{macro} +% +% Deprecated 2012-05-13 for removal by 2012-11-31. +% +% \begin{macro} +% {\tl_length:N, \tl_length:c, \tl_length:n, \tl_length:V, \tl_length:o} +% Renames. +% \begin{macrocode} +\cs_new_eq:NN \tl_length:N \tl_count:N +\cs_new_eq:NN \tl_length:c \tl_count:c +\cs_new_eq:NN \tl_length:n \tl_count:n +\cs_new_eq:NN \tl_length:V \tl_count:V +\cs_new_eq:NN \tl_length:o \tl_count:o +% \end{macrocode} +% \end{macro} +% +% Deprecated 2012-06-05 for removal after 2012-12-31. +% +% \begin{macro}[pTF]{\tl_if_empty:x} +% We can test expandably the emptiness of an expanded token list +% thanks to the primitive \tn{pdfstrcmp} which expands its argument: +% a token list is empty if and only if its string representation is +% empty. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_empty:x #1 { p , T , F , TF } + { \__str_if_eq_x_return:nn { } {#1} } +% \end{macrocode} +% \end{macro} +% +% Deprecated 2012-07-08 for removal after 2012-10-31. +% +% \begin{macro}[EXP, pTF]{\tl_if_head_group:n} +% \begin{macro}[EXP, pTF]{\tl_if_head_N_type:n} +% \begin{macro}[EXP, pTF]{\tl_if_head_space:n} +% \begin{macrocode} +\prg_new_eq_conditional:NNn \tl_if_head_group:n \tl_if_head_is_group:n + { p , T , F , TF } +\prg_new_eq_conditional:NNn \tl_if_head_N_type:n \tl_if_head_is_N_type:n + { p , T , F , TF } +\prg_new_eq_conditional:NNn \tl_if_head_space:n \tl_if_head_is_space:n + { p , T , F , TF } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} |