texlive[63468] Master/texmf-dist: tabularray (1jun22)

commits+karl at tug.org commits+karl at tug.org
Wed Jun 1 22:08:23 CEST 2022


Revision: 63468
          http://tug.org/svn/texlive?view=revision&revision=63468
Author:   karl
Date:     2022-06-01 22:08:22 +0200 (Wed, 01 Jun 2022)
Log Message:
-----------
tabularray (1jun22)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.pdf
    trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex
    trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty

Modified: trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex	2022-06-01 20:08:07 UTC (rev 63467)
+++ trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex	2022-06-01 20:08:22 UTC (rev 63468)
@@ -1,7 +1,7 @@
 % -*- coding: utf-8 -*-
 % !TEX program = lualatex
 \documentclass[oneside]{book}
-\newcommand*{\myversion}{2022A}
+\newcommand*{\myversion}{2022B}
 \newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
 
 \usepackage[a4paper,margin=2.5cm]{geometry}
@@ -18,7 +18,7 @@
 \usepackage[firstpage=true]{background}
 \backgroundsetup{contents={}}
 
-\UseTblrLibrary{amsmath,booktabs,counter,diagbox,siunitx,varwidth}
+\UseTblrLibrary{amsmath,booktabs,counter,diagbox,functional,siunitx,varwidth}
 
 \usepackage{hyperref}
 \hypersetup{
@@ -2463,7 +2463,7 @@
 \end{tblr}
 \end{demohigh}
 
-From version \verb!2021N!, trim options (\verb!l!, \verb!r!, \verb!lr!)
+From version 2021N (2021-09-01), trim options (\verb!l!, \verb!r!, \verb!lr!)
 for \verb!\cmidrule! command are also supported.
 
 \begin{demohigh}
@@ -2541,7 +2541,8 @@
 \end{booktabs}
 \end{demohigh}
 
-From version 2022A, there is a \verb!longtabs! environment for writing long \verb!booktabs! tables,
+From version 2022A (2022-03-01), there is a \verb!longtabs! environment
+for writing long \verb!booktabs! tables,
 and a \verb!talltabs! environment for writing tall \verb!booktabs! tables.
 
 \section{Library \texttt{counter}}
@@ -2594,6 +2595,228 @@
 \end{tblr}$
 \end{demohigh}
 
+\section{Library \texttt{functional}}
+
+With \verb!\UseTblrLibrary{functional}! in the preamble of the document,
+\verb!tabularray! will load \href{https://ctan.org/pkg/functional}{\texttt{functional}} package,
+and define outer key \verb!evaluate! and inner key \verb!process!.
+These two new keys are useful for doing functional programming inside tables.
+
+\subsection{Outer key \texttt{evaluate} in action}
+
+With outer key \verb!evaluate!, you can evaluate every occurrence of a specified protected function
+(defined with \verb!\prgNewFunction!) and replace it with the return value before splitting the table body.
+
+The first application of \verb!evaluate! key is for inputting files inside tables.
+Assume you have two files \verb!test1.tmp! and \verb!test2.tmp! with the following contents:
+
+\begin{filecontents*}[overwrite]{test1.tmp}
+Some & Some \\
+\end{filecontents*}
+\begin{filecontents*}[overwrite]{test2.tmp}
+Other & Other \\
+\end{filecontents*}
+
+\begin{codehigh}
+\begin{filecontents*}[overwrite]{test1.tmp}
+Some & Some \\
+\end{filecontents*}
+\end{codehigh}
+
+\begin{codehigh}
+\begin{filecontents*}[overwrite]{test2.tmp}
+Other & Other \\
+\end{filecontents*}
+\end{codehigh}
+
+Then you can input them with outer specification \verb!evaluate=\fileInput!.
+The \verb!\fileInput! function is provided by \verb!functional! package.
+
+\begin{demohigh}
+\begin{tblr}[evaluate=\fileInput]{hlines}
+  Row1 & 1 \\
+  \fileInput{test1.tmp}
+  Row3 & 3 \\
+  \fileInput{test2.tmp}
+  Row5 & 5 \\
+\end{tblr}
+\end{demohigh}
+
+In general, you can define your functions which return parts of table contents,
+and use \verb!evaluate! key to evaluate them inside tables.
+
+\begin{demohigh}
+\IgnoreSpacesOn
+\prgNewFunction \someFunc {m} {
+  \prgReturn {#1 & #1 \\}
+}
+\IgnoreSpacesOff
+\begin{tblr}[evaluate=\someFunc]{hlines}
+  Row1 & 1 \\
+  \someFunc{Text}
+  Row3 & 3 \\
+  \someFunc{Text}
+  Row5 & 5 \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\IgnoreSpacesOn
+\prgNewFunction \otherFunc {} {
+  \prgReturn {Other & Other \\}
+}
+\IgnoreSpacesOff
+\begin{tblr}[evaluate=\otherFunc]{hlines}
+  Row1 & 1 \\
+  \otherFunc
+  Row3 & 3 \\
+  \otherFunc
+  Row5 & 5 \\
+\end{tblr}
+\end{demohigh}
+
+You can even generate the whole table with some function.
+
+\begin{demohigh}
+\IgnoreSpacesOn
+\prgNewFunction \makeEmptyTable {mm}  {
+  \tlSet \lTmpaTl {\intReplicate {\intEval{#2-1}} {&}}
+  \tlPutRight \lTmpaTl {\\}
+  \intReplicate {#1} {\tlUse \lTmpaTl}
+}
+\IgnoreSpacesOff
+\begin{tblr}[evaluate=\makeEmptyTable]{hlines,vlines}
+  \makeEmptyTable{3}{7}
+\end{tblr}
+\end{demohigh}
+
+\subsection{Inner key \texttt{process} in action}
+
+With inner key \verb!process!, you can modify the contents and styles before the table is built.
+Several public functions defined with \verb!\prgNewFuncton! are provided for you:
+
+\begin{itemize}
+  \item \verb!\cellGetText{<rownum>}{<colnum>}!
+  \item \verb!\cellSetText{<rownum>}{<colnum>}{<text>}!
+  \item \verb!\cellSetStyle{<rownum>}{<colnum>}{<style>}!
+  \item \verb!\rowSetStyle{<rownum>}{<style>}!
+  \item \verb!\columnSetStyle{<colnum>}{<style>}!
+\end{itemize}
+
+As the first example, let's calculate the sums of cells column by column:
+
+\IgnoreSpacesOn
+\prgNewFunction \funcSum {} {
+  \intStepOneInline {1} {\arabic{colcount}} {
+    \intZero \lTmpaInt
+    \intStepOneInline {1} {\arabic{rowcount}-1} {
+      \intAdd \lTmpaInt {\cellGetText {####1} {##1}}
+    }
+    \cellSetText {\expWhole{\arabic{rowcount}}} {##1} {\intUse\lTmpaInt}
+  }
+}
+\IgnoreSpacesOff
+\begin{codehigh}
+\IgnoreSpacesOn
+\prgNewFunction \funcSum {} {
+  \intStepOneInline {1} {\arabic{colcount}} {
+    \intZero \lTmpaInt
+    \intStepOneInline {1} {\arabic{rowcount}-1} {
+      \intAdd \lTmpaInt {\cellGetText {####1} {##1}}
+    }
+    \cellSetText {\expWhole{\arabic{rowcount}}} {##1} {\intUse\lTmpaInt}
+  }
+}
+\IgnoreSpacesOff
+\end{codehigh}
+
+\begin{demohigh}
+\begin{tblr}{colspec={rrr},process=\funcSum}
+\hline
+  1 & 2 & 3 \\
+  4 & 5 & 6 \\
+  7 & 8 & 9 \\
+\hline
+    &   &   \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+Now, let's set background colors of cells depending on their contents:
+
+\IgnoreSpacesOn
+\prgNewFunction \funcColor {} {
+  \intStepOneInline {1} {\arabic{rowcount}} {
+    \intStepOneInline {1} {\arabic{colcount}} {
+      \intSet \lTmpaInt {\cellGetText {##1} {####1}}
+      \intCompareTF {\lTmpaInt} > {0}
+        {\cellSetStyle {##1} {####1} {bg=purple8}}
+        {\cellSetStyle {##1} {####1} {bg=olive8}}
+    }
+  }
+}
+\IgnoreSpacesOff
+\begin{codehigh}
+\IgnoreSpacesOn
+\prgNewFunction \funcColor {} {
+  \intStepOneInline {1} {\arabic{rowcount}} {
+    \intStepOneInline {1} {\arabic{colcount}} {
+      \intSet \lTmpaInt {\cellGetText {##1} {####1}}
+      \intCompareTF {\lTmpaInt} > {0}
+        {\cellSetStyle {##1} {####1} {bg=purple8}}
+        {\cellSetStyle {##1} {####1} {bg=olive8}}
+    }
+  }
+}
+\IgnoreSpacesOff
+\end{codehigh}
+
+\begin{demohigh}
+\begin{tblr}{hlines,vlines,cells={r,$},process=\funcColor}
+  -1 &  2 &  3 \\
+   4 &  5 & -6 \\
+   7 & -8 &  9 \\
+\end{tblr}
+\end{demohigh}
+
+We can also use color series of \verb!xcolor! package to color table rows:
+
+\definecolor{lightb}{RGB}{217,224,250}
+\definecolorseries{tblrow}{rgb}{last}{lightb}{white}
+\resetcolorseries[3]{tblrow}
+\IgnoreSpacesOn
+\prgNewFunction \funcSeries {} {
+  \intStepOneInline {1} {\arabic{rowcount}} {
+    \tlSet \lTmpaTl {\intMathMod {##1-1} {3}}
+    \rowSetStyle {##1} {\expWhole{bg=tblrow!![\lTmpaTl]}}
+  }
+}
+\IgnoreSpacesOff
+\begin{codehigh}
+\definecolor{lightb}{RGB}{217,224,250}
+\definecolorseries{tblrow}{rgb}{last}{lightb}{white}
+\resetcolorseries[3]{tblrow}
+\IgnoreSpacesOn
+\prgNewFunction \funcSeries {} {
+  \intStepOneInline {1} {\arabic{rowcount}} {
+    \tlSet \lTmpaTl {\intMathMod {##1-1} {3}}
+    \rowSetStyle {##1} {\expWhole{bg=tblrow!![\lTmpaTl]}}
+  }
+}
+\IgnoreSpacesOff
+\end{codehigh}
+
+\begin{demohigh}
+\begin{tblr}{hlines,process=\funcSeries}
+  Row1 & 1 \\
+  Row2 & 2 \\
+  Row3 & 3 \\
+  Row4 & 4 \\
+  Row5 & 5 \\
+  Row6 & 6 \\
+\end{tblr}
+\end{demohigh}
+
 \section{Library \texttt{siunitx}}
 
 When writing \verb!\UseTblrLibrary{siunitx}! in the preamble of the document,
@@ -2603,7 +2826,7 @@
 \begin{demohigh}
 \begin{tblr}{
   hlines, vlines,
-  colspec={S[table-format=3.2]S[table-format=3.2]},
+  colspec={S[table-format=3.2]S[table-format=3.2]}
 }
  {{{Head}}} & {{{Head}}} \\
    111      &   111      \\
@@ -2624,8 +2847,24 @@
 \end{tblr}
 \end{demohigh}
 
-Note that you need to use \underline{\color{red3}triple} pairs of braces to guard non-numeric cells.
+Note that you need to use \underline{\color{red3}triple} pairs of curly braces to guard non-numeric cells.
+But it is cumbersome to enclose each cell with braces. From version 2022B (2022-06-01)
+a new key \verb!guard! is provided for cells and rows. With \verb!guard! key the previous example
+can be largely simplified.
 
+\begin{demohigh}
+\begin{tblr}{
+  hlines, vlines,
+  colspec={Q[si={table-format=3.2},c]Q[si={table-format=3.2},c]},
+  row{1} = {guard}
+}
+   Head  & Head   \\
+  111    & 111    \\
+    2.1  &   2.2  \\
+   33.11 &  33.22 \\
+\end{tblr}
+\end{demohigh}
+
 Also you must use \verb!l!, \verb!c! or \verb!r! to set horizontal alignment for non-numeric cells:
 \nopagebreak
 \begin{demohigh}
@@ -2635,12 +2874,13 @@
     Q[si={table-format=3.2,table-number-alignment=left},l,blue7]
     Q[si={table-format=3.2,table-number-alignment=center},c,teal7]
     Q[si={table-format=3.2,table-number-alignment=right},r,purple7]
-  }
+  },
+  row{1} = {guard}
 }
- {{{Head}}} & {{{Head}}} & {{{Head}}} \\
-   111      &   111      &   111      \\
-     2.1    &     2.2    &     2.3    \\
-    33.11   &    33.22   &    33.33   \\
+  Head  & Head   & Head   \\
+ 111    & 111    & 111    \\
+   2.1  &   2.2  &   2.3  \\
+  33.11 &  33.22 &  33.33 \\
 \end{tblr}
 \end{demohigh}
 
@@ -2673,7 +2913,7 @@
 \end{tblr}
 \end{demohigh}
 
-From version 2022A, you can remove extra space above and below lists,
+From version 2022A (2022-03-01), you can remove extra space above and below lists,
 by adding option \verb!stretch=-1!.
 The following example also needs \verb!enumitem! package and its \verb!nosep! option:
 

Modified: trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty	2022-06-01 20:08:07 UTC (rev 63467)
+++ trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty	2022-06-01 20:08:22 UTC (rev 63468)
@@ -12,11 +12,11 @@
 
 %% \DeclareRelease and \DeclareCurrentRelease are added in LaTeX 2018-04-01
 \NeedsTeXFormat{LaTeX2e}[2018-04-01]
-\DeclareRelease{v2021}{}{tabularray-2021.sty}
+\DeclareRelease{v2021}{2021-01-01}{tabularray-2021.sty}
 \DeclareCurrentRelease{}{2022-01-01}
 
 \RequirePackage{expl3}
-\ProvidesExplPackage{tabularray}{2022-03-01}{2022A}
+\ProvidesExplPackage{tabularray}{2022-06-01}{2022B}
   {Typeset tabulars and arrays with LaTeX3}
 
 %% \IfFormatAtLeastTF, xparse and lthooks are added in LaTeX 2020-10-01
@@ -2594,7 +2594,6 @@
     \tl_new:c { l__tblr_default_ #1 _inner_tl }
     \tl_new:c { l__tblr_default_ #1 _outer_tl }
     \tl_set_eq:cN { l__tblr_default_ #1 _outer_tl } \l__tblr_initial_tblr_outer_tl
-    \ignorespaces
   }
 
 %% Create tblr and longtblr environments
@@ -2608,8 +2607,11 @@
 \bool_new:N \l__tblr_math_mode_bool
 
 %% Main environment code
+%% We need to add \group_align_safe_begin: and \group_align_safe_end:
+%% to make tabularray correctly nest in align environment (see issue #143)
 \cs_new_protected:Npn \__tblr_environ_code:nnnn #1 #2 #3 #4
   {
+    \group_align_safe_begin:
     \int_gincr:N \g__tblr_table_count_int
     \tl_set:Nn \l__tblr_env_name_tl {#1}
     \mode_if_math:TF
@@ -2616,6 +2618,7 @@
       { \bool_set_true:N \l__tblr_math_mode_bool }
       { \bool_set_false:N \l__tblr_math_mode_bool }
     \__tblr_builder:nnn {#2} {#3} {#4}
+    \group_align_safe_end:
   }
 
 %% Read, split and build the table
@@ -2643,6 +2646,7 @@
     \LogTblrTracing { step = execute ~ table ~ commands}
     \__tblr_execute_table_commands:
     \__tblr_disable_table_commands:
+    \__tblr_functional_calculation:
     \LogTblrTracing { step = calculate ~ cell ~ and ~ line ~ sizes}
     \__tblr_enable_content_commands:
     \__tblr_calc_cell_and_line_sizes:
@@ -2686,39 +2690,52 @@
   }
 
 \tl_new:N \l__tblr_body_tl
-\tl_new:N \l__tblr_expand_tl
 \seq_new:N \l__tblr_lines_seq
 
+%% Split table content to cells and store them
+%% #1: table content
+\cs_new_protected:Npn \__tblr_split_table:n #1
+  {
+    \tl_set:Nn \l__tblr_body_tl {#1}
+    \tblr_modify_table_body:
+    \int_zero:N \c at rowcount
+    \int_zero:N \c at colcount
+    \__tblr_split_table_to_lines:NN \l__tblr_body_tl \l__tblr_lines_seq
+    \__tblr_split_lines_to_cells:N \l__tblr_lines_seq
+  }
+
+\tl_new:N \l__tblr_expand_tl
+
+\cs_set_eq:NN \__tblr_hook_split_before: \prg_do_nothing:
+
+\cs_new_protected:Npn \tblr_modify_table_body:
+  {
+    \__tblr_hook_split_before:
+    \tl_set:Nx \l__tblr_expand_tl { \__tblr_spec_item:nn { outer } { expand } }
+    \tl_set:Nx \l__tblr_expand_tl { \tl_head:N \l__tblr_expand_tl }
+    \tl_if_empty:NF \l__tblr_expand_tl
+      {
+        \exp_last_unbraced:NNV
+        \__tblr_expand_table_body:NN \l__tblr_body_tl \l__tblr_expand_tl
+      }
+  }
+
 %% Expand every occurrence of the specified macro once
-%% #1: table content; #2: macro to be expanded
-\cs_new_protected:Npn \__tblr_expand_table_body:nN #1 #2
+%% #1: tl with table content; #2: macro to be expanded
+\cs_new_protected:Npn \__tblr_expand_table_body:NN #1 #2
   {
-    \tl_clear:N \l__tblr_body_tl
+    \tl_set_eq:NN \l_tmpa_tl #1
+    \tl_clear:N #1
     \cs_set_protected:Npn \__tblr_expand_table_body_aux:w ##1 #2
       {
-        \tl_put_right:Nn \l__tblr_body_tl {##1}
+        \tl_put_right:Nn #1 {##1}
         \peek_meaning:NTF \q_stop
           { \use_none:n }
           { \exp_last_unbraced:NV \__tblr_expand_table_body_aux:w #2 }
       }
-    \__tblr_expand_table_body_aux:w #1 #2 \q_stop
+    \exp_last_unbraced:NV \__tblr_expand_table_body_aux:w \l_tmpa_tl #2 \q_stop
   }
 
-%% Split table content to cells and store them
-%% #1: table content
-\cs_new_protected:Npn \__tblr_split_table:n #1
-  {
-    \tl_set:Nx \l__tblr_expand_tl { \__tblr_spec_item:nn { outer } { expand } }
-    \tl_set:Nx \l__tblr_expand_tl { \tl_head:N \l__tblr_expand_tl }
-    \tl_if_empty:NTF \l__tblr_expand_tl
-      { \tl_set:Nn \l__tblr_body_tl {#1} }
-      { \exp_args:NnV \__tblr_expand_table_body:nN {#1} \l__tblr_expand_tl }
-    \int_zero:N \c at rowcount
-    \int_zero:N \c at colcount
-    \__tblr_split_table_to_lines:NN \l__tblr_body_tl \l__tblr_lines_seq
-    \__tblr_split_lines_to_cells:N \l__tblr_lines_seq
-  }
-
 %% Split table content to a sequence of lines
 %% #1: tl with table contents, #2: resulting sequence of lines
 \cs_new_protected:Npn \__tblr_split_table_to_lines:NN #1 #2
@@ -5231,14 +5248,18 @@
     %% \l__tblr_row_head_tl and \l__tblr_row_foot_tl may be empty
     \tl_set:Nx \l__tblr_row_head_tl { \__tblr_prop_item:ne { inner } { rowhead } }
     \int_compare:nNnTF { \l__tblr_row_head_tl + 0 } > { 0 }
-      { \__tblr_build_one_table:nn {1} { \l__tblr_row_head_tl } }
+      {
+        \__tblr_build_one_table:nnNN {1} { \l__tblr_row_head_tl }
+          \c_true_bool \c_true_bool
+      }
       { \__tblr_build_one_hline:n {1} }
     \box_set_eq:NN \l__tblr_row_head_box \l__tblr_table_box
     \tl_set:Nx \l__tblr_row_foot_tl { \__tblr_prop_item:ne { inner } { rowfoot } }
     \int_compare:nNnTF { \l__tblr_row_foot_tl + 0 } > { 0 }
       {
-        \__tblr_build_one_table:nn
+        \__tblr_build_one_table:nnNN
           { \c at rowcount - \l__tblr_row_foot_tl + 1 } { \c at rowcount }
+          \c_true_bool \c_true_bool
       }
       { \__tblr_build_one_hline:n { \int_eval:n { \c at rowcount + 1 } } }
     \box_set_eq:NN \l__tblr_row_foot_box \l__tblr_table_box
@@ -5401,6 +5422,7 @@
   {
     \LogTblrTracing { page }
     \par
+    \skip_zero:N \parskip % see issue #203
     \LogTblrTracing { page }
     \dim_compare:nNnTF { \pagegoal } = { \maxdimen }
       { \hbox{}\kern-\topskip\nobreak }
@@ -5578,9 +5600,7 @@
 %% #1: table alignment; #2: row from; #3: row to
 \cs_new_protected:Npn \__tblr_build_page_table:nnn #1 #2 #3
   {
-    \bool_set_false:N \l__tblr_build_first_hline_bool
-    \bool_set_false:N \l__tblr_build_last_hline_bool
-    \__tblr_build_one_table:nn {#2} {#3}
+    \__tblr_build_one_table:nnNN {#2} {#3} \c_false_bool \c_false_bool
     \vbox_set:Nn \l__tblr_table_box
       {
         \box_use:N \l__tblr_table_head_box
@@ -5628,7 +5648,7 @@
   {
     \mode_leave_vertical:
     \__tblr_build_tall_table_head_foot:
-    \__tblr_build_one_table:nn {1} {\c at rowcount}
+    \__tblr_build_one_table:nnNN {1} {\c at rowcount} \c_true_bool \c_true_bool
     \vbox_set:Nn \l__tblr_table_box
       {
         \box_use:N \l__tblr_table_firsthead_box
@@ -5646,23 +5666,20 @@
 \cs_new_protected:Npn \__tblr_build_short_table:n #1
   {
     \mode_leave_vertical:
-    \__tblr_build_one_table:nn {1} {\c at rowcount}
+    \__tblr_build_one_table:nnNN {1} {\c at rowcount} \c_true_bool \c_true_bool
     \__tblr_valign_whole:Nn \l__tblr_table_box {#1}
   }
 \cs_generate_variant:Nn \__tblr_build_short_table:n { e }
 
-\bool_new:N \l__tblr_build_first_hline_bool
-\bool_new:N \l__tblr_build_last_hline_bool
-\bool_set_true:N \l__tblr_build_first_hline_bool
-\bool_set_true:N \l__tblr_build_last_hline_bool
 \box_new:N \l__tblr_table_hlines_box
 \box_new:N \l__tblr_hline_box
 \box_new:N \l__tblr_row_box
 
 %% #1: row from; #2: row to
+%% #3: whether build first hline or not; #4: whether build last hline or not
 %% To fix disappeared hlines with colorful tables in Adobe Reader (see #76),
 %% we collect all hlines and draw them at the end of the table.
-\cs_new_protected:Npn \__tblr_build_one_table:nn #1 #2
+\cs_new_protected:Npn \__tblr_build_one_table:nnNN #1 #2 #3 #4
   {
     \box_clear:N \l__tblr_table_hlines_box
     \vbox_set:Nn \l__tblr_table_box
@@ -5671,13 +5688,13 @@
           {
             \bool_lazy_or:nnT
               { \int_compare_p:nNn { \l__tblr_i_tl } > {#1} }
-              { \bool_if_p:N \l__tblr_build_first_hline_bool }
+              { \bool_if_p:N #3 }
               { \__tblr_put_one_hline:n { \__tblr_build_hline:V \l__tblr_i_tl } }
             \hrule height ~ 0pt % remove lineskip between hlines and rows
             \__tblr_put_one_row:n { \__tblr_build_row:N \l__tblr_i_tl }
             \hrule height ~ 0pt
           }
-        \bool_if:NT \l__tblr_build_last_hline_bool
+        \bool_if:NT #4
           {
             \__tblr_put_one_hline:n
               { \__tblr_build_hline:n { \int_eval:n {#2 + 1} } }
@@ -5689,8 +5706,6 @@
           }
         \box_use:N \l__tblr_table_hlines_box
       }
-    \bool_set_true:N \l__tblr_build_first_hline_bool
-    \bool_set_true:N \l__tblr_build_last_hline_bool
   }
 
 \cs_new_protected:Npn \__tblr_put_one_hline:n #1
@@ -6962,6 +6977,81 @@
     \box_use:N \l__tblr_diag_box
   }
 
+%% Library functional with evaluate and process options
+
+\cs_set_eq:NN \__tblr_functional_calculation: \prg_do_nothing:
+
+\NewTblrLibrary { functional }
+  {
+    \RequirePackage { functional }
+    %% Add outer specification "evaluate"
+    \keys_define:nn { tblr-outer }
+      { evaluate .code:n = \__tblr_outer_gput_spec:nn { evaluate } {##1} }
+    \tl_new:N \l__tblr_evaluate_tl
+    \cs_set_protected:Npn \__tblr_hook_split_before:
+      {
+        \tl_set:Nx \l__tblr_evaluate_tl
+          { \__tblr_spec_item:nn { outer } { evaluate } }
+        \tl_set:Nx \l__tblr_evaluate_tl { \tl_head:N \l__tblr_evaluate_tl }
+        \tl_if_empty:NF \l__tblr_evaluate_tl
+          {
+            \exp_last_unbraced:NNV
+            \__tblr_evaluate_table_body:NN \l__tblr_body_tl \l__tblr_evaluate_tl
+          }
+      }
+    %% Evaluate every occurrence of the specified function
+    %% Note that funtional package runs every return processor inside a group
+    %% #1: tl with table content; #2: function to be evaluated
+    \tl_new:N \g__tblr_functional_result_tl
+    \cs_new_protected:Npn \__tblr_evaluate_table_body:NN ##1 ##2
+      {
+        \tl_gclear:N \g__tblr_functional_result_tl
+        \cs_set_protected:Npn \__tblr_evaluate_table_body_aux:w ####1 ##2
+          {
+            \tl_gput_right:Nn \g__tblr_functional_result_tl {####1}
+            \peek_meaning:NTF \q_stop { \use_none:n } {##2}
+          }
+        \fun_run_return_processor:nn
+          {
+            \exp_last_unbraced:NV \__tblr_evaluate_table_body_aux:w \gResultTl
+          }
+          {
+            \exp_last_unbraced:NV
+              \__tblr_evaluate_table_body_aux:w ##1 ##2 \q_stop
+          }
+        \tl_set_eq:NN ##1 \g__tblr_functional_result_tl
+      }
+    %% Add inner specification "process"
+    \clist_put_right:Nn \g__tblr_table_known_keys_clist { process }
+    \keys_define:nn { tblr }
+      { process .code:n = \__tblr_keys_gput:nn { process } {##1} }
+    \cs_set:Npn \__tblr_functional_calculation:
+      {
+        \LogTblrTracing { step = do ~ functional ~ calculation }
+        \__tblr_prop_item:nn { inner } { process }
+      }
+    \prgNewFunction \cellGetText { m m }
+      {
+        \expWhole { \__tblr_spec_item:nn { text } { [##1][##2] } }
+      }
+    \prgNewFunction \cellSetText { m m m }
+      {
+        \__tblr_spec_gput:nnn { text } { [##1][##2] } {##3}
+      }
+    \prgNewFunction \cellSetStyle { m m m }
+      {
+        \tblr_set_cell:nnnn {##1} {##2} {} {##3}
+      }
+    \prgNewFunction \rowSetStyle { m m }
+      {
+        \tblr_set_row:nnn {##1} {} {##2}
+      }
+    \prgNewFunction \columnSetStyle { m m }
+      {
+        \tblr_set_column:nnn {##1} {} {##2}
+      }
+  }
+
 %% Library siunitx and S columns
 
 \NewTblrLibrary { siunitx }
@@ -7003,6 +7093,9 @@
             \group_end:
           }
       }
+    \keys_define:nn { tblr-cell-spec } { guard .meta:n = { cmd = } }
+    \keys_define:nn { tblr-row }       { guard .meta:n = { cmd = } }
+    \keys_define:nn { tblr-column }    { guard .meta:n = { cmd = } }
   }
 
 %% Library varwidth and measure option
@@ -7013,4 +7106,3 @@
     \clist_gput_left:Nn \g__tblr_table_known_keys_clist { measure }
     \keys_define:nn { tblr } { measure .tl_set:N = \l__tblr_inner_spec_measure_tl }
   }
-



More information about the tex-live-commits mailing list.