[latex3-commits] [git/LaTeX3-latex3-latex3] main: Implement \seq_pop_item:NnN(TF) (fixes #844) (0adfe3ec4)

Bruno Le Floch blflatex at gmail.com
Wed Apr 28 15:21:50 CEST 2021


Repository : https://github.com/latex3/latex3
On branch  : main
Link       : https://github.com/latex3/latex3/commit/0adfe3ec4897f5ef394039d502686fac96a88320

>---------------------------------------------------------------

commit 0adfe3ec4897f5ef394039d502686fac96a88320
Author: Bruno Le Floch <blflatex at gmail.com>
Date:   Wed Apr 28 08:12:54 2021 +0200

    Implement \seq_pop_item:NnN(TF) (fixes #844)


>---------------------------------------------------------------

0adfe3ec4897f5ef394039d502686fac96a88320
 l3kernel/CHANGELOG.md           |  2 +-
 l3kernel/l3candidates.dtx       | 72 +++++++++++++++++++++++++++++++++
 l3kernel/testfiles/m3seq005.lvt | 43 ++++++++++++++++++++
 l3kernel/testfiles/m3seq005.tlg | 90 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/l3kernel/CHANGELOG.md b/l3kernel/CHANGELOG.md
index 0a219856d..3c34ad55d 100644
--- a/l3kernel/CHANGELOG.md
+++ b/l3kernel/CHANGELOG.md
@@ -12,7 +12,7 @@ this project uses date-based 'snapshot' version identifiers.
 - `\tracingstacklevels`
 - Color export in comma-separated format
 - `\ur{...}` escape in `l3regex` to compose regexes
-- `\seq_put_item:Nnn(TF)` to change an entry of a sequence
+- `\seq_put_item:Nnn(TF)` and `\seq_pop_item:NnN(TF)`
 
 ### Changed
 - Breaking change: use prevailing catcodes instead of string in
diff --git a/l3kernel/l3candidates.dtx b/l3kernel/l3candidates.dtx
index 381f9779a..5ddfe2578 100644
--- a/l3kernel/l3candidates.dtx
+++ b/l3kernel/l3candidates.dtx
@@ -452,6 +452,24 @@
 %   afterwards.
 % \end{function}
 %
+% \begin{function}[added = 2021-04-28, noTF]
+%   {\seq_pop_item:NnN, \seq_pop_item:cnN, \seq_gpop_item:NnN, \seq_gpop_item:cnN}
+%   \begin{syntax}
+%     \cs{seq_pop_item:NnN} \meta{seq~var} \Arg{intexpr} \Arg{tl~var}
+%     \cs{seq_pop_item:NnNTF} \meta{seq~var} \Arg{intexpr} \Arg{tl~var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Removes the \meta{item} at position \meta{integer expression} in the
+%   \meta{sequence}, and places it in the \meta{token list variable}.
+%   Items are indexed from $1$ on the left/top of the \meta{sequence},
+%   or from $-1$ on the right/bottom.  If the position is zero or is
+%   larger (in absolute value) than the number of items in the sequence,
+%   the \meta{seq~var} is not modified, the \meta{token list} is set to
+%   the special marker \cs{q_no_value}, and the \meta{false code} is
+%   left in the input stream; otherwise the \meta{true code} is.  The
+%   \meta{token list} assignment is local while the \meta{sequence} is
+%   assigned locally for |pop| or globally for |gpop| functions.
+% \end{function}
+%
 % \section{Additions to \pkg{l3sys}}
 %
 % \begin{variable}[added = 2018-05-02]{\c_sys_engine_version_str}
@@ -1261,6 +1279,60 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}[noTF]{\seq_pop_item:NnN, \seq_pop_item:cnN, \seq_gpop_item:NnN, \seq_gpop_item:cnN}
+% \begin{macro}{\@@_pop_item:NnNNN}
+%   The |NnN| versions simply call the conditionals, for which we will
+%   rely on the internals of \cs{seq_put_item:Nnn}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \seq_pop_item:NnN #1#2#3
+  { \seq_pop_item:NnNTF #1 {#2} #3 { } { } }
+\cs_new_protected:Npn \seq_gpop_item:NnN #1#2#3
+  { \seq_gpop_item:NnNTF #1 {#2} #3 { } { } }
+\cs_generate_variant:Nn \seq_pop_item:NnN { c }
+\cs_generate_variant:Nn \seq_gpop_item:NnN { c }
+\prg_new_protected_conditional:Npnn \seq_pop_item:NnN #1#2#3 { TF , T , F }
+  { \@@_pop_item:NnNN #1 {#2} #3 \__kernel_tl_set:Nx }
+\prg_new_protected_conditional:Npnn \seq_gpop_item:NnN #1#2#3 { TF , T , F }
+  { \@@_pop_item:NnNN #1 {#2} #3 \__kernel_tl_gset:Nx }
+\prg_generate_conditional_variant:Nnn \seq_pop_item:NnN { c } { TF , T , F }
+\prg_generate_conditional_variant:Nnn \seq_gpop_item:NnN { c } { TF , T , F }
+%    \end{macrocode}
+%   Save in \cs{l_@@_internal_b_tl} the token list variable |#3| in
+%   which we will store the item.  The \cs{@@_put_item:nnNNNN} auxiliary
+%   eventually inserts \cs{l_@@_internal_a_tl} in place of the item
+%   found in the sequence, so we empty that.  Instead of the last
+%   argument \cs{use_i:nn} or \cs{use_ii:nn} used for |put| functions,
+%   we introduce \cs{@@_pop_item:nn}, which stores \cs{q_no_value}
+%   before calling its second argument
+%   (\cs{prg_return_true:}/\texttt{false:}) to end the conditional.  The
+%   item found is passed to \cs{@@_pop_item_aux:w}, which interrupts the
+%   |x|-expanding sequence assignment and stores the item using the
+%   assignment function in \cs{l_@@_internal_b_tl}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_pop_item:NnNN #1#2#3#4
+  {
+    \tl_clear:N \l_@@_internal_a_tl
+    \tl_set:Nn \l_@@_internal_b_tl { \__kernel_tl_set:Nx #3 }
+    \exp_args:Nff \@@_put_item:nnNNNN
+      { \int_eval:n {#2} } { \seq_count:N #1 }
+      #1 \@@_pop_item_aux:w #4 \@@_pop_item:nn
+  }
+\cs_new_protected:Npn \@@_pop_item:nn #1#2
+  {
+    \if_meaning:w \prg_return_false: #2
+      \l_@@_internal_b_tl { \exp_not:N \q_no_value }
+    \fi:
+    #2
+  }
+\cs_new:Npn \@@_pop_item_aux:w \@@_item:n #1
+  {
+    \if_false: { \fi: }
+    \l_@@_internal_b_tl { \if_false: } \fi: \exp_not:n {#1}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \subsection{Additions to \pkg{l3sys}}
 %
 %    \begin{macrocode}
diff --git a/l3kernel/testfiles/m3seq005.lvt b/l3kernel/testfiles/m3seq005.lvt
index 35b93c065..499615262 100644
--- a/l3kernel/testfiles/m3seq005.lvt
+++ b/l3kernel/testfiles/m3seq005.lvt
@@ -90,4 +90,47 @@
     \seq_gput_item:NnnTF \g_tmpa_seq { 5 } { #\par } { \TRUE } { \FALSE } \seq_show:N \g_tmpa_seq
   }
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\TEST { seq_pop_item:NnN }
+  {
+    \cs_set_protected:Npn \test_log: { \seq_log:N \l_tmpa_seq \tl_log:N \l_tmpa_tl }
+    %
+    \seq_clear:N \l_tmpa_seq
+    \tl_clear:N \l_tmpa_tl
+    \seq_pop_item:NnN \l_tmpa_seq { 0 } \l_tmpa_tl \test_log:
+    \tl_clear:N \l_tmpa_tl
+    \seq_pop_item:cnN { l_tmpa_seq } { 1 } \l_tmpa_tl \test_log:
+    \tl_clear:N \l_tmpa_tl
+    \seq_pop_item:cnNTF { l_tmpa_seq } { -11 } \l_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    %
+    \SEPARATOR
+    \tl_clear:N \l_tmpa_tl
+    \seq_put_right:Nn \l_tmpa_seq { \AAA }
+    \seq_put_right:Nn \l_tmpa_seq { \BBB }
+    \seq_pop_item:cnN { l_tmpa_seq } { 0 } \l_tmpa_tl \test_log:
+    \group_begin:
+      \seq_pop_item:NnN \l_tmpa_seq { 1 } \l_tmpa_tl \test_log:
+    \group_end:
+    \seq_pop_item:cnNTF { l_tmpa_seq } { 0 } \l_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    \seq_pop_item:NnNTF \l_tmpa_seq { 2+3-4 } \g_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    \tl_log:N \g_tmpa_tl
+    \seq_gpop_item:cnNTF { l_tmpa_seq } { -1 } \l_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    %
+    \SEPARATOR
+    \cs_set_protected:Npn \test_log: { \seq_log:N \g_tmpa_seq \tl_log:N \l_tmpa_tl }
+    \seq_gset_split:Nnn \g_tmpa_seq { } { { \AAA } { \B\B } { { } } { # } }
+    \tl_clear:N \l_tmpa_tl
+    \seq_gpop_item:cnN { g_tmpa_seq } { 0 } \l_tmpa_tl \test_log:
+    \seq_gpop_item:NnN \g_tmpa_seq { 1 } \l_tmpa_tl \test_log:
+    \group_begin:
+      \seq_gpop_item:cnN { g_tmpa_seq } { 1+2-5 } \l_tmpa_tl \test_log:
+      \seq_gpop_item:NnNTF \g_tmpa_seq { 0 } \l_tmpa_tl { \TRUE } { \FALSE } \test_log:
+      \seq_gpop_item:cnNTF { g_tmpa_seq } { -1 } \l_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    \group_end:
+    \seq_gpop_item:NnNTF \g_tmpa_seq { 5 } \l_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    \seq_gpop_item:NnNTF \g_tmpa_seq { 1 } \g_tmpa_tl { \TRUE } { \FALSE } \test_log:
+    \tl_show:N \g_tmpa_tl
+  }
+
 \END
diff --git a/l3kernel/testfiles/m3seq005.tlg b/l3kernel/testfiles/m3seq005.tlg
index a6f025ae5..7e6b958f7 100644
--- a/l3kernel/testfiles/m3seq005.tlg
+++ b/l3kernel/testfiles/m3seq005.tlg
@@ -144,3 +144,93 @@ The sequence \g_tmpa_seq contains the items (without outer braces):
 <recently read> }
 l. ...  }
 ============================================================
+============================================================
+TEST 4: seq_pop_item:NnN
+============================================================
+The sequence \l_tmpa_seq is empty
+> .
+> \l_tmpa_tl=\q_no_value .
+The sequence \l_tmpa_seq is empty
+> .
+> \l_tmpa_tl=\q_no_value .
+FALSE
+The sequence \l_tmpa_seq is empty
+> .
+> \l_tmpa_tl=\q_no_value .
+============================================================
+The sequence \l_tmpa_seq contains the items (without outer braces):
+>  {\AAA }
+>  {\BBB }.
+> \l_tmpa_tl=\q_no_value .
+The sequence \l_tmpa_seq contains the items (without outer braces):
+>  {\BBB }.
+> \l_tmpa_tl=\AAA .
+FALSE
+The sequence \l_tmpa_seq contains the items (without outer braces):
+>  {\AAA }
+>  {\BBB }.
+> \l_tmpa_tl=\q_no_value .
+! LaTeX3 Error: Inconsistent local/global assignment
+For immediate help type H <return>.
+ ...                                              
+l. ...  }
+This is a coding error.
+Local assignment to a global variable '\g_tmpa_tl'.
+TRUE
+The sequence \l_tmpa_seq contains the items (without outer braces):
+>  {\BBB }.
+> \l_tmpa_tl=\q_no_value .
+> \g_tmpa_tl=\AAA .
+! LaTeX3 Error: Inconsistent local/global assignment
+For immediate help type H <return>.
+ ...                                              
+l. ...  }
+This is a coding error.
+Global assignment to a local variable '\l_tmpa_seq'.
+TRUE
+The sequence \l_tmpa_seq is empty
+> .
+> \l_tmpa_tl=\BBB .
+============================================================
+The sequence \g_tmpa_seq contains the items (without outer braces):
+>  {\AAA }
+>  {\B \B }
+>  {{}}
+>  {##}.
+> \l_tmpa_tl=\q_no_value .
+The sequence \g_tmpa_seq contains the items (without outer braces):
+>  {\B \B }
+>  {{}}
+>  {##}.
+> \l_tmpa_tl=\AAA .
+The sequence \g_tmpa_seq contains the items (without outer braces):
+>  {\B \B }
+>  {##}.
+> \l_tmpa_tl={}.
+FALSE
+The sequence \g_tmpa_seq contains the items (without outer braces):
+>  {\B \B }
+>  {##}.
+> \l_tmpa_tl=\q_no_value .
+TRUE
+The sequence \g_tmpa_seq contains the items (without outer braces):
+>  {\B \B }.
+> \l_tmpa_tl=##.
+FALSE
+The sequence \g_tmpa_seq contains the items (without outer braces):
+>  {\B \B }.
+> \l_tmpa_tl=\q_no_value .
+! LaTeX3 Error: Inconsistent local/global assignment
+For immediate help type H <return>.
+ ...                                              
+l. ...  }
+This is a coding error.
+Local assignment to a global variable '\g_tmpa_tl'.
+TRUE
+The sequence \g_tmpa_seq is empty
+> .
+> \l_tmpa_tl=\q_no_value .
+> \g_tmpa_tl=\B \B .
+<recently read> }
+l. ...  }
+============================================================





More information about the latex3-commits mailing list.