diff options
author | Karl Berry <karl@freefriends.org> | 2011-07-31 18:27:06 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-07-31 18:27:06 +0000 |
commit | dac945b204407dae96f70ec228206516093156d7 (patch) | |
tree | 02ca182689947e45dec95e17ba08b503c959bd17 /Master/texmf-dist/source/latex/l3kernel/l3tl.dtx | |
parent | c1840548792cfbc7c9f746da1d53d89b94406e72 (diff) |
l3kernel (5jun11)
git-svn-id: svn://tug.org/texlive/trunk@23282 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 | 2268 |
1 files changed, 2268 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx new file mode 100644 index 00000000000..a7f292d14c7 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -0,0 +1,2268 @@ +% \iffalse meta-comment +% +%% File: l3tl.dtx Copyright (C) 1990-2011 The 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 +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the "expl3 bundle" (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX3 Project. +%% +%% ----------------------------------------------------------------------- +% +%<*driver|package> +\RequirePackage{l3names} +\GetIdInfo$Id: l3tl.dtx 2498 2011-07-09 17:51:47Z joseph $ + {L3 Experimental token lists} +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \pkg{l3tl} package\\ Token lists^^A +% \thanks{This file describes v\ExplFileVersion, +% last revised \ExplFileDate.}^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released \ExplFileDate} +% +% \maketitle +% +% \begin{documentation} +% +% \LaTeX3 stores lists of token in variables also called \enquote{token lists}. +% Variables of this type get the suffix |tl| and functions of this type +% have the prefix |tl|. To use a token list variable you simply call +% the corresponding variable. +% +% Often you find yourself with not a token list variable but an +% arbitrary token list which has to undergo certain tests. We will \emph{also} +% prefix these functions with |tl|. While token list variables are +% always single tokens, token lists are always surrounded by +% braces. Many of the functions for token lists and token list variables +% are very similar, and so are grouped together here. +% +% \section{Creating and initialising token list variables} +% +% \begin{function}{\tl_new:N, \tl_new:c} +% \begin{syntax} +% \cs{tl_new:N} \meta{tl~var} +% \end{syntax} +% Creates a new \meta{tl~var} or raises an error if the +% name is already taken. The declaration is global. The +% \meta{tl~var} will initially be empty. +% \end{function} +% +% \begin{function}{\tl_const:Nn, \tl_const:Nx, \tl_const:cn, \tl_const:cx} +% \begin{syntax} +% \cs{tl_const:Nn} \meta{tl~var} \Arg{token list} +% \end{syntax} +% Creates a new constant \meta{tl~var} or raises an error +% if the name is already taken. The value of the +% \meta{tl~var} will be set globally to the +% \meta{token list}. +% \end{function} +% +% \begin{function}{\tl_clear:N, \tl_clear:c} +% \begin{syntax} +% \cs{tl_clear:N} \meta{tl~var} +% \end{syntax} +% Clears all entries from the \meta{tl~var} within the scope of +% the current \TeX{} group. +% \end{function} +% +% \begin{function}{\tl_gclear:N, \tl_gclear:c} +% \begin{syntax} +% \cs{tl_gclear:N} \meta{tl~var} +% \end{syntax} +% Clears all entries from the \meta{tl~var} globally. +% \end{function} +% +% \begin{function}{\tl_clear_new:N, \tl_clear_new:c} +% \begin{syntax} +% \cs{tl_clear_new:N} \meta{tl~var} +% \end{syntax} +% If the \meta{tl~var} already exists, clears it within the scope +% of the current \TeX{} group. If the \meta{tl~var} is not defined, +% it will be created (using \cs{tl_new:N}). Thus the sequence is +% guaranteed to be available and clear within the current \TeX{} +% group. The \meta{tl~var} will exist globally, but the content +% outside of the current \TeX{} group is not specified. +% \end{function} +% +% \begin{function}{\tl_gclear_new:N, \tl_gclear_new:c} +% \begin{syntax} +% \cs{tl_gclear_new:N} \meta{tl~var} +% \end{syntax} +% If the \meta{tl~var} already exists, clears it globally. If the +% \meta{tl~var} is not defined, it will be created (using +% \cs{tl_new:N}). Thus the sequence is guaranteed to be available +% and globally clear. +% \end{function} +% +% \begin{function}{\tl_set_eq:NN, \tl_set_eq:cN, \tl_set_eq:Nc, \tl_set_eq:cc} +% \begin{syntax} +% \cs{tl_set_eq:NN} \meta{tl~var1} \meta{tl~var2} +% \end{syntax} +% Sets the content of \meta{tl~var1} equal to that of +% \meta{tl~var2}. This assignment is restricted to the current +% \TeX{} group level. +% \end{function} +% +% \begin{function} +% {\tl_gset_eq:NN, \tl_gset_eq:cN, \tl_gset_eq:Nc, \tl_gset_eq:cc} +% \begin{syntax} +% \cs{tl_gset_eq:NN} \meta{tl~var1} \meta{tl~var2} +% \end{syntax} +% Sets the content of \meta{tl~var1} equal to that of +% \meta{tl~var2}. This assignment is global and so is not +% limited by the current \TeX{} group level. +% \end{function} +% +% \section{Adding data to token list variables} +% +% \begin{function} +% { +% \tl_set:Nn, \tl_set:NV, \tl_set:Nv, \tl_set:No, \tl_set:Nf, \tl_set:Nx, +% \tl_set:cn, \tl_set:NV, \tl_set:Nv, \tl_set:co, \tl_set:cf, \tl_set:cx +% } +% \begin{syntax} +% \cs{tl_set:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Sets \meta{tl~var} to contain \meta{tokens}, +% removing any previous content from the variable. This assignment +% is restricted to the current \TeX{} group. +% \end{function} +% +% \begin{function} +% { +% \tl_gset:Nn, \tl_gset:NV, \tl_gset:Nv, +% \tl_gset:No, \tl_gset:Nf, \tl_gset:Nx, +% \tl_gset:cn, \tl_gset:cV, \tl_gset:cv, +% \tl_gset:co, \tl_gset:cf, \tl_gset:cx +% } +% \begin{syntax} +% \cs{tl_gset:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Sets \meta{tl~var} to contain \meta{tokens}, +% removing any previous content from the variable. This assignment +% is global and is not limited to the current \TeX{} group level. +% \end{function} +% +% \begin{function} +% { +% \tl_put_left:Nn, \tl_put_left:NV, \tl_put_left:No, \tl_put_left:Nx, +% \tl_put_left:cn, \tl_put_left:cV, \tl_put_left:co, \tl_put_left:cx +% } +% \begin{syntax} +% \cs{tl_put_left:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Appends \meta{tokens} to the left side of the current content of +% \meta{tl~var}. This modification is restricted to the +% current \TeX{} group level. +% \end{function} +% +% \begin{function} +% { +% \tl_gput_left:Nn, \tl_gput_left:NV, \tl_gput_left:No, \tl_gput_left:Nx, +% \tl_gput_left:cn, \tl_gput_left:cV, \tl_gput_left:co, \tl_gput_left:cx +% } +% \begin{syntax} +% \cs{tl_gput_left:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Globally appends \meta{tokens} to the left side of the current +% content of \meta{tl~var}. This modification is not +% limited by \TeX{} grouping. +% \end{function} +% +% \begin{function} +% { +% \tl_put_right:Nn, \tl_put_right:NV, \tl_put_right:No, \tl_put_right:Nx, +% \tl_put_right:cn, \tl_put_right:cV, \tl_put_right:co, \tl_put_right:cx +% } +% \begin{syntax} +% \cs{tl_put_right:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Appends \meta{tokens} to the right side of the current content of +% \meta{tl~var}. This modification is restricted to the +% current \TeX{} group level. +% \end{function} +% +% \begin{function} +% { +% \tl_gput_right:Nn, \tl_gput_right:NV, \tl_gput_right:No, +% \tl_gput_right:Nx, +% \tl_gput_right:cn, \tl_gput_right:cV, \tl_gput_right:co, +% \tl_gput_right:cx +% } +% \begin{syntax} +% \cs{tl_gput_right:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Globally appends \meta{tokens} to the right side of the current +% content of \meta{tl~var}. This modification is not +% limited by \TeX{} grouping. +% \end{function} +% +% \section{Modifying token list variables} +% +% \begin{function}{\tl_replace_once:Nnn, \tl_replace_once:cnn} +% \begin{syntax} +% \cs{tl_replace_once:Nnn} \meta{tl~var} \Arg{old tokens} +% ~~\Arg{new tokens} +% \end{syntax} +% Replaces the first (leftmost) occurrence of \meta{old tokens} in the +% \meta{tl~var} with \meta{new tokens}. \meta{Old tokens} +% cannot contain |{|, |}| or |#| +% (assuming normal \TeX{} category codes). The assignment is +% restricted to the current \TeX{} group. +% \end{function} +% +% \begin{function}{\tl_greplace_once:Nnn, \tl_greplace_once:cnn} +% \begin{syntax} +% \cs{tl_greplace_once:Nnn} \meta{tl~var} \Arg{old tokens} +% ~~\Arg{new tokens} +% \end{syntax} +% Replaces the first (leftmost) occurrence of \meta{old tokens} in the +% \meta{tl~var} with \meta{new tokens}. \meta{Old tokens} +% cannot contain |{|, |}| or |#| +% (assuming normal \TeX{} category codes). The assignment is +% applied globally. +% \end{function} +% +% \begin{function}{\tl_replace_all:Nnn, \tl_replace_all:cnn} +% \begin{syntax} +% \cs{tl_replace_all:Nnn} \meta{tl~var} \Arg{old tokens} +% ~~\Arg{new tokens} +% \end{syntax} +% Replaces all occurrences of \meta{old tokens} in the +% \meta{tl~var} with \meta{new tokens}. \meta{Old tokens} +% cannot contain |{|, |}| or |#| +% (assuming normal \TeX{} category codes). The assignment is +% restricted to the current \TeX{} group. +% \end{function} +% +% \begin{function}{\tl_greplace_all:Nnn, \tl_greplace_all:cnn} +% \begin{syntax} +% \cs{tl_greplace_all:Nnn} \meta{tl~var} \Arg{old tokens} +% ~~\Arg{new tokens} +% \end{syntax} +% Replaces all occurrences of \meta{old tokens} in the +% \meta{tl~var} with \meta{new tokens}. \meta{Old tokens} +% cannot contain |{|, |}| or |#| +% (assuming normal \TeX{} category codes). The assignment is +% applied globally. +% \end{function} +% +% \begin{function}{\tl_remove_once:Nn, \tl_remove_once:cn} +% \begin{syntax} +% \cs{tl_remove_once:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Removes the first (leftmost) occurrence of \meta{tokens} from the +% \meta{tl~var}. \meta{Tokens} cannot contain |{|, |}| or +% |#| (assuming normal \TeX{} category codes). The assignment is +% restricted to the current \TeX{} group. +% \end{function} +% +% \begin{function}{\tl_gremove_once:Nn, \tl_gremove_once:cn} +% \begin{syntax} +% \cs{tl_gremove_once:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Removes the first (leftmost) occurrence of \meta{tokens} from the +% \meta{tl~var}. \meta{Tokens} cannot contain |{|, |}| or +% |#| (assuming normal \TeX{} category codes). The assignment is +% applied globally. +% \end{function} +% +% \begin{function}{\tl_remove_all:Nn, \tl_remove_all:cn} +% \begin{syntax} +% \cs{tl_remove_all:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Removes all occurrences of \meta{tokens} from the +% \meta{tl~var}. \meta{Tokens} cannot contain |{|, |}| or +% |#| (assuming normal \TeX{} category codes). The assignment is +% restricted to the current \TeX{} group. +% \end{function} +% +% \begin{function}{\tl_gremove_all:Nn, \tl_gremove_all:cn} +% \begin{syntax} +% \cs{tl_gremove_all:Nn} \meta{tl~var} \Arg{tokens} +% \end{syntax} +% Removes all occurrences of \meta{tokens} from the +% \meta{tl~var}. \meta{Tokens} cannot contain |{|, |}| or +% |#| (assuming normal \TeX{} category codes). The assignment is +% applied globally. +% \end{function} +% +% \section{Reassigning token list category codes} +% +% \begin{function} +% { +% \tl_set_rescan:Nnn, \tl_set_rescan:Nno, \tl_set_rescan:Nnx, +% \tl_set_rescan:cnn, \tl_set_rescan:cno, \tl_set_rescan:cnx, +% } +% \begin{syntax} +% \cs{tl_set_rescan:Nnn} \meta{tl~var} \Arg{setup} +% ~~\Arg{tokens} +% \end{syntax} +% Sets \meta{tl~var} to contain \meta{tokens}, +% applying the category code regim{\'e} specified in the +% \meta{setup} before carrying out the assignment. This allows the +% \meta{tl~var} to contain material with category codes +% other than those that apply when \meta{tokens} are absorbed. The +% assignment is local to the current \TeX{} group. See also +% \cs{tl_rescan:nn}. +% \end{function} +% +% \begin{function} +% { +% \tl_gset_rescan:Nnn, \tl_gset_rescan:Nno, \tl_gset_rescan:Nnx, +% \tl_gset_rescan:cnn, \tl_gset_rescan:cno, \tl_gset_rescan:cnx, +% } +% \begin{syntax} +% \cs{tl_gset_rescan:Nnn} \meta{tl~var} \Arg{setup} +% ~~\Arg{tokens} +% \end{syntax} +% Sets \meta{tl~var} to contain \meta{tokens}, +% applying the category code regim{\'e} specified in the +% \meta{setup} before carrying out the assignment. This allows the +% \meta{tl~var} to contain material with category codes +% other than those that apply when \meta{tokens} are absorbed. The +% assignment is global. See also \cs{tl_rescan:nn}. +% \end{function} +% +% \begin{function}{\tl_rescan:nn} +% \begin{syntax} +% \cs{tl_rescan:nn} \Arg{setup} \Arg{tokens} +% \end{syntax} +% Rescans \meta{tokens} applying the category code regim{\'e} specified +% in the \meta{setup}, and leaves the resulting tokens in the input +% stream. See also \cs{tl_set_rescan:Nnn}. +% \end{function} +% +% \section{Reassigning token list character codes} +% +% \begin{function}{\tl_to_lowercase:n} +% \begin{syntax} +% \cs{tl_to_lowercase:n} \Arg{tokens} +% \end{syntax} +% Works through all of the \meta{tokens}, replacing each character +% with the lower case equivalent as defined by \cs{char_set_lccode:nn}. +% Characters with no defined lower case character code are left +% unchanged. This process does not alter the category code assigned +% to the \meta{tokens}. +% \begin{texnote} +% This is the \TeX{} primitive \cs{lowercase} renamed. +% As a result, this function takes place on execution and +% not on expansion. +% \end{texnote} +% \end{function} +% +% \begin{function}{\tl_to_uppercase:n} +% \begin{syntax} +% \cs{tl_to_uppercase:n} \Arg{tokens} +% \end{syntax} +% Works through all of the \meta{tokens}, replacing each character +% with the upper case equivalent as defined by \cs{char_set_uccode:nn}. +% Characters with no defined lower case character code are left +% unchanged. This process does not alter the category code assigned +% to the \meta{tokens}. +% \begin{texnote} +% This is the \TeX{} primitive \cs{uppercase} renamed.. +% As a result, this function takes place on execution and +% not on expansion. +% \end{texnote} +% \end{function} +% +% \section{Token list conditionals} +% +% \begin{function}[EXP,pTF]{\tl_if_blank:n, \tl_if_blank:V, \tl_if_blank:o} +% \begin{syntax} +% \cs{tl_if_blank_p:n} \Arg{token list} +% \cs{tl_if_blank:nTF} \Arg{token list} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the \meta{token list} consists only of blank spaces. The +% test is \texttt{true} if \meta{token list} is empty or consists +% entirely of explicit tokens of character code $32$ +% and category code $10$, and is \texttt{false} +% otherwise. The branching versions then leave either \meta{true code} +% or \meta{false code} in the input stream, as appropriate to the +% truth of the test and the variant of the function chosen. The logical +% truth of the test is left in the input stream by the predicate +% version. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_empty:N, \tl_if_empty:c} +% \begin{syntax} +% \cs{tl_if_empty_p:N} \meta{tl var} +% \cs{tl_if_empty:NTF} \meta{tl var} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the \meta{token list variable} is entirely empty +% (\emph{i.e.}~contains no tokens at all). The branching versions then +% leave either \meta{true code} or \meta{false code} in the input +% stream, as appropriate to the truth of the test and the variant of +% the function chosen. The logical truth of the test is left in the +% input stream by the predicate version. +% \end{function} +% +% \begin{function}[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). The branching versions then +% leave either \meta{true code} or \meta{false code} in the input +% stream, as appropriate to the truth of the test and the variant of +% the function chosen. The logical truth of the test is left in the +% input stream by the predicate version. +% \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} +% \end{syntax} +% Compares the content of two \meta{token list variables} and +% is logically \texttt{true} if the two contain the same list of +% tokens (\emph{i.e.}~identical in both the list of characters they +% contain and the category codes of those characters). Thus for example +% \begin{verbatim} +% \tl_set:Nn \l_tmpa_tl { abc } +% \tl_set:Nx \l_tmpb_tl { \tl_to_str:n { abc } } +% \tl_if_eq_p:NN \l_tmpa_tl \l_tmpb_tl +% \end{verbatim} +% is logically \texttt{false}. The branching versions then leave either +% \meta{true code} or \meta{false code} in the input stream, as +% appropriate to the truth of the test and the variant of the function +% chosen. The logical truth of the test is left in the input stream by +% the predicate version. +% \end{function} +% +% \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} +% \end{syntax} +% Tests if \meta{token list1} and \meta{token list2} are equal, both in +% respect of character codes and category codes. Either the +% \meta{true code} or \meta{false code} in the input stream, as +% appropriate to the truth of the test and the variant of the function +% chosen. +% \end{function} +% +% \begin{function}[TF]{\tl_if_in:Nn, \tl_if_in:cn} +% \begin{syntax} +% \cs{tl_if_in:NnTF} \meta{tl~var} \Arg{token list} \Arg{true code} +% ~~\Arg{false code} +% \end{syntax} +% Tests if the \meta{token list} is found in the content of the +% \meta{token list variable}. The \meta{token list} cannot contain +% the tokens |{|, |}| or |#| (assuming the usual \TeX{} category +% codes apply). Either the \meta{true code} or \meta{false code} +% is left in the +% input stream, as appropriate to the truth of the test and the variant +% of the function chosen. +% \end{function} +% +% \begin{function}[TF] +% {\tl_if_in:nn, \tl_if_in:Vn, \tl_if_in:on, \tl_if_in:on} +% \begin{syntax} +% \cs{tl_if_in:nnTF} \meta{token list1} \Arg{token list2} \Arg{true code} +% ~~\Arg{false code} +% \end{syntax} +% Tests if the \meta{token list1} is found inside \meta{token list2}. +% The \meta{token list} cannot contain the tokens |{|, |}| or |#| +% (assuming the usual \TeX{} category codes apply). Either the +% \meta{true code} or \meta{false code} is left in the input stream, as +% appropriate to the truth of the test and the variant of the function +% chosen. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_single:N, \tl_if_single:c} +% \begin{syntax} +% \cs{tl_if_single_p:N} \Arg{tl~var} +% \cs{tl_if_single:nTF} \Arg{tl~var} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the content of the \meta{tl~var} consists of a +% single token or token group. The test is \texttt{true} if +% \meta{token list} contains exactly one token, if it consists +% entirely of explicit tokens of character code $32$ and category +% code $10$, or if it contains one braced token group (optionally +% preceeded by spaces), and it is \texttt{false} otherwise. The branching +% versions then leave either \meta{true code} or \meta{false code} +% in the input stream, as appropriate to the truth of the test and the +% variant of the function chosen. The logical truth of the test is left +% in the input stream by the predicate version. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_single:n} +% \begin{syntax} +% \cs{tl_if_single_p:n} \Arg{token list} +% \cs{tl_if_single:nTF} \Arg{token list} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the \meta{token list} consists of a single token +% or token group. The test is \texttt{true} if \meta{token list} +% contains exactly one token, or if it consists entirely of +% explicit tokens of character code $32$ and category code $10$, +% or if it contains a braced token group (optionally preceeded by blank +% spaces), and it is +% \texttt{false} otherwise. The branching versions then leave +% either \meta{true code} or \meta{false code} in the input stream, as +% appropriate to the truth of the test and the variant of the function +% chosen. The logical truth of the test is left in the input stream by +% the predicate version. +% \end{function} +% +% \section{Mapping to token lists} +% +% \begin{function}[EXP]{\tl_map_function:NN, \tl_map_function:cN} +% \begin{syntax} +% \cs{tl_map_function:NN} \meta{tl~var} \meta{function} +% \end{syntax} +% Applies \meta{function} to every \meta{token group} stored in the +% \meta{tl~var}. The \meta{function} +% will receive one argument for each iteration. This may be a number +% of tokens if the \meta{token group} was an item stored within +% braces. Hence the \meta{function} should anticipate receiving +% \texttt{n}-type arguments. See also \cs{tl_map_function:nN}. +% \end{function} +% +% \begin{function}[EXP]{\tl_map_function:nN} +% \begin{syntax} +% \cs{tl_map_function:nN} \meta{token list} \meta{function} +% \end{syntax} +% Applies \meta{function} to every \meta{token group} in the +% \meta{token list}. The \meta{function} +% will receive one argument for each iteration. This may be a number +% of tokens if the \meta{token group} was an item stored within +% braces. Hence the \meta{function} should anticipate receiving +% \texttt{n}-type arguments. See also \cs{tl_map_function:NN}. +% \end{function} +% +% \begin{function}{\tl_map_inline:Nn, \tl_map_inline:cn} +% \begin{syntax} +% \cs{tl_map_inline:Nn} \meta{tl~var} \Arg{inline function} +% \end{syntax} +% Applies the \meta{inline function} to every \meta{token group} stored +% within the \meta{tl~var}. The \meta{inline function} +% should consist of code which will receive the \meta{token group} as +% |#1|. One in line mapping can be nested inside another. See also +% \cs{tl_map_function:Nn}. +% \end{function} +% +% \begin{function}{\tl_map_inline:nn} +% \begin{syntax} +% \cs{tl_map_inline:nn} \meta{token list} \Arg{inline function} +% \end{syntax} +% Applies the \meta{inline function} to every \meta{token group} stored +% within the \meta{token list}. The \meta{inline function} should +% consist of code which will receive the \meta{token group} as +% |#1|. One in line mapping can be nested inside another. See also +% \cs{tl_map_function:nn}. +% \end{function} +% +% \begin{function}{\tl_map_variable:NNn, \tl_map_variable:cNn} +% \begin{syntax} +% \cs{tl_map_variable:NNn} \meta{tl~var} \meta{variable} \Arg{function} +% \end{syntax} +% Applies the \meta{function} to every \meta{token group} stored +% within the \meta{tl~var}. The \meta{function} should consist of code +% which will receive the \meta{token group} stored in the \meta{variable}. +% One variable mapping can be nested inside another. See also +% \cs{tl_map_inline:Nn}. +% \end{function} +% +% \begin{function}{\tl_map_variable:nNn} +% \begin{syntax} +% \cs{tl_map_variable:nNn} \meta{token list} \meta{variable} \Arg{function} +% \end{syntax} +% Applies the \meta{function} to every \meta{token group} stored +% within the \meta{token list}. The \meta{function} should consist of code +% which will receive the \meta{token group} stored in the \meta{variable}. +% One variable mapping can be nested inside another. See also +% \cs{tl_map_inline:nn}. +% \end{function} +% +% \begin{function}[EXP]{\tl_map_break:} +% \begin{syntax} +% \cs{tl_map_break:} +% \end{syntax} +% Used to terminate a \cs{tl_map_\ldots} function before all +% entries in the \meta{token list variable} have been processed. 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: } +% { +% % Do something useful +% } +% } +% \end{verbatim} +% Use outside of a \cs{tl_map_\ldots} scenario will lead low +% level \TeX{} errors. +% \end{function} +% +% \section{Using token lists} +% +% \begin{function}[EXP]{\tl_to_str:N, \tl_to_str:c} +% \begin{syntax} +% \cs{tl_to_str:N} \meta{tl~var} +% \end{syntax} +% Converts the content of the \meta{tl~var} into a series of characters +% with category code $12$ (other) with the exception of spaces, which +% retain category code $10$ (space). This \meta{string} is then left +% in the input stream. +% \end{function} +% +% \begin{function}[EXP]{\tl_to_str:n} +% \begin{syntax} +% \cs{tl_to_str:n} \Arg{tokens} +% \end{syntax} +% Converts the given \meta{tokens} into a series of characters with +% category code $12$ (other) with the exception of spaces, which +% retain category code $10$ (space). This \meta{string} is then left +% in the input stream. Note that this function requires only a single +% expansion. +% \begin{texnote} +% This is the \eTeX{} primitive \cs{detokenize}. +% \end{texnote} +% \end{function} +% +% \begin{function}[EXP]{\tl_use:N, \tl_use:c} +% \begin{syntax} +% \cs{tl_use:N} \meta{tl~var} +% \end{syntax} +% Recovers the content of a \meta{tl~var} and places it +% directly in the input stream. An error will be raised if the variable +% does not exist or if it is invalid. Note that it is possible to use +% a \meta{tl~var} directly without an accessor function. +% \end{function} +% +% \section{Working with the content of token lists} +% +% \begin{function}[EXP]{\tl_length:n, \tl_length:V, \tl_length:o} +% \begin{syntax} +% \cs{tl_length:n} \Arg{tokens} +% \end{syntax} +% Counts the number of token groups 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, +% giving an \meta{integer denotation}. +% \end{function} +% +% \begin{function}[EXP]{\tl_length:N, \tl_length:c} +% \begin{syntax} +% \cs{tl_length: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, +% giving an \meta{integer denotation}. +% \end{function} +% +% \begin{function}[EXP]{\tl_reverse:n, \tl_reverse:V, \tl_reverse:o} +% \begin{syntax} +% \cs{tl_reverse:n} \Arg{tokens} +% \end{syntax} +% Reverses the order of the \meta{tokens}, so that +% \meta{token1}\meta{token2}\meta{token3} \ldots \meta{token$_n$} +% becomes \meta{token$_n$}\ldots +% \meta{token3}\meta{token2}\meta{token1}. This process will remove +% any unprotected space within the \meta{tokens}. Tokens are not reversed +% within braced token groups, which lose their outer set of braces. +% See also \cs{tl_reverse:N}. +% \end{function} +% +% \begin{function}{\tl_reverse:N, \tl_reverse:c} +% \begin{syntax} +% \cs{tl_reverse:N} \Arg{tl~var} +% \end{syntax} +% Reverses the order of the \meta{tokens} stored in +% \meta{tl~var}, so that +% \meta{token1}\meta{token2}\meta{token3} \ldots \meta{token$_n$} +% becomes \meta{token$_n$}\ldots +% \meta{token3}\meta{token2}\meta{token1}. This process will +% remove any unprotected spaces within the +% \meta{token list variable}. Braced token groups are copied without +% reversing the order of tokens, and the outer set of braces is removed. +% The reversal is local to the current +% \TeX{} group. See also \cs{tl_reverse:n}. +% \end{function} +% +% \begin{function}[EXP]{\tl_trim_spaces:n} +% \begin{syntax} +% \cs{tl_trim_spaces:n} \meta{token list} +% \end{syntax} +% Removes any leading and trailing spaces from the \meta{token list} +% and leaves the result in the input stream. This process requires +% two expansions. +% \end{function} +% +% \begin{function}{\tl_trim_spaces:N, \tl_trim_spaces:c} +% \begin{syntax} +% \cs{tl_trim_spaces:N} \meta{tl~var} +% \end{syntax} +% Removes any leading and trailing spaces from the content of the +% \meta{tl~var} within the current \TeX{} group. +% \end{function} +% +% \begin{function}{\tl_gtrim_spaces:N, \tl_gtrim_spaces:c} +% \begin{syntax} +% \cs{tl_gtrim_spaces:N} \meta{tl~var} +% \end{syntax} +% Removes any leading and trailing spaces from the content of the +% \meta{tl~var} globally. +% \end{function} +% +% \section{The first token from a token list} +% +% Functions which deal with either onlt the very first token of a +% token list or everything except the first token. +% +% \begin{function}[EXP]{\tl_head:n, \tl_head:V, \tl_head:v, \tl_head:f} +% \begin{syntax} +% \cs{tl_head:n} \Arg{tokens} +% \end{syntax} +% Leaves only the first \meta{token} in \meta{tokens} in the input +% stream, discarding the remainder. +% \end{function} +% +% \begin{function}[EXP]{\tl_head:w} +% \begin{syntax} +% \cs{tl_head:w} \Arg{tokens} \cs{q_stop} +% \end{syntax} +% Leaves only the first \meta{token} in \meta{tokens} in the input +% stream, discarding the remainder. This function requires only a +% single expansion, and so is suitable for use inside an +% \texttt{o}-type expansion. In general \cs{tl_head:n} should be +% preferred. +% \end{function} +% +% \begin{function}[EXP]{\tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f} +% \begin{syntax} +% \cs{tl_tail:n} \Arg{tokens} +% \end{syntax} +% Discards the first \meta{token} of the \meta{tokens} and leaves the +% remainder in the input stream. +% \end{function} +% +% \begin{function}[EXP]{\tl_tail:w} +% \begin{syntax} +% \cs{tl_tail:w} \Arg{tokens} \cs{q_stop} +% \end{syntax} +% Discards the first \meta{token} of the \meta{tokens} and leaves the +% remainder in the input stream. This function requires only a +% single expansion, and so is suitable for use inside an +% \texttt{o}-type expansion. In general \cs{tl_tail:n} should be +% preferred. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_head_eq_catcode:nN} +% \begin{syntax} +% \cs{tl_if_head_eq_catcode_p:n} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_catcode:nTF} \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}. The branching versions then +% leave either \meta{true code} or \meta{false code} in the input +% stream, as appropriate to the truth of the test and the variant of +% the function chosen. The logical truth of the test is left in the +% input stream by the predicate +% version. +% \end{function} +% +% \begin{function}[EXP,pTF] +% {\tl_if_head_eq_charcode:nN, \tl_if_head_eq_charcode:fN} +% \begin{syntax} +% \cs{tl_if_head_eq_charcode_p:n} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_charcode:nTF} \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}. The branching versions then +% leave either \meta{true code} or \meta{false code} in the input +% stream, as appropriate to the truth of the test and the variant of +% the function chosen. The logical truth of the test is left in the +% input stream by the predicate +% version. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_head_eq_meaning:nN} +% \begin{syntax} +% \cs{tl_if_head_eq_meaning_p:n} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_meaning:nTF} \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}. The branching versions then +% leave either \meta{true code} or \meta{false code} in the input +% stream, as appropriate to the truth of the test and the variant of +% the function chosen. The logical truth of the test is left in the +% input stream by the predicate +% version. +% \end{function} +% +% \section{Viewing token lists} +% +% \begin{function}{\tl_show:N, \tl_show:c} +% \begin{syntax} +% \cs{tl_show:N} \meta{tl~var} +% \end{syntax} +% Displays the content of the \meta{tl~var} on the terminal. +% \begin{texnote} +% \cs{tl_show:N} is the \TeX{} primitive \cs{show}. +% \end{texnote} +% \end{function} +% +% \begin{function}{\tl_show:n} +% \begin{syntax} +% \cs{tl_show:n} \meta{token list} +% \end{syntax} +% Displays the \meta{token list} on the terminal. +% \begin{texnote} +% \cs{tl_show:n} is the \eTeX{} primitive \cs{showtokens}. +% \end{texnote} +% \end{function} +% +% \section{Constant token lists} +% +% \begin{variable}{\c_job_name_tl} +% Constant that gets the \enquote{job name} assigned when \TeX{} starts. +% \begin{texnote} +% This is the new name for the primitive \cs{jobname}. It is a constant +% that is set by \TeX{} and should not be overwritten by the package. +% \end{texnote} +% \end{variable} +% +% \begin{variable}{\c_empty_tl} +% Constant that is always empty. +% \end{variable} +% +% \begin{variable}{\c_space_tl} +% A space token contained in a token list (compare this with +% \cs{c_space_token}). For use where an explicit space is required. +% \end{variable} +% +% \section{Scratch token lists} +% +% \begin{variable}{\l_tmpa_tl, \l_tmpb_tl} +% Scratch token lists for local assignment. These are never used by +% the kernel code, and so are safe for use with any \LaTeX3-defined +% function. However, they may be overwritten by other non-kernel +% code and so should only be used for short-term storage. +% \end{variable} +% +% \begin{variable}{\g_tmpa_tl, \g_tmpb_tl} +% Scratch token lists for global assignment. These are never used by +% the kernel code, and so are safe for use with any \LaTeX3-defined +% function. However, they may be overwritten by other non-kernel +% code and so should only be used for short-term storage. +% \end{variable} +% +% \section{Experimental token list functions} +% +% \begin{function}[EXP,pTF]{\tl_if_single_item:n} +% \begin{syntax} +% \cs{tl_if_single_item_p:n} \Arg{token list} +% \cs{tl_if_single_item:nTF} \Arg{token list} +% ~~\Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the token list has exactly one item, 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}. The branching +% versions then leave either \meta{true code} or \meta{false code} +% in the input stream, as appropriate to the truth of the test and +% the variant of the function chosen. The logical truth of the test +% is left in the input stream by the predicate. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_head_begin_group:n} +% \begin{syntax} +% \cs{tl_if_head_begin_group_p:n} \Arg{token list} +% \cs{tl_if_head_begin_group:nTF} \Arg{token list} +% ~~\Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the first \meta{token} in the \meta{token list} +% has catcode~1, i.e., is a begin-group character. This conditional +% is mainly intended to be used in combination with +% \cs{tl_if_head_eq_space:n} to check if grabbing an undelimited +% argument from the token list is safe. The branching +% versions leave either \meta{true code} or \meta{false code} +% in the input stream, as appropriate to the truth of the test and +% the variant of the function chosen. The logical truth of the test +% is left in the input stream by the predicate. +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_head_eq_space:n} +% \begin{syntax} +% \cs{tl_if_head_eq_space_p:n} \Arg{token list} +% \cs{tl_if_head_eq_space:nTF} \Arg{token list} +% ~~\Arg{true code} \Arg{false code} +% \end{syntax} +%^^A Needs rewriting. We need to add a discussion of +%^^A explicit vs implicit tokens somewhere in the doc. +% Tests if the first token of the token list is an explicit space, +% i.e., a token which matches \verb*+ + both in character code and +% in category code. In the case of an implicit space token, such as +% \cs{c_space_token}, the test will return \meta{false}. +% This conditional is mainly intended to be used in combination with +% \cs{tl_if_head_begin_group:n} to test if grabbing an undelimited +% argument is safe (see \cs{tl_if_single_token:n} for an example. +% The branching versions leave either \meta{true code} or +% \meta{false code} in the input stream, as appropriate to the truth +% of the test and the variant of the function chosen. The logical +% truth of the test is left in the input stream by the predicate. +% \begin{texnote} +% When \TeX{}'s reads a character of category code $10$ for the +% first time, it is converted to an explicit space token, with +% character code $32$, regardless of the initial character code. +% ``Funny'' spaces with a different category code, can be produced +% using \cs{tex_lowercase:D}. Explicit spaces are also produced +% as a result of \cs{token_to_str:N}, \cs{tl_to_str:n}, etc. +% \end{texnote} +% \end{function} +% +% \begin{function}[EXP,pTF]{\tl_if_single_token:n} +% \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} +% \end{syntax} +% Tests if the token list consists of exactly one token, i.e., +% is either a single space character or a single ``normal'' token. +% Token groups are not single tokens. The branching +% versions leaves either \meta{true code} or \meta{false code} +% in the input stream, as appropriate to the truth of the test and +% the variant of the function chosen. The logical truth of the test +% is left in the input stream by the predicate. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3tl} implementation} +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\package_check_loaded_expl: +%</package> +% \end{macrocode} +% +% A token list variable is a \TeX{} macro that holds tokens. By using the +% \eTeX{} primitive \cs{unexpanded} inside a \TeX{} \cs{edef} it is +% possible to store any tokens, including |#|, in this way. +% +% \subsection{Functions} +% +% \begin{macro}{\tl_new:N, \tl_new:c} +% Creating new token list variables is a case of checking for an +% existing definition and if free doing the definition. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_new:N #1 + { + \chk_if_free_cs:N #1 + \cs_gset_eq:NN #1 \c_empty_tl + } +\cs_generate_variant:Nn \tl_new:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_const:Nn, \tl_const:Nx, \tl_const:cn, \tl_const:cx} +% Constants are also easy to generate. +% \begin{macrocode} +\cs_new_protected:Npn \tl_const:Nn #1#2 + { + \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 + \cs_gset_nopar:Npx #1 {#2} + } +\cs_generate_variant:Nn \tl_const:Nn { c } +\cs_generate_variant:Nn \tl_const:Nx { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_clear:N, \tl_clear:c} +% \begin{macro}{\tl_gclear:N, \tl_gclear:c} +% Clearing a token list variable means setting it to an empty value. +% Error checking will be sorted out by the parent function. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_clear:N #1 + { \tl_set_eq:NN #1 \c_empty_tl } +\cs_new_protected_nopar:Npn \tl_gclear:N #1 + { \tl_gset_eq:NN #1 \c_empty_tl } +\cs_generate_variant:Nn \tl_clear:N { c } +\cs_generate_variant:Nn \tl_gclear:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_clear_new:N, \tl_clear_new:c} +% \begin{macro}{\tl_gclear_new:N, \tl_gclear_new:c} +% Clearing a token list variable means setting it to an empty value. +% Error checking will be sorted out by the parent function. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_clear_new:N #1 + { \cs_if_exist:NTF #1 { \tl_clear:N #1 } { \tl_new:N #1 } } +\cs_new_protected_nopar:Npn \tl_gclear_new:N #1 + { \cs_if_exist:NTF #1 { \tl_gclear:N #1 } { \tl_new:N #1 } } +\cs_generate_variant:Nn \tl_clear_new:N { c } +\cs_generate_variant:Nn \tl_gclear_new:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_set_eq:NN, \tl_set_eq:Nc, \tl_set_eq:cN, \tl_set_eq:cc} +% \begin{macro}{\tl_gset_eq:NN, \tl_gset_eq:Nc, \tl_gset_eq:cN, \tl_gset_eq:cc} +% For setting token list variables equal to each other. +% \begin{macrocode} +\cs_new_eq:NN \tl_set_eq:NN \cs_set_eq:NN +\cs_new_eq:NN \tl_set_eq:cN \cs_set_eq:cN +\cs_new_eq:NN \tl_set_eq:Nc \cs_set_eq:Nc +\cs_new_eq:NN \tl_set_eq:cc \cs_set_eq:cc +\cs_new_eq:NN \tl_gset_eq:NN \cs_gset_eq:NN +\cs_new_eq:NN \tl_gset_eq:cN \cs_gset_eq:cN +\cs_new_eq:NN \tl_gset_eq:Nc \cs_gset_eq:Nc +\cs_new_eq:NN \tl_gset_eq:cc \cs_gset_eq:cc +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Adding to token list variables} +% +% \begin{macro} +% { +% \tl_set:Nn, \tl_set:NV, \tl_set:Nv, \tl_set:No, \tl_set:Nf, \tl_set:Nx, +% \tl_set:cn, \tl_set:NV, \tl_set:Nv, \tl_set:co, \tl_set:cf, \tl_set:cx +% } +% \begin{macro} +% { +% \tl_gset:Nn, \tl_gset:NV, \tl_gset:Nv, +% \tl_gset:No, \tl_gset:Nf, \tl_gset:Nx, +% \tl_gset:cn, \tl_gset:NV, \tl_gset:Nv, +% \tl_gset:co, \tl_gset:cf, \tl_gset:cx +% } +% By using \cs{exp_not:n} token list variables can contain |#| tokens, +% which makes the token list registers provided by \TeX{} +% more or less redundant. The \cs{tl_set:No} version is done +% \enquote{by hand} as it is used quite a lot. +% \begin{macrocode} +\cs_new_protected:Npn \tl_set:Nn #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:n {#2} } } +\cs_new_protected:Npn \tl_set:No #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:o {#2} } } +\cs_new_protected:Npn \tl_set:Nx #1#2 + { \cs_set_nopar:Npx #1 {#2} } +\cs_new_protected:Npn \tl_gset:Nn #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:n {#2} } } +\cs_new_protected:Npn \tl_gset:No #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:o {#2} } } +\cs_new_protected:Npn \tl_gset:Nx #1#2 + { \cs_gset_nopar:Npx #1 {#2} } +\cs_generate_variant:Nn \tl_set:Nn { NV , Nv , Nf } +\cs_generate_variant:Nn \tl_set:Nx { c } +\cs_generate_variant:Nn \tl_set:Nn { c, co , cV , cv , cf } +\cs_generate_variant:Nn \tl_gset:Nn { NV , Nv , Nf } +\cs_generate_variant:Nn \tl_gset:Nx { c } +\cs_generate_variant:Nn \tl_gset:Nn { c, co , cV , cv , cf } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \tl_put_left:Nn, \tl_put_left:NV, \tl_put_left:No, \tl_put_left:Nx, +% \tl_put_left:cn, \tl_put_left:cV, \tl_put_left:co, \tl_put_left:cx +% } +% \begin{macro} +% { +% \tl_gput_left:Nn, \tl_gput_left:NV, \tl_gput_left:No, \tl_gput_left:Nx, +% \tl_gput_left:cn, \tl_gput_left:cV, \tl_gput_left:co, \tl_gput_left:cx +% } +% Adding to the left is done directly to gain a little performance. +% \begin{macrocode} +\cs_new_protected:Npn \tl_put_left:Nn #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:n {#2} \exp_not:o #1 } } +\cs_new_protected:Npn \tl_put_left:NV #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:V #2 \exp_not:o #1 } } +\cs_new_protected:Npn \tl_put_left:No #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:o {#2} \exp_not:o #1 } } +\cs_new_protected:Npn \tl_put_left:Nx #1#2 + { \cs_set_nopar:Npx #1 { #2 \exp_not:o #1 } } +\cs_new_protected:Npn \tl_gput_left:Nn #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:n {#2} \exp_not:o #1 } } +\cs_new_protected:Npn \tl_gput_left:NV #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:V #2 \exp_not:o #1 } } +\cs_new_protected:Npn \tl_gput_left:No #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:o {#2} \exp_not:o #1 } } +\cs_new_protected:Npn \tl_gput_left:Nx #1#2 + { \cs_gset_nopar:Npx #1 { #2 \exp_not:o {#1} } } +\cs_generate_variant:Nn \tl_put_left:Nn { c } +\cs_generate_variant:Nn \tl_put_left:NV { c } +\cs_generate_variant:Nn \tl_put_left:No { c } +\cs_generate_variant:Nn \tl_put_left:Nx { c } +\cs_generate_variant:Nn \tl_gput_left:Nn { c } +\cs_generate_variant:Nn \tl_gput_left:NV { c } +\cs_generate_variant:Nn \tl_gput_left:No { c } +\cs_generate_variant:Nn \tl_gput_left:Nx { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \tl_put_right:Nn, \tl_put_right:NV, \tl_put_right:No, \tl_put_right:Nx, +% \tl_put_right:cn, \tl_put_right:cV, \tl_put_right:co, \tl_put_right:cx +% } +% \begin{macro} +% { +% \tl_gput_right:Nn, \tl_gput_right:NV, \tl_gput_right:No, +% \tl_gput_right:Nx, +% \tl_gput_right:cn, \tl_gput_right:cV, \tl_gput_right:co, +% \tl_gput_right:cx +% } +% The same on the right. +% \begin{macrocode} +\cs_new_protected:Npn \tl_put_right:Nn #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:o #1 \exp_not:n {#2} } } +\cs_new_protected:Npn \tl_put_right:NV #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:o #1 \exp_not:V #2 } } +\cs_new_protected:Npn \tl_put_right:No #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:o #1 \exp_not:o {#2} } } +\cs_new_protected:Npn \tl_put_right:Nx #1#2 + { \cs_set_nopar:Npx #1 { \exp_not:o #1 #2 } } +\cs_new_protected:Npn \tl_gput_right:Nn #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:o #1 \exp_not:n {#2} } } +\cs_new_protected:Npn \tl_gput_right:NV #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:o #1 \exp_not:V #2 } } +\cs_new_protected:Npn \tl_gput_right:No #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:o #1 \exp_not:o {#2} } } +\cs_new_protected:Npn \tl_gput_right:Nx #1#2 + { \cs_gset_nopar:Npx #1 { \exp_not:o {#1} #2 } } +\cs_generate_variant:Nn \tl_put_right:Nn { c } +\cs_generate_variant:Nn \tl_put_right:NV { c } +\cs_generate_variant:Nn \tl_put_right:No { c } +\cs_generate_variant:Nn \tl_put_right:Nx { c } +\cs_generate_variant:Nn \tl_gput_right:Nn { c } +\cs_generate_variant:Nn \tl_gput_right:NV { c } +\cs_generate_variant:Nn \tl_gput_right:No { c } +\cs_generate_variant:Nn \tl_gput_right:Nx { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Reassigning token list category codes} +% +% \begin{variable}{\c_tl_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. +% \begin{macrocode} +\group_begin: + \tex_lccode:D `\A = `\@ \scan_stop: + \tex_lccode:D `\B = `\@ \scan_stop: + \tex_catcode:D `\A = 8 \scan_stop: + \tex_catcode:D `\B = 3 \scan_stop: +\tex_lowercase:D + { + \group_end: + \tl_const:Nn \c_tl_rescan_marker_tl { A B } + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_tl_rescan_tl} +% A token list variable to actually store the material being processed. +% \begin{macrocode} +\tl_new:N \l_tl_rescan_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \tl_set_rescan:Nnn, \tl_set_rescan:Nno, +% \tl_set_rescan:cnn, \tl_set_rescan:cno +% } +% \begin{macro} +% { +% \tl_gset_rescan:Nnn, \tl_gset_rescan:Nno, +% \tl_gset_rescan:cnn, \tl_gset_rescan:cno +% } +% \begin{macro}[aux]{\tl_set_rescan_aux:NNnn} +% \begin{macro}[aux]{\tl_rescan_aux:w} +% The idea here is to deal cleanly with the problem that +% \cs{tex_scantokens:D} treats the argument as a file, and without +% the correct settings a \TeX{} error occurs: +% \begin{verbatim} +% ! File ended while scanning definition of ... +% \end{verbatim} +% When expanding a token list this can be handled using \cs{exp_not:N} +% but this fails if the token list is not being expanded. So instead +% a delimited argument is used with an end marker which cannot appear +% within the token list which is scanned: two |@| symbols with different +% category codes. The rescanned token list cannot contain the end marker, +% because all |@| present in the token list are read with the same category +% code. The setting of \cs{tex_endlinechar:D} +% is needed to avoid introducing an extraneous space in the result. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_set_rescan:Nnn + { \tl_set_rescan_aux:NNnn \tl_set:Nn } +\cs_new_protected_nopar:Npn \tl_gset_rescan:Nnn + { \tl_set_rescan_aux:NNnn \tl_gset:Nn } +\cs_new_protected:Npn \tl_set_rescan_aux:NNnn #1#2#3#4 + { + \group_begin: + \exp_args:No \etex_everyeof:D { \c_tl_rescan_marker_tl } + \tex_endlinechar:D \c_minus_one + #3 + \tl_clear:N \l_tl_rescan_tl + \exp_after:wN \tl_rescan_aux:w \etex_scantokens:D {#4} + \exp_args:NNNo \group_end: + #1 #2 \l_tl_rescan_tl + } +\cs_new_nopar:Npx \tl_rescan_aux:w + { + \cs_set_protected:Npn \exp_not:N \tl_rescan_aux:w ##1 + \c_tl_rescan_marker_tl + { \tl_set:Nn \exp_not:N \l_tl_rescan_tl {##1} } + } +\tl_rescan_aux:w +\cs_generate_variant:Nn \tl_set_rescan:Nnn { Nno } +\cs_generate_variant:Nn \tl_set_rescan:Nnn { c , cno } +\cs_generate_variant:Nn \tl_gset_rescan:Nnn { Nno } +\cs_generate_variant:Nn \tl_gset_rescan:Nnn { c , cno } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_set_rescan:Nnx, \tl_set_rescan:cnx} +% \begin{macro}{\tl_gset_rescan:Nnx, \tl_gset_rescan:cnx} +% \begin{macro}[aux]{\tl_set_rescan_aux:NNnx} +% With \texttt{x}-type expansion the \cs{tex_everyoef:D} method +% does apply and the code is simple. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_set_rescan:Nnx + { \tl_set_rescan_aux:NNnx \tl_set:Nn } +\cs_new_protected_nopar:Npn \tl_gset_rescan:Nnx + { \tl_set_rescan_aux:NNnx \tl_gset:Nn } +\cs_new_protected_nopar:Npn \tl_set_rescan_aux:NNnx #1#2#3#4 + { + \group_begin: + \etex_everyeof:D { \exp_not:N } + \tex_endlinechar:D \c_minus_one + #3 + \tl_set:Nx \l_tl_rescan_tl { \etex_scantokens:D {#4} } + \exp_args:NNNo \group_end: + #1 #2 \l_tl_rescan_tl + } +\cs_generate_variant:Nn \tl_set_rescan:Nnx { c } +\cs_generate_variant:Nn \tl_gset_rescan:Nnx { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_rescan:nn} +% The same idea is also applied to in line token lists. +% \begin{macrocode} +\cs_new_protected:Npn \tl_rescan:nn #1#2 + { + \group_begin: + \exp_args:No \etex_everyeof:D { \c_tl_rescan_marker_tl } + \tex_endlinechar:D \c_minus_one + #1 + \exp_after:wN \tl_rescan_aux:w \etex_scantokens:D {#2} + \exp_args:No \group_end: + \l_tl_rescan_tl + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Reassigning token list character codes} +% +% \begin{macro}{\tl_to_lowercase:n} +% \begin{macro}{\tl_to_uppercase:n} +% Just some names for a few primitives. +% \begin{macrocode} +\cs_new_eq:NN \tl_to_lowercase:n \tex_lowercase:D +\cs_new_eq:NN \tl_to_uppercase:n \tex_uppercase:D +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Modifying token list variables} +% +% \begin{variable}{\l_tl_replace_tl} +% A scratch variable for doing token replacement. +% \begin{macrocode} +\tl_new:N \l_tl_replace_tl +% \end{macrocode} +% \end{variable} +% +% \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_once_aux:NNnn} +% The concept here is that only the first occurrence should be +% replaced. The first step is to define an auxiliary which will +% match the appropriate item, with a trailing marker. If the last token +% is the marker there is nothing to do, otherwise replace the token +% and clean up (hence the second use of \cs{tl_tmp:w}). To prevent +% loosing braces or spaces there are a couple of empty groups and +% the strange-looking \cs{use:n}. There is a \cs{q_nil} between the +% original and the search input, to prevent cases where +% the end of the original and the start of the search run together +% to give an erroneous test result. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_replace_once:Nnn + { \tl_replace_once_aux:NNnn \tl_set_eq:NN } +\cs_new_protected_nopar:Npn \tl_greplace_once:Nnn + { \tl_replace_once_aux:NNnn \tl_gset_eq:NN } +\cs_new_protected:Npn \tl_replace_once_aux:NNnn #1#2#3#4 + { + \cs_set_protected:Npx \tl_tmp:w ##1 #3 ##2 \q_stop + { + \exp_not:N \quark_if_no_value:nF {##2} + { + \tl_set:No \exp_not:N \l_tl_replace_tl { ##1 \exp_not:n{#4} } + \exp_not:n + { + \cs_set_protected:Npn \tl_tmp:w ##1 \q_nil #3 \q_no_value + { \tl_put_right:No \l_tl_replace_tl {##1} } + } + \exp_not:n { \tl_tmp:w \prg_do_nothing: } ##2 + \exp_not:n { #1 #2 \l_tl_replace_tl } + } + } + \exp_after:wN \tl_tmp:w \exp_after:wN \prg_do_nothing: + #2 \q_nil #3 \q_no_value \q_stop + } +\cs_generate_variant:Nn \tl_replace_once:Nnn { c } +\cs_generate_variant:Nn \tl_greplace_once:Nnn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_replace_all:Nnn, \tl_replace_all:cnn} +% \begin{macro}{\tl_greplace_all:Nnn, \tl_greplace_all:cnn} +% \begin{macro}[aux]{\tl_replace_all_aux:NNnn} +% A similar approach here but with a loop built in. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_replace_all:Nnn + { \tl_replace_all_aux:NNnn \tl_set_eq:NN } +\cs_new_protected_nopar:Npn \tl_greplace_all:Nnn + { \tl_replace_all_aux:NNnn \tl_gset_eq:NN } +\cs_new_protected:Npn \tl_replace_all_aux:NNnn #1#2#3#4 + { + \tl_clear:N \l_tl_replace_tl + \cs_set_protected:Npx \tl_tmp:w ##1 #3 ##2 \q_stop + { + \exp_not:N \quark_if_no_value:nTF {##2} + { + \exp_not:n + { + \cs_set_protected:Npn \tl_tmp:w ##1 \q_nil ##2 \q_stop + { \tl_put_right:No \l_tl_replace_tl {##1} } + } + \exp_not:N \tl_tmp:w ##1 \exp_not:N \q_stop + } + { + \exp_not:n { \tl_put_right:No \l_tl_replace_tl } + { ##1 \exp_not:n{#4} } + \exp_not:n { \tl_tmp:w \prg_do_nothing: } ##2 \exp_not:N \q_stop + } + } + \exp_after:wN \tl_tmp:w \exp_after:wN \prg_do_nothing: + #2 \q_nil #3 \q_no_value \q_stop + #1 #2 \l_tl_replace_tl + } +\cs_generate_variant:Nn \tl_replace_all:Nnn { c } +\cs_generate_variant:Nn \tl_greplace_all:Nnn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_remove_once:Nn, \tl_remove_once:cn} +% \begin{macro}{\tl_gremove_once:Nn, \tl_gremove_once:cn} +% Removal is just a special case of replacement. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_remove_once:Nn #1#2 + { \tl_replace_once:Nnn #1 {#2} { } } +\cs_new_protected_nopar:Npn \tl_gremove_once:Nn #1#2 + { \tl_greplace_once:Nnn #1 {#2} { } } +\cs_generate_variant:Nn \tl_remove_once:Nn { c } +\cs_generate_variant:Nn \tl_gremove_once:Nn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_remove_all:Nn, \tl_remove_all:cn} +% \begin{macro}{\tl_gremove_all:Nn, \tl_gremove_all:cn} +% Removal is just a special case of replacement. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_remove_all:Nn #1#2 + { \tl_replace_all:Nnn #1 {#2} { } } +\cs_new_protected_nopar:Npn \tl_gremove_all:Nn #1#2 + { \tl_greplace_all:Nnn #1 {#2} { } } +\cs_generate_variant:Nn \tl_remove_all:Nn { c } +\cs_generate_variant:Nn \tl_gremove_all:Nn { c } +% \end{macrocode} +% \end{macro} +% +% \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} +% \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 +% the emptyness test done in \cs{tl_if_empty:n(TF)}: convert to harmless +% characters with \cs{tl_to_str:n}, and then use +% \cs{if_meaning:w} \cs{q_nil} |...| \cs{q_nil}. +% Note that converting to a string is done after reading the delimited +% argument for \cs{use_none:n}. The similar construction +% \cs{exp_after:wN} \cs{use_none:n} \cs{tl_to_str:n} \Arg{token list} |?| +% would fail if the token list contains the control sequence \cs{ }, +% while \cs{tex_escapechar:D} 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 ? } } +\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 } +\cs_generate_variant:Nn \tl_if_blank:nTF { V } +\cs_generate_variant:Nn \tl_if_blank_p:n { o } +\cs_generate_variant:Nn \tl_if_blank:nT { o } +\cs_generate_variant:Nn \tl_if_blank:nF { o } +\cs_generate_variant:Nn \tl_if_blank:nTF { o } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[pTF]{\tl_if_empty:N,\tl_if_empty:c} +% These functions check whether the token list in the argument is +% empty and execute the proper code from their argument(s). +% \begin{macrocode} +\prg_set_conditional:Npnn \tl_if_empty:N #1 { p , T , F , TF } + { + \if_meaning:w #1 \c_empty_tl + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_generate_variant:Nn \tl_if_empty_p:N { c } +\cs_generate_variant:Nn \tl_if_empty:NT { c } +\cs_generate_variant:Nn \tl_if_empty:NF { c } +\cs_generate_variant:Nn \tl_if_empty:NTF { c } +% \end{macrocode} +% \end{macro} +% +% \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 +% 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 +% token. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_empty:n #1 { p,TF,T,F} { + \exp_after:wN \if_meaning:w \exp_after:wN \q_nil \tl_to_str:n {#1} \q_nil + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +\cs_generate_variant:Nn \tl_if_empty_p:n { V } +\cs_generate_variant:Nn \tl_if_empty:nTF { V } +\cs_generate_variant:Nn \tl_if_empty:nT { V } +\cs_generate_variant:Nn \tl_if_empty:nF { V } +% \end{macrocode} +% \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 +% in conditionals on token lists, which mostly reduce to testing +% if a given token list is empty after applying a simple function +% to it. +% The test for emptyness is based on \cs{tl_if_empty:n(TF)}, but +% the expansion is hard-coded for efficiency, as this auxiliary +% function is used in many places. +% 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 { + \exp_after:wN \if_meaning:w \exp_after:wN \q_nil + \tl_to_str:n \exp_after:wN {#1} \q_nil + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +\prg_new_conditional:Npnn \tl_if_empty:o #1 { p,TF,T,F} + { \tl_if_empty_return:o {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[pTF]{\tl_if_eq:NN,\tl_if_eq:Nc,\tl_if_eq:cN,\tl_if_eq:cc} +% Returns \cs{c_true_bool} if and only if the two token list variables are +% equal. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_eq:NN #1#2 { p , T , F , TF } + { + \if_meaning:w #1 #2 + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_generate_variant:Nn \tl_if_eq_p:NN { Nc , c , cc } +\cs_generate_variant:Nn \tl_if_eq:NNTF { Nc , c , cc } +\cs_generate_variant:Nn \tl_if_eq:NNT { Nc , c , cc } +\cs_generate_variant:Nn \tl_if_eq:NNF { Nc , c , cc } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{\tl_if_eq:nn} +% \begin{variable}{\l_tl_tmpa_tl, \l_tl_tmpb_tl} +% A simple store and compare routine. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \tl_if_eq:nn #1#2 { T , F , TF } + { + \group_begin: + \tl_set:Nn \l_tl_tmpa_tl {#1} + \tl_set:Nn \l_tl_tmpb_tl {#2} + \if_meaning:w \l_tl_tmpa_tl \l_tl_tmpb_tl + \group_end: + \prg_return_true: + \else: + \group_end: + \prg_return_false: + \fi: + } +\tl_new:N \l_tl_tmpa_tl +\tl_new:N \l_tl_tmpb_tl +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro}[TF]{\tl_if_in:Nn, \tl_if_in:cn} +% See \cs{tl_if_in:nn(TF)} for further comments. Here we simply +% expand the token list variable and pass it to \cs{tl_if_in:nn(TF)}. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_if_in:NnT { \exp_args:No \tl_if_in:nnT } +\cs_new_protected_nopar:Npn \tl_if_in:NnF { \exp_args:No \tl_if_in:nnF } +\cs_new_protected_nopar:Npn \tl_if_in:NnTF { \exp_args:No \tl_if_in:nnTF } +\cs_generate_variant:Nn \tl_if_in:NnT { c } +\cs_generate_variant:Nn \tl_if_in:NnF { c } +\cs_generate_variant:Nn \tl_if_in:NnTF { c } +% \end{macrocode} +% \end{macro} +% +% \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 +% 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 +% the emptyness test. +% +% Special care is needed to treat correctly cases like +% |\tl_if_in:nnTF {a state}{states}|, where |#1#2| contains |#2| before +% the end. To cater for this case, we insert |{}{}| between the two token +% lists. This marker may not appear in |#2| because of \TeX{} limitations +% on what can delimit a parameter, hence we are safe. Using two brace +% groups makes the test work also for empty arguments. +% \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 } + { \prg_return_false: } { \prg_return_true: } + } +\cs_generate_variant:Nn \tl_if_in:nnT { V } +\cs_generate_variant:Nn \tl_if_in:nnF { V } +\cs_generate_variant:Nn \tl_if_in:nnTF { V } +\cs_generate_variant:Nn \tl_if_in:nnT { o } +\cs_generate_variant:Nn \tl_if_in:nnF { o } +\cs_generate_variant:Nn \tl_if_in:nnTF { o } +\cs_generate_variant:Nn \tl_if_in:nnT { no } +\cs_generate_variant:Nn \tl_if_in:nnF { no } +\cs_generate_variant:Nn \tl_if_in:nnTF { no } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\tl_if_single:n} +% \begin{macro}[aux]{\tl_if_single_aux:n} +% If the argument is a single token, or a single brace group +% preceeded by optional (explicit) spaces, or a non-zero number +% of spaces. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_single:n #1 { p , T , F , TF } + { + \tl_if_blank:nTF {#1} + { \tl_if_empty:nTF {#1} { \prg_return_false: } { \prg_return_true: } } + { \tl_if_single_aux:n {#1} } + } +\prg_new_conditional:Npnn \tl_if_single:N #1 { p , T , F , TF } + { + \tl_if_blank:oTF #1 + { \tl_if_empty:NTF #1 { \prg_return_false: } { \prg_return_true: } } + { \exp_args:No \tl_if_single_aux:n {#1} } + } +\cs_new:Npn \tl_if_single_aux:n #1 + { \tl_if_empty_return:o { \use_none:n #1 } } +% \end{macrocode} +% \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} +% 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 \q_recursion_tail \q_recursion_stop } +\cs_new_nopar:Npn \tl_map_function:NN #1#2 + { + \exp_after:wN \tl_map_function_aux:Nn + \exp_after:wN #2 #1 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \tl_map_function_aux:Nn #1#2 + { + \quark_if_recursion_tail_stop:n {#2} + #1 {#2} \tl_map_function_aux:Nn #1 + } +\cs_generate_variant:Nn \tl_map_function:NN { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_map_inline:nn} +% \begin{macro}{\tl_map_inline:Nn, \tl_map_inline:cn} +% \begin{macro}[aux]{\tl_map_inline_aux:n} +% \begin{variable}{\g_tl_inline_level_int} +% The inline functions are straight forward by now. We use a little +% trick with the counter \cs{g_tl_inline_level_int} to make +% them nestable. We can also make use of \cs{tl_map_function:Nn} +% from before. (\cs{g_tl_inline_level_int} is defined in \pkg{l3int} +% for order-of-loading reasons.) +% \begin{macrocode} +\cs_new_protected:Npn \tl_map_inline:nn #1#2 + { + \int_gincr:N \g_tl_inline_level_int + \cs_gset:cpn { tl_map_inline_ \int_use:N \g_tl_inline_level_int :n } + ##1 {#2} + \exp_args:Nc \tl_map_function_aux:Nn + { tl_map_inline_ \int_use:N \g_tl_inline_level_int :n } + #1 \q_recursion_tail \q_recursion_stop + \int_gdecr:N \g_tl_inline_level_int + } +\cs_new_protected:Npn \tl_map_inline:Nn #1#2 + { + \int_gincr:N \g_tl_inline_level_int + \cs_gset:cpn { tl_map_inline_ \int_use:N \g_tl_inline_level_int :n } + ##1 {#2} + \exp_last_unbraced:NcV \tl_map_function_aux:Nn + { tl_map_inline_ \int_use:N \g_tl_inline_level_int :n } + #1 \q_recursion_tail\q_recursion_stop + \int_gdecr:N \g_tl_inline_level_int + } +\cs_generate_variant:Nn \tl_map_inline:Nn { c } +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_map_variable:nNn} +% \begin{macro}{\tl_map_variable:NNn, \tl_map_variable:cNn} +% \begin{macro}[aux]{\tl_map_variable_aux: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 \q_recursion_tail \q_recursion_stop } +\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 + { + \tl_set:Nn #1 {#3} + \quark_if_recursion_tail_stop:N #1 + #2 \tl_map_variable_aux:Nnn #1 {#2} + } +\cs_generate_variant:Nn \tl_map_variable:NNn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_map_break:} +% The break statement. +% \begin{macrocode} +\cs_new_eq:NN \tl_map_break: \use_none_delimit_by_q_recursion_stop:w +% \end{macrocode} +% \end{macro} +% +% \subsection{Using token lists} +% +% \begin{macro}{\tl_to_str:n} +% Another name for a primitive. +% \begin{macrocode} +\cs_new_eq:NN \tl_to_str:n \etex_detokenize:D +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_to_str:N, \tl_to_str:c} +% These functions return the replacement text of a token list as a +% string. +% \begin{macrocode} +\cs_new_nopar:Npn \tl_to_str:N #1 { \etex_detokenize:D \exp_after:wN {#1} } +\cs_generate_variant:Nn \tl_to_str:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_use:N, \tl_use:c} +% \begin{macro}[aux]{\tl_error_message:} +% Token lists which are simply not defined will give a clear \TeX{} +% error here. No such luck for ones equal to \cs{scan_stop:} so +% instead a test is made and if there is an issue an error is forced. +% \begin{macrocode} +\cs_new_eq:NN \tl_use:N \prg_do_nothing: +\cs_new_nopar:Npn \tl_use:c #1 + { + \if_cs_exist:w #1 \cs_end: + \cs:w #1 \exp_after:wN \cs_end: + \else: + \exp_after:wN \tl_error_message: + \fi: + } +\group_begin: +\tex_catcode:D `\! = 11 \scan_stop: +\tex_catcode:D `\ = 11\scan_stop:% +\cs_gset_nopar:Npn\tl_error_message:{\undefined variable name!}% +\group_end:% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \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} +% 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|. +% The |0| to ensure it works on an empty list. +% \begin{macrocode} +\cs_new:Npn \tl_length:n #1 + { + \int_eval:n + { 0 \tl_map_function:nN {#1} \tl_length_aux:n } + } +\cs_new_nopar:Npn \tl_length:N #1 + { + \int_eval:n + { 0 \tl_map_function:NN #1 \tl_length_aux:n } + } +\cs_new:Npn \tl_length_aux:n #1 { + 1 } +\cs_generate_variant:Nn \tl_length:n { V , o } +\cs_generate_variant:Nn \tl_length:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_reverse:n, \tl_reverse:V, \tl_reverse:o} +% \begin{macro}[aux]{\tl_reverse_aux:nN} +% Reversal of a token list is done by taking one token at a time +% and putting it in front of the ones before it. +% \begin{macrocode} +\cs_new:Npn \tl_reverse:n #1 + { \tl_reverse_aux:nN { } #1 \q_recursion_tail \q_recursion_stop } +\cs_new:Npn \tl_reverse_aux:nN #1#2 + { + \quark_if_recursion_tail_stop_do:nn {#2} {#1} + \tl_reverse_aux:nN { #2 #1 } + } +\cs_generate_variant:Nn \tl_reverse:n {V,o} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_reverse:N, \tl_reverse:c} +% This reverses the list, leaving |\exp_stop_f:| in front, which in turn +% is removed by the |f| expansion which comes to a halt. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_reverse:N #1 + { \tl_set:Nf #1 { \tl_reverse:o { #1 \exp_stop_f: } } } +\cs_generate_variant:Nn \tl_reverse:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_trim_spaces:n} +% \begin{macro} +% { +% \tl_trim_spaces:N, \tl_trim_spaces:c, +% \tl_gtrim_spaces:N, \tl_gtrim_spaces:c +% } +% \begin{macro}[aux]{\tl_trim_spaces_exp:n} +% \begin{macro}[aux]{\tl_trim_spaces_aux_i:w} +% \begin{macro}[aux]{\tl_trim_spaces_aux_ii:w} +% Trimming spaces from around the input uses the idea of a sufficiently +% odd token to allow for a delimited argument to do this. Here, the +% standard approach [a |Q| with category code 3 (math toggle)] is used. +% The \cs{etex_unexpanded:D} here is used so that space trimming will +% behave correctly within an \texttt{x}-type expansion. +% \begin{macrocode} +\cs_new:Npn \tl_trim_spaces:n #1 + { + \etex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN + { \tl_trim_spaces_exp:n {#1} } + } +\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} } } +\group_begin: + \tex_catcode:D `\Q = 3 \scan_stop: + \cs_new:Npn \tl_trim_spaces_exp:n #1 + { \tex_romannumeral:D - `0 \tl_trim_spaces_aux_i:w \exp_not:N #1 Q ~ Q } + \cs_new:Npn \tl_trim_spaces_aux_i:w #1 ~ Q { \tl_trim_spaces_aux_ii:w #1 Q } + \cs_new:Npn \tl_trim_spaces_aux_ii:w #1 Q #2 {#1} +\group_end: +\cs_generate_variant:Nn \tl_trim_spaces:N { c } +\cs_generate_variant:Nn \tl_gtrim_spaces:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{The first token from a token list} +% +% \begin{macro}{\tl_head:n, \tl_head:V, \tl_head:v, \tl_head:f} +% \begin{macro}{\tl_head:w} +% \begin{macro}{\tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f} +% \begin{macro}{\tl_tail:w} +% These functions pick up either the head or the tail of a list. +% \begin{macrocode} +\cs_new:Npn \tl_head:n #1 { \tl_head:w #1 \q_stop } +\cs_new:Npn \tl_tail:n #1 { \tl_tail:w #1 \q_stop } +\cs_new:Npn \tl_head:w #1#2 \q_stop {#1} +\cs_new:Npn \tl_tail:w #1#2 \q_stop {#2} +\cs_generate_variant:Nn \tl_head:n { V , v , f } +\cs_generate_variant:Nn \tl_tail:n { V , v , f } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[pTF]{\tl_if_head_eq_meaning:nN} +% \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} +% When we want to check if the first token of a list equals something +% specific it is usually either to see if it is a control sequence or +% a character. Hence we make two different functions as the internal +% test is different. +% \cs{tl_if_head_meaning_eq:nNTF} uses \cs{if_meaning:w} and will +% consider the tokens |b|$\sb{11}$ and |b|$\sb{12}$ different. +% \cs{tl_if_head_char_eq:nNTF} on the other hand only compares +% character codes so would regard |b|$\sb{11}$ and |b|$\sb{12}$ as +% equal but would also regard two primitives as equal. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_head_eq_meaning:nN #1#2 { p , T , F , TF } + { + \exp_after:wN \if_meaning:w \tl_head:w #1 \q_stop #2 + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +% \end{macrocode} +% For the charcode and catcode versions we insert |\exp_not:N| in +% front of both tokens. If you need them to expand fully as \TeX{} +% does itself with these you can use an |f| type expansion. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_head_eq_charcode:nN #1#2 { p , T , F , TF } + { + \exp_after:wN \if:w + \exp_after:wN \exp_not:N \tl_head:w #1 \q_stop \exp_not:N #2 + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_generate_variant:Nn \tl_if_head_eq_charcode_p:nN { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNTF { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { f } +% \end{macrocode} +% And now catcodes: +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_head_eq_catcode:nN #1#2 { p , T , F , TF } + { + \exp_after:wN \if_catcode:w \exp_after:wN \exp_not:N + \tl_head:w #1 \q_stop \exp_not:N #2 + \prg_return_true: \else: \prg_return_false: \fi: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Viewing token lists} +% +% \begin{macro}{\tl_show:N, \tl_show:c} +% Showing token list variables is done directly: at the moment do not +% worry if they are defined. +% \begin{macrocode} +\cs_new_protected:Npn \tl_show:N #1 { \cs_show:N #1 } +\cs_generate_variant:Nn \tl_show:N { c } +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\tl_show:n} +% For literal token lists, life is easy. +% \begin{macrocode} +\cs_new_eq:NN \tl_show:n \etex_showtokens:D +% \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. +% \begin{macrocode} +%<*package> +\tl_const:Nx \c_job_name_tl { \tex_jobname:D } +%</package> +%<*initex> +\tex_everyjob:D \exp_after:wN + { + \tex_the:D \tex_everyjob:D + \luatex_if_engine:TF + { + \tl_if_in:onTF { \tex_jobname:D } { ~ } + { \tl_const:Nx \c_job_name_tl { " \tex_jobname:D " } } + { \tl_const:Nx \c_job_name_tl { \tex_jobname:D } } + } + { \tl_const:Nx \c_job_name_tl { \tex_jobname:D } } + } +%</initex> +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\c_empty_tl} +% Never full. +% \begin{macrocode} +\tl_const:Nn \c_empty_tl { } +% \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} +% Global temporary token list variables. +% They are supposed to be set and used immediately, +% with no delay between the definition and the use because you +% can't count on other macros not to redefine them from under you. +% \begin{macrocode} +\tl_new:N \g_tmpa_tl +\tl_new:N \g_tmpb_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_tmpa_tl, \l_tmpb_tl} +% These are local temporary token list variables. Be sure not to assume +% that the value you put into them will survive for +% long---see discussion above. +% \begin{macrocode} +\tl_new:N \l_tmpa_tl +\tl_new:N \l_tmpb_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Experimental functions} +% +% \begin{macro}[EXP,pTF]{\tl_if_single_item: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} +\cs_new:Npn \tl_if_single_item:nTF #1 + { \str_if_eq:onTF { \use_ii:nn #1 {?} ? } {??} } +\cs_new:Npn \tl_if_single_item:nT #1 + { \str_if_eq:onT { \use_ii:nn #1 {?} ? } {??} } +\cs_new:Npn \tl_if_single_item:nF #1 + { \str_if_eq:onF { \use_ii:nn #1 {?} ? } {??} } +\cs_new:Npn \tl_if_single_item_p:n #1 + { \str_if_eq_p:on { \use_ii:nn #1 {?} ? } {??} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,pTF]{\tl_if_head_begin_group:n} +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_head_begin_group:n #1 { p , T , F , TF } + { + \exp_after:wN \use_none:n + \exp_after:wN { + \exp_after:wN { + \token_to_str:N #1 . + } + \prg_return_true: \exp_after:wN \use_none:nn \token_to_str:N + } + \prg_return_false: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP,pTF]{\tl_if_head_eq_space:n} +% \begin{macro}[EXP,aux]{\tl_if_head_eq_space_aux: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 +% 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. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_head_eq_space:n #1 { p , T , F , TF } + { + \if_false: { \fi: + \tl_if_head_eq_space_aux:w \prg_do_nothing: #1 ? ~ } + } +\cs_new:Npn \tl_if_head_eq_space_aux:w #1 ~ % + { + \tl_if_empty_return:o { #1 } + \exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP,pTF]{\tl_if_single_token:n} +% If the token list starts with a space, then it is +% a single token if and only if its string representation +% is exactly one space character. Otherwise, we check if removing +% the first token group makes the token list empty. If it doesn't, +% the token list is not a single token. If it does, then the token +% list is either a single token or a single brace group. This is +% tested for using \cs{tl_if_head_begin_group:n}. +% \begin{macrocode} +\prg_new_conditional:Npnn \tl_if_single_token:n #1 { p , T , F , TF } + { + \tl_if_head_eq_space:nTF {#1} + { + \str_if_eq:nnTF {#1} {~} + \prg_return_true: \prg_return_false: + } + { + \str_if_eq:onTF { \use_none:n #1 ? } {?} + { + \tl_if_head_begin_group:nTF {#1} + \prg_return_false: \prg_return_true: + } + \prg_return_false: + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated functions} +% +% \begin{macro}{\tl_new:Nn, \tl_new:cn, \tl_new:Nx} +% Use either \cs{tl_const:Nn} or \cs{tl_new:N}. +% \begin{macrocode} +\cs_new_protected:Npn \tl_new:Nn #1#2 + { + \tl_new:N #1 + \tl_gset:Nn #1 {#2} + } +\cs_generate_variant:Nn \tl_new:Nn { c } +\cs_generate_variant:Nn \tl_new:Nn { Nx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\tl_gset:Nc} +% \begin{macro}{\tl_set:Nc} +% This was useful once, but nowadays does not make much sense. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \tl_gset:Nc + { \pref_global:D \tl_set:Nc } +\cs_new_protected_nopar:Npn \tl_set:Nc #1#2 + { \tl_set:No #1 { \cs:w #2 \cs_end: } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_replace_in:Nnn, \tl_replace_in:cnn} +% \begin{macro}{\tl_greplace_in:Nnn, \tl_greplace_in:cnn} +% \begin{macro}{\tl_replace_all_in:Nnn, \tl_replace_all_in:cnn} +% \begin{macro}{\tl_greplace_all_in:Nnn, \tl_greplace_all_in:cnn} +% These are renamed. +% \begin{macrocode} +\cs_new_eq:NN \tl_replace_in:Nnn \tl_replace_once:Nnn +\cs_new_eq:NN \tl_replace_in:cnn \tl_replace_once:cnn +\cs_new_eq:NN \tl_greplace_in:Nnn \tl_greplace_once:Nnn +\cs_new_eq:NN \tl_greplace_in:cnn \tl_greplace_once:cnn +\cs_new_eq:NN \tl_replace_all_in:Nnn \tl_replace_all:Nnn +\cs_new_eq:NN \tl_replace_all_in:cnn \tl_replace_all:cnn +\cs_new_eq:NN \tl_greplace_all_in:Nnn \tl_greplace_all:Nnn +\cs_new_eq:NN \tl_greplace_all_in:cnn \tl_greplace_all:cnn +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_remove_in:Nn, \tl_remove_in:cn} +% \begin{macro}{\tl_gremove_in:Nn, \tl_gremove_in:cn} +% \begin{macro}{\tl_remove_all_in:Nn, \tl_remove_all_in:cn} +% \begin{macro}{\tl_gremove_all_in:Nn, \tl_gremove_all_in:cn} +% Also renamed. +% \begin{macrocode} +\cs_new_eq:NN \tl_remove_in:Nn \tl_remove_once:Nn +\cs_new_eq:NN \tl_remove_in:cn \tl_remove_once:cn +\cs_new_eq:NN \tl_gremove_in:Nn \tl_gremove_once:Nn +\cs_new_eq:NN \tl_gremove_in:cn \tl_gremove_once:cn +\cs_new_eq:NN \tl_remove_all_in:Nn \tl_remove_all:Nn +\cs_new_eq:NN \tl_remove_all_in:cn \tl_remove_all:cn +\cs_new_eq:NN \tl_gremove_all_in:Nn \tl_gremove_all:Nn +\cs_new_eq:NN \tl_gremove_all_in:cn \tl_gremove_all:cn +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_elt_count:n, \tl_elt_count:V, \tl_elt_count:o} +% \begin{macro}{\tl_elt_count:N, \tl_elt_count:c} +% Another renaming job. +% \begin{macrocode} +\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 +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tl_head_i:n} +% \begin{macro}{\tl_head_i:w} +% \begin{macro}{\tl_head_iii:n} +% \begin{macro}{\tl_head_iii:f} +% \begin{macro}{\tl_head_iii:w} +% Two renames, and a few that are rather too specialised. +% \begin{macrocode} +\cs_new_eq:NN \tl_head_i:n \tl_head:n +\cs_new_eq:NN \tl_head_i:w \tl_head:w +\cs_new:Npn \tl_head_iii:n #1 { \tl_head_iii:w #1 \q_stop } +\cs_generate_variant:Nn \tl_head_iii:n { f } +\cs_new:Npn \tl_head_iii:w #1#2#3#4 \q_stop {#1#2#3} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex |