[latex3-commits] [l3svn] r6944 - Add tl_range:nnn to l3candidates (fixes #339)
noreply at latex-project.org
noreply at latex-project.org
Fri Feb 17 18:34:28 CET 2017
Author: bruno
Date: 2017-02-17 18:34:27 +0100 (Fri, 17 Feb 2017)
New Revision: 6944
Added:
trunk/l3kernel/testfiles/m3tl014.lvt
trunk/l3kernel/testfiles/m3tl014.tlg
Modified:
trunk/l3kernel/l3candidates.dtx
Log:
Add tl_range:nnn to l3candidates (fixes #339)
Modified: trunk/l3kernel/l3candidates.dtx
===================================================================
--- trunk/l3kernel/l3candidates.dtx 2017-02-17 16:47:59 UTC (rev 6943)
+++ trunk/l3kernel/l3candidates.dtx 2017-02-17 17:34:27 UTC (rev 6944)
@@ -961,6 +961,41 @@
% \end{texnote}
% \end{function}
%
+% \begin{function}[EXP, added = 2017-02-17]
+% {\tl_range:Nnn, \tl_range:cnn, \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. Positive \meta{indices} are counted
+% from the start of the \meta{token list}, $1$~being the first item, and
+% negative \meta{indices} are counted from the end of the token list,
+% $-1$~being the last item. If either of \meta{start index} or
+% \meta{end index} is~$0$, the result is empty. For instance,
+% \begin{verbatim}
+% \iow_term:x { \tl_range:nnn { abcdef } { 2 } { 5 } }
+% \iow_term:x { \tl_range:nnn { abcdef } { -4 } { -1 } }
+% \iow_term:x { \tl_range:nnn { abcdef } { -2 } { -1 } }
+% \iow_term:x { \tl_range:nnn { abcdef } { 0 } { -1 } }
+% \end{verbatim}
+% will print \texttt{{b}{c}{d}{e}}, \texttt{{c}{d}{e}{f}}, \texttt{{e}{f}}, and an empty
+% line to the terminal. The \meta{start index} must always be smaller than
+% or equal to the \meta{end index}: if this is not the case then no output
+% is generated. Thus
+% \begin{verbatim}
+% \iow_term:x { \tl_range:nnn { abcdef } { 5 } { 2 } }
+% \iow_term:x { \tl_range:nnn { abcdef } { -1 } { -4 } }
+% \end{verbatim}
+% both yield empty token lists.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{item}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
% \section{Additions to \pkg{l3tokens}}
%
% \begin{function}[TF, updated = 2012-12-20]{\peek_N_type:}
@@ -4300,6 +4335,8 @@
% \end{macrocode}
% \end{variable}
%
+% \subsubsection{Other additions to \pkg{l3tl}}
+%
% \begin{macro}{\tl_rand_item:n, \tl_rand_item:N, \tl_rand_item:c}
% Importantly \cs{tl_item:nn} only evaluates its argument once.
% \begin{macrocode}
@@ -4313,6 +4350,105 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\tl_range:Nnn, \tl_range:cnn, \tl_range:nnn}
+% \begin{macro}[aux]{\@@_range:nnnw, \@@_range:nnw, \@@_range_normalize:nn, \@@_range_collect:w, \@@_range_skip:w}
+% 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:nnw} receives
+% the number of items to skip at the beginning of the token list, and
+% the index of the last item to keep. 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 mistake), then
+% repeatedly call \cs{@@_range_collect:w} to store in its second
+% argument the items to be kept. 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 #1#2#3
+ {
+ \tl_head:f
+ {
+ \exp_args:Nf \@@_range:nnnw { \tl_count:n {#1} } {#2} {#3}
+ #1
+ }
+ }
+\cs_new:Npn \@@_range:nnnw #1#2#3
+ {
+ \exp_args:Nff \@@_range:nnw
+ {
+ \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:nnw #1#2
+ {
+ \if_int_compare:w #2 > #1 \exp_stop_f: \else:
+ \exp_after:wN { \exp_after:wN }
+ \fi:
+ \exp_after:wN \@@_range_collect:w
+ \__int_value:w \__int_eval:w #2 - #1 \exp_after:wN ;
+ \exp_after:wN { \exp_after:wN }
+ \exp:w \@@_range_skip:w #1 ; { }
+ }
+\cs_new:Npn \@@_range_skip:w #1 ; #2
+ {
+ \if_int_compare:w #1 > \c_zero
+ \exp_after:wN \@@_range_skip:w
+ \__int_value:w \__int_eval:w #1 - 1 \exp_after:wN ;
+ \else:
+ \exp_after:wN \exp_end:
+ \fi:
+ }
+\cs_new:Npn \@@_range_collect:w #1 ; #2#3
+ {
+ \if_int_compare:w #1 > \c_one
+ \exp_after:wN \@@_range_collect:w
+ \__int_value:w \__int_eval:w #1 - 1 \exp_after:wN ;
+ \fi:
+ { #2 {#3} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}[EXP, aux]{\@@_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 < \c_zero
+ \if_int_compare:w #1 < -#2 \exp_stop_f:
+ \c_zero
+ \else:
+ #1 + #2 + \c_one
+ \fi:
+ \else:
+ \if_int_compare:w #1 < #2 \exp_stop_f:
+ #1
+ \else:
+ #2
+ \fi:
+ \fi:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{Additions to \pkg{l3tokens}}
%
% \begin{macrocode}
Added: trunk/l3kernel/testfiles/m3tl014.lvt
===================================================================
--- trunk/l3kernel/testfiles/m3tl014.lvt (rev 0)
+++ trunk/l3kernel/testfiles/m3tl014.lvt 2017-02-17 17:34:27 UTC (rev 6944)
@@ -0,0 +1,24 @@
+%
+% Copyright (C) 2017 LaTeX3 Project
+%
+\input{regression-test}
+
+\RequirePackage[check-declarations,log-functions]{expl3}
+
+\START
+\AUTHOR{Bruno Le Floch}
+\ExplSyntaxOn
+
+\TEST { tl~range }
+ {
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { 0 } { 0 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { 1 } { 1 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { 1 } { -2 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { -1 } { -3 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { -3 } { -1 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { 1 } { 7 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { -7 } { 3 } | }
+ \TYPE { | \tl_range:nnn { \A{\B\C}\D{}~{\E} } { -7 } { 0 } | }
+ }
+
+\END
Property changes on: trunk/l3kernel/testfiles/m3tl014.lvt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/l3kernel/testfiles/m3tl014.tlg
===================================================================
--- trunk/l3kernel/testfiles/m3tl014.tlg (rev 0)
+++ trunk/l3kernel/testfiles/m3tl014.tlg 2017-02-17 17:34:27 UTC (rev 6944)
@@ -0,0 +1,15 @@
+This is a generated file for the LaTeX (2e + expl3) validation system.
+Don't change this file in any respect.
+Author: Bruno Le Floch
+============================================================
+TEST 1: tl range
+============================================================
+||
+|{\A }|
+|{\A }{\B \C }{\D }{}|
+||
+|{\D }{}{\E }|
+|{\A }{\B \C }{\D }{}{\E }|
+|{\A }{\B \C }{\D }|
+||
+============================================================
Property changes on: trunk/l3kernel/testfiles/m3tl014.tlg
___________________________________________________________________
Added: svn:eol-style
+ native
More information about the latex3-commits
mailing list