diff options
author | Karl Berry <karl@freefriends.org> | 2018-12-13 22:53:27 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-12-13 22:53:27 +0000 |
commit | bbbf3700086ea2f861b6594ea23e37f29d3f9dc1 (patch) | |
tree | 051ec6913956e3f2a6563878941ccebd9645b401 /Master/texmf-dist/source/latex/l3kernel/l3tl.dtx | |
parent | 301b93fafda199abb5c1eaf8b18cb1d1d0345a68 (diff) |
l3kernel (13dec18)
git-svn-id: svn://tug.org/texlive/trunk@49405 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 | 214 |
1 files changed, 213 insertions, 1 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index fab5c69b28a..b85b98a9222 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018-12-11} +% \date{Released 2018-12-12} % % \maketitle % @@ -1026,6 +1026,79 @@ % \end{texnote} % \end{function} % +% \begin{function}[EXP, added = 2017-02-17, updated = 2017-07-15] +% {\tl_range:Nnn, \tl_range:nnn} +% \begin{syntax} +% \cs{tl_range:Nnn} \meta{tl~var} \Arg{start index} \Arg{end index} +% \cs{tl_range:nnn} \Arg{token list} \Arg{start index} \Arg{end index} +% \end{syntax} +% Leaves in the input stream the items from the \meta{start index} to the +% \meta{end index} inclusive. Spaces and braces are preserved between +% the items returned (but never at either end of the list). +% +% Here \meta{start index} and \meta{end index} should be integer denotations. +% For describing in detail the functions' behavior, let $m$ and $n$ be the start +% and end index respectively. If either is $0$, the result is empty. A positive +% index means `start counting from the left end', a negative index means +% `start counting from the right end'. Let $l$ be the count of the token list. +% +% The \emph{actual start point} is determined as $M=m$ if~$m>0$ and as $M=l+m+1$ +% if~$m<0$. Similarly the \emph{actual end point} is $N=n$ if~$n>0$ and $N=l+n+1$ +% if~$n<0$. If $M>N$, the result is empty. Otherwise it consists of all items from +% position $M$ to position $N$ inclusive; for the purpose of this rule, we can +% imagine that the token list extends at infinity on either side, with void items +% at positions $s$ for $s\le0$ or $s>l$. +% +% Spaces in between items in the actual range are preserved. Spaces at either end +% of the token list will be removed anyway (think to the token list being passed to +% |\tl_trim_spaces:n| to begin with. +% +% Thus, with $l=7$ as in the examples below, all of the following are equivalent +% and result in the whole token list +% \begin{verbatim} +% \tl_range:nnn { abcd~{e{}}fg } { 1 } { 7 } +% \tl_range:nnn { abcd~{e{}}fg } { 1 } { 12 } +% \tl_range:nnn { abcd~{e{}}fg } { -7 } { 7 } +% \tl_range:nnn { abcd~{e{}}fg } { -12 } { 7 } +% \end{verbatim} +% Here are some more interesting examples. The calls +% \begin{verbatim} +% \iow_term:x { \tl_range:nnn { abcd{e{}}fg } { 2 } { 5 } } +% \iow_term:x { \tl_range:nnn { abcd{e{}}fg } { 2 } { -3 } } +% \iow_term:x { \tl_range:nnn { abcd{e{}}fg } { -6 } { 5 } } +% \iow_term:x { \tl_range:nnn { abcd{e{}}fg } { -6 } { -3 } } +% \end{verbatim} +% are all equivalent and will print |bcd{e{}}| on the terminal; similarly +% \begin{verbatim} +% \iow_term:x { \tl_range:nnn { abcd~{e{}}fg } { 2 } { 5 } } +% \iow_term:x { \tl_range:nnn { abcd~{e{}}fg } { 2 } { -3 } } +% \iow_term:x { \tl_range:nnn { abcd~{e{}}fg } { -6 } { 5 } } +% \iow_term:x { \tl_range:nnn { abcd~{e{}}fg } { -6 } { -3 } } +% \end{verbatim} +% are all equivalent and will print |bcd {e{}}| on the +% terminal (note the space in the middle). To the contrary, +% \begin{verbatim} +% \tl_range:nnn { abcd~{e{}}f } { 2 } { 4 } +% \end{verbatim} +% will discard the space after `d`. +% +% If we want to get the items from the third to the last, the call +% is |\tl_range:nnn { <tl> } { 3 } { -1 }|. Similarly, for discarding +% the last item, we can do |\tl_range:nnn { <tl> } { 1 } { -2 }|. +% +% The behavior of \cs{tl_range:Nnn} is exactly the same, acting on the +% contents of the tl variable. +% +% For improved performance, see \cs{tl_range_braced:nnn} and +% \cs{tl_range_unbraced:nnn}. +% \begin{texnote} +% The result is returned within the \tn{unexpanded} +% primitive (\cs{exp_not:n}), which means that the \meta{item} +% does not expand further when appearing in an \texttt{x}-type +% argument expansion. +% \end{texnote} +% \end{function} +% % \section{Viewing token lists} % % \begin{function}[updated = 2015-08-01]{\tl_show:N, \tl_show:c} @@ -2994,6 +3067,145 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\tl_range:Nnn, \tl_range:cnn, \tl_range:nnn} +% \begin{macro} +% { +% \@@_range:Nnnn, \@@_range:nnnNn, \@@_range:nnNn, \@@_range_skip:w, +% \@@_range:w, \@@_range_skip_spaces:n, \@@_range_collect:nn, +% \@@_range_collect:ff, \@@_range_collect_space:nw, +% \@@_range_collect_N:nN, \@@_range_collect_group:nN, +% } +% To avoid checking for the end of the token list at every step, start +% by counting the number $l$ of items and \enquote{normalizing} the +% bounds, namely clamping them to the interval $[0,l]$ and dealing +% with negative indices. More precisely, \cs{@@_range_items:nnNn} +% receives the number of items to skip at the beginning of the token +% list, the index of the last item to keep, a function which is either +% \cs{@@_range:w} or the token list itself. If nothing should be kept, +% leave |{}|: this stops the \texttt{f}-expansion of \cs{tl_head:f} and that +% function produces an empty result. Otherwise, repeatedly call +% \cs{@@_range_skip:w} to delete |#1| items from the input stream (the +% extra brace group avoids an off-by-one shift). For the braced +% version \cs{@@_range_braced:w} sets up +% \cs{@@_range_collect_braced:w} which stores items one by one in an +% argument after the semicolon. Depending on the first token of the tail, +% either just move it (if it is a space) or also decrement the number of +% items left to find. Eventually, the result is a brace group followed by +% the rest of the token list, and \cs{tl_head:f} cleans up and gives the +% result in \cs{exp_not:n}. +% \begin{macrocode} +\cs_new:Npn \tl_range:Nnn { \exp_args:No \tl_range:nnn } +\cs_generate_variant:Nn \tl_range:Nnn { c } +\cs_new:Npn \tl_range:nnn { \@@_range:Nnnn \@@_range:w } +\cs_new:Npn \@@_range:Nnnn #1#2#3#4 + { + \tl_head:f + { + \exp_args:Nf \@@_range:nnnNn + { \tl_count:n {#2} } {#3} {#4} #1 {#2} + } + } +\cs_new:Npn \@@_range:nnnNn #1#2#3 + { + \exp_args:Nff \@@_range:nnNn + { + \exp_args:Nf \@@_range_normalize:nn + { \int_eval:n { #2 - 1 } } {#1} + } + { + \exp_args:Nf \@@_range_normalize:nn + { \int_eval:n {#3} } {#1} + } + } +\cs_new:Npn \@@_range:nnNn #1#2#3#4 + { + \if_int_compare:w #2 > #1 \exp_stop_f: \else: + \exp_after:wN { \exp_after:wN } + \fi: + \exp_after:wN #3 + \int_value:w \int_eval:n { #2 - #1 } \exp_after:wN ; + \exp_after:wN { \exp:w \@@_range_skip:w #1 ; { } #4 } + } +\cs_new:Npn \@@_range_skip:w #1 ; #2 + { + \if_int_compare:w #1 > 0 \exp_stop_f: + \exp_after:wN \@@_range_skip:w + \int_value:w \int_eval:n { #1 - 1 } \exp_after:wN ; + \else: + \exp_after:wN \exp_end: + \fi: + } +\cs_new:Npn \@@_range:w #1 ; #2 + { + \exp_args:Nf \@@_range_collect:nn + { \@@_range_skip_spaces:n {#2} } {#1} + } +\cs_new:Npn \@@_range_skip_spaces:n #1 + { + \tl_if_head_is_space:nTF {#1} + { \exp_args:Nf \@@_range_skip_spaces:n {#1} } + { { } #1 } + } +\cs_new:Npn \@@_range_collect:nn #1#2 + { + \int_compare:nNnTF {#2} = 0 + {#1} + { + \exp_args:No \tl_if_head_is_space:nTF { \use_none:n #1 } + { + \exp_args:Nf \@@_range_collect:nn + { \@@_range_collect_space:nw #1 } + {#2} + } + { + \@@_range_collect:ff + { + \exp_args:No \tl_if_head_is_N_type:nTF { \use_none:n #1 } + { \@@_range_collect_N:nN } + { \@@_range_collect_group:nn } + #1 + } + { \int_eval:n { #2 - 1 } } + } + } + } +\cs_new:Npn \@@_range_collect_space:nw #1 ~ { { #1 ~ } } +\cs_new:Npn \@@_range_collect_N:nN #1#2 { { #1 #2 } } +\cs_new:Npn \@@_range_collect_group:nn #1#2 { { #1 {#2} } } +\cs_generate_variant:Nn \@@_range_collect:nn { ff } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_range_normalize:nn} +% This function converts an \meta{index} argument into an explicit +% position in the token list (a result of $0$ denoting \enquote{out of +% bounds}). Expects two explicit integer arguments: the \meta{index} +% |#1| and the string count~|#2|. If |#1| is negative, replace it by +% $|#1| + |#2| + 1$, then limit to the range $[0, |#2|]$. +% \begin{macrocode} +\cs_new:Npn \@@_range_normalize:nn #1#2 + { + \int_eval:n + { + \if_int_compare:w #1 < 0 \exp_stop_f: + \if_int_compare:w #1 < -#2 \exp_stop_f: + 0 + \else: + #1 + #2 + 1 + \fi: + \else: + \if_int_compare:w #1 < #2 \exp_stop_f: + #1 + \else: + #2 + \fi: + \fi: + } + } +% \end{macrocode} +% \end{macro} +% % \subsection{Viewing token lists} % % \begin{macro}{\tl_show:N, \tl_show:c, \tl_log:N, \tl_log:c, \@@_show:NN} |