Tabular Ray
Tabular Ray
Code https://github.com/lvjr/tabularray
Code https://bitbucket.org/lvjr/tabularray
Support https://github.com/lvjr/tabularray/discussions
Support https://topanswers.xyz/tex
Issue https://github.com/lvjr/tabularray/issues
\begin{tblr}{
colspec = {rX}, colsep = 8mm, hlines = {2pt, white},
row{odd} = {azure8}, row{even} = {gray8},
row{1} = {6em,azure2,fg=white,font=\LARGE\bfseries\sffamily},
row{2-Z} = {3em,font=\Large},
}
Tabularray & Typeset Tabulars and Arrays with \LaTeX3 \\
Author & Jianrui Lyu ([email protected]) \\
Version & \myversion\ (\the\year-\mylpad\month-\mylpad\day) \\
Code & \url{https://github.com/lvjr/tabularray} \\
Code & \url{https://bitbucket.org/lvjr/tabularray} \\
Support & \url{https://github.com/lvjr/tabularray/discussions} \\
Support & \url{https://topanswers.xyz/tex} \\
Issue & \url{https://github.com/lvjr/tabularray/issues} \\
\end{tblr}
Contents
1 Overview of Features 4
1.1 Vertical Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Multiline Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Cell Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Multirow Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Multi Rows and Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6 Column Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.7 Row Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.8 Hlines and Vlines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.9 Colorful Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2 Basic Interfaces 12
2.1 Old and New Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2 Hlines and Vlines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3 Hborders and Vborders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4 Cells and Spancells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.5 Rows and Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.6 Colspec and Rowspec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3 Extra Interfaces 26
3.1 Inner Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2 Outer Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3 Default Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.4 New Tabularray Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.5 New General Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.6 New Table Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.7 Odd and Even Selectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.8 Counters and Lengths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.9 Tracing Tabularray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
1
CONTENTS 2
Overview of Features
Before using tabularray package, it is better to know how to typeset simple text and math tables with
traditional tabular, tabularx and array environments, because we will compare tblr environment from
tabularray package with these environments. You may read web pages on LaTeX tables on LearnLaTeX
and Overleaf first.
\begin{tabular}{lccr}
\hline
Alpha & Beta & Gamma & Delta \\
\hline Alpha Beta Gamma Delta
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\hline Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\hline
\end{tabular}
\begin{tblr}{lccr}
\hline
Alpha & Beta & Gamma & Delta \\
Alpha Beta Gamma Delta
\hline
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\hline Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\hline
\end{tblr}
You may notice that there is extra space above and below the table rows with tblr environment. This
space makes the table look better. If you don’t like it, you could use \SetTblrInner command:
4
CHAPTER 1. OVERVIEW OF FEATURES 5
\SetTblrInner{rowsep=0pt}
\begin{tblr}{lccr}
\hline
Alpha & Beta & Gamma & Delta \\ Alpha Beta Gamma Delta
\hline
Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\
Iota Kappa Lambda Mu
\hline
Iota & Kappa & Lambda & Mu \\
\hline
\end{tblr}
$\begin{array}{rrr}
\hline 2 2 1
\dfrac{2}{3} & \dfrac{2}{3} & \dfrac{1}{3} \\ 3 3 3
2 1 2
\dfrac{2}{3} & -\dfrac{1}{3} & -\dfrac{2}{3} \\ − −
\dfrac{1}{3} & -\dfrac{2}{3} & \dfrac{2}{3} \\ 3 3 3
1 2 2
\hline −
3 3 3
\end{array}$
$\begin{tblr}{rrr}
2 2 1
\hline
3 3 3
\dfrac{2}{3} & \dfrac{2}{3} & \dfrac{1}{3} \\
2 1 2
\dfrac{2}{3} & -\dfrac{1}{3} & -\dfrac{2}{3} \\ − −
3 3 3
\dfrac{1}{3} & -\dfrac{2}{3} & \dfrac{2}{3} \\
1 2 2
\hline −
\end{tblr}$ 3 3 3
Note that you can use tblr in both text and math modes.
\begin{tblr}{|Q[l,t]|Q[c,m]|Q[r,b]|}
\hline
{Top Baseline \\ Left Left} & Middle Center & {Right Right \\ Bottom Baseline} \\
\hline
\end{tblr}
Right Right
Top Baseline Middle Center Bottom Baseline
Left Left
Note that you can use more meaningful t instead of p for top baseline alignment. For some users who are
familiar with word processors, these t and b columns are counter-intuitive. In tabularray package, there
are another two column types h and f, which will align cell text at the head and the foot, respectively:
\begin{tblr}{Q[h,4em]Q[t,4em]Q[m,4em]Q[b,4em]Q[f,4em]}
\hline
{row\\head} & {top\\line} & {middle} & {line\\bottom} & {row\\foot} \\
\hline
{row\\head} & {top\\line} & {11\\22\\mid\\44\\55} & {line\\bottom} & {row\\foot} \\
\hline
\end{tblr}
row line
head top middle bottom row
line foot
row 11
head 22 line
top mid bottom
line 44 row
55 foot
\begin{tabular}{|l|l|l|l|}
\hline
\multirow[t]{4}{1.5cm}{Multirow Cell One} & Alpha &
\multirow[b]{4}{1.5cm}{Multirow Cell Two} & Alpha \\
& Beta & & Beta \\
& Gamma & & Gamma \\
& Delta & & Delta \\
\hline
\end{tabular}
\begin{tblr}{|l|l|l|l|}
\hline
\SetCell[r=4]{h,1.5cm} Multirow Cell One & Alpha &
\SetCell[r=4]{f,1.5cm} Multirow Cell Two & Alpha \\
& Beta & & Beta \\
& Gamma & & Gamma \\
& Delta & & Delta \\
\hline
\end{tblr}
Note that you don’t need to load multirow package first, since tabularray doesn’t depend on it. Fur-
thermore, tabularray will always typeset decent multirow cells. First, it will set correct vertical middle
alignment, even though some rows have large height:
\begin{tabular}{|l|m{4em}|}
\hline Alpha
\multirow[c]{4}{1.5cm}{Multirow} & Alpha \\ Beta
Multirow
& Beta \\ Gamma
& Gamma \\ Delta
& Delta Delta Delta \\ Delta
\hline Delta
\end{tabular}
\begin{tblr}{|l|m{4em}|}
Alpha
\hline
\SetCell[r=4]{m,1.5cm} Multirow & Alpha \\ Beta
& Beta \\ Gamma
Multirow
& Gamma \\
Delta
& Delta Delta Delta \\
Delta
\hline
Delta
\end{tblr}
Second, it will enlarge row heights if the multirow cells have large height, therefore it always avoids
vertical overflow:
\begin{tabular}{|l|m{4em}|}
\hline
\multirow[c]{2}{1cm}{Line \\ Line \\ Line \\ Line} & Alpha \\
Line Alpha
\cline{2-2}
Line Beta
& Beta \\
Line
\hline
Line
\end{tabular}
\begin{tblr}{|l|m{4em}|}
\hline
Line Alpha
\SetCell[r=2]{m,1cm} {Line \\ Line \\ Line \\ Line} & Alpha \\
Line
\cline{2}
Line Beta
& Beta \\
Line
\hline
\end{tblr}
CHAPTER 1. OVERVIEW OF FEATURES 8
If you want to distribute extra vertical space evenly to two rows, you may use vspan option described in
Chapter 3.
\begin{tabular}{|c|c|c|c|c|}
\hline
\multirow{2}{*}{2 Rows}
& \multicolumn{2}{c|}{2 Columns}
& \multicolumn{2}{c|}{\multirow{2}{*}{2 Rows 2 Columns}} \\
\cline{2-3}
& 2-2 & 2-3 & \multicolumn{2}{c|}{} \\
\hline
3-1 & 3-2 & 3-3 & 3-4 & 3-5 \\
\hline
\end{tabular}
2 Columns
2 Rows 2 Rows 2 Columns
2-2 2-3
3-1 3-2 3-3 3-4 3-5
With tabularray package, you can set spanned cells with \SetCell command: within the optional
argument of \SetCell command, option r is for rowspan number, and c for colspan number; within the
mandatory argument of it, horizontal and vertical alignment options are accepted. Therefore it’s much
simpler to typeset spanned cells:
\begin{tblr}{|c|c|c|c|c|}
\hline
\SetCell[r=2]{c} 2 Rows
& \SetCell[c=2]{c} 2 Columns
& & \SetCell[r=2,c=2]{c} 2 Rows 2 Columns & \\
\hline
& 2-2 & 2-3 & & \\
\hline
3-1 & 3-2 & 3-3 & 3-4 & 3-5 \\
\hline
\end{tblr}
2 Columns
2 Rows 2 Rows 2 Columns
2-2 2-3
3-1 3-2 3-3 3-4 3-5
Using \multicolumn command, the omitted cells must be removed. On the contrary, using \multirow
command, the omitted cells must not be removed. \SetCell command behaves the same as \multirow
command in this aspect.
With tblr environment, any \hline segments inside a spanned cell will be ignored, therefore we’re free
to use \hline in the above example. Also, any omitted cell will definitely be ignored when typesetting,
no matter it’s empty or not. With this feature, we could put row and column numbers into the omitted
cells, which will help us to locate cells when the tables are rather complex:
CHAPTER 1. OVERVIEW OF FEATURES 9
\begin{tblr}{|ll|c|rr|}
\hline
\SetCell[r=3,c=2]{h} r=3 c=2 & 1-2 & \SetCell[r=2,c=3]{r} r=2 c=3 & 1-4 & 1-5 \\
2-1 & 2-2 & 2-3 & 2-4 & 2-5 \\
\hline
3-1 & 3-2 & MIDDLE & \SetCell[r=3,c=2]{f} r=3 c=2 & 3-5 \\
\hline
\SetCell[r=2,c=3]{l} r=2 c=3 & 4-2 & 4-3 & 4-4 & 4-5 \\
5-1 & 5-2 & 5-3 & 5-4 & 5-5 \\
\hline
\end{tblr}
\begin{tblr}{|X[2,l]|X[3,l]|X[1,r]|X[r]|}
\hline
Alpha & Beta & Gamma & Delta \\
\hline
\end{tblr}
\begin{tblr}{|X[2,l]|X[3,l]|X[-1,r]|X[r]|}
\hline
Alpha & Beta & Gamma & Delta \\
\hline
\end{tblr}
We need the width to typeset a table with X columns. If unset, the default is \linewidth. To change
the width, we have to first put all column specifications into colspec={...}:
\begin{tblr}{width=0.8\linewidth,colspec={|X[2,l]|X[3,l]|X[-1,r]|X[r]|}}
\hline
Alpha & Beta & Gamma & Delta \\
\hline
\end{tblr}
You can define new column types with \NewColumnType command. For example, in tabularray package,
b and X columns are defined as special Q columns:
\NewColumnType{b}[1]{Q[b,wd=#1]}
\NewColumnType{X}[1][]{Q[co=1,#1]}
CHAPTER 1. OVERVIEW OF FEATURES 10
\begin{tblr}{colspec={Q[l]Q[c]Q[r]},rowspec={|Q[t]|Q[m]|Q[b]|}}
{Alpha \\ Alpha} & Beta & Gamma \\
Delta & Epsilon & {Zeta \\ Zeta} \\
Eta & {Theta \\ Theta} & Iota \\
\end{tblr}
Same as column types, Q is the only primitive row type, and other row types are defined as Q types
with different options. It’s better to specify horizontal alignment in colspec, and vertical alignment in
rowspec, respectively.
Inside rowspec, | is the hline type. Therefore we need not to write \hline command, which makes table
code cleaner.
\begin{tblr}{|l|[dotted]|[2pt]c|r|[solid]|[dashed]|}
\hline
One & Two & Three \\ One Two Three
\hline\hline[dotted]\hline
Four & Five & Six \\ Four Five Six
\hline[dashed]\hline[1pt]
Seven & Eight & Nine \\ Seven Eight Nine
\hline
\end{tblr}
\begin{tblr}{colspec={lcr},rowspec={|Q[cyan7]|Q[azure7]|Q[blue7]|}}
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\
Iota & Kappa & Lambda \\
\end{tblr}
\begin{tblr}{colspec={Q[l,brown7]Q[c,yellow7]Q[r,olive7]},rowspec={|Q|Q|Q|}}
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\
Iota & Kappa & Lambda \\
\end{tblr}
Also you can use \SetRow or \SetColumn command to specify row or column colors:
\begin{tblr}{colspec={lcr},rowspec={|Q|Q|Q|}}
Alpha Beta Gamma
\SetRow{cyan7} Alpha & Beta & Gamma \\
\SetRow{azure7} Epsilon & Zeta & Eta \\ Epsilon Zeta Eta
\SetRow{blue7} Iota & Kappa & Lambda \\ Iota Kappa Lambda
\end{tblr}
\begin{tblr}{colspec={lcr},rowspec={|Q|Q|Q|}}
\SetColumn{brown7}
Alpha & \SetColumn{yellow7} Alpha Beta Gamma
Beta & \SetColumn{olive7}
Epsilon Zeta Eta
Gamma \\
Epsilon & Zeta & Eta \\ Iota Kappa Lambda
Iota & Kappa & Lambda \\
\end{tblr}
\begin{tblr}{colspec={lcr},rowspec={|[2pt,green7]Q|[teal7]Q|[green7]Q|[3pt,teal7]}}
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\
Iota & Kappa & Lambda \\
\end{tblr}
\begin{tblr}{colspec={|[2pt,violet5]l|[2pt,magenta5]c|[2pt,purple5]r|[2pt,red5]}}
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\
Iota & Kappa & Lambda \\
\end{tblr}
Basic Interfaces
12
CHAPTER 2. BASIC INTERFACES 13
\begin{tblr}{hlines,vlines}
Alpha Beta Gamma Delta
Alpha & Beta & Gamma & Delta \\
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\end{tblr}
With values inside one pair of braces, all hlines/vlines will be styled.
\begin{tblr}{
hlines = {1pt,solid}, vlines = {red3,dashed},
Alpha Beta Gamma Delta
}
Alpha & Beta & Gamma & Delta \\ Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\ Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\end{tblr}
\begin{tblr}{
vlines = {1,3,5}{dashed},
vlines = {2,4}{solid}, Alpha Beta Gamma Delta
} Epsilon Zeta Eta Theta
Alpha & Beta & Gamma & Delta \\
Iota Kappa Lambda Mu
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\ Nu Xi Omicron Pi
Nu & Xi & Omicron & Pi \\ Rho Sigma Tau Upsilon
Rho & Sigma & Tau & Upsilon \\
\end{tblr}
CHAPTER 2. BASIC INTERFACES 14
The above example can be simplified with odd and even values. (More child selectors can be defined
with \NewChildSelector command. Advanced users could read the source code for this.)
\begin{tblr}{
vlines = {odd}{dashed},
vlines = {even}{solid}, Alpha Beta Gamma Delta
} Epsilon Zeta Eta Theta
Alpha & Beta & Gamma & Delta \\
Iota Kappa Lambda Mu
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\ Nu Xi Omicron Pi
Nu & Xi & Omicron & Pi \\ Rho Sigma Tau Upsilon
Rho & Sigma & Tau & Upsilon \\
\end{tblr}
Another pair of braces before will draw more hlines/vlines (in which - stands for all line segments).
\begin{tblr}{
hlines = {1}{-}{dashed}, hlines = {2}{-}{solid}, Alpha Beta Gamma Delta
}
Alpha & Beta & Gamma & Delta \\ Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\
Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\end{tblr}
Note that you must use indexes in order: first 1, then 2, etc.
Options hline{i} and vline{j} are for setting some hlines and vlines, respectively. Their values are
the same as options hlines and vlines:
\begin{tblr}{
hline{1,7} = {1pt,solid},
hline{3-5} = {blue3,dashed}, Alpha Beta Gamma Delta
vline{1,5} = {3-4}{dotted}, Epsilon Zeta Eta Theta
}
Alpha & Beta & Gamma & Delta \\ Iota Kappa Lambda Mu
Epsilon & Zeta & Eta & Theta \\ Nu Xi Omicron Pi
Iota & Kappa & Lambda & Mu \\
Rho Sigma Tau Upsilon
Nu & Xi & Omicron & Pi \\
Rho & Sigma & Tau & Upsilon \\ Phi Chi Psi Omega
Phi & Chi & Psi & Omega \\
\end{tblr}
You can use U, V, W, X, Y, Z to denote the last six children, respectively. It is especially useful when you
are writing long tables:
\begin{tblr}{
hline{1,Z} = {2pt},
hline{2,Y} = {1pt}, Alpha Beta Gamma Delta
hline{3-X} = {dashed}, Epsilon Zeta Eta Theta
}
Alpha & Beta & Gamma & Delta \\ Iota Kappa Lambda Mu
Epsilon & Zeta & Eta & Theta \\ Nu Xi Omicron Pi
Iota & Kappa & Lambda & Mu \\
Rho Sigma Tau Upsilon
Nu & Xi & Omicron & Pi \\
Rho & Sigma & Tau & Upsilon \\ Phi Chi Psi Omega
Phi & Chi & Psi & Omega \\
\end{tblr}
CHAPTER 2. BASIC INTERFACES 15
\begin{tblr}{
vlines, hlines,
colspec = {lX[c]X[c]X[c]X[c]},
vline{2} = {1}{text=\clap{:}},
vline{3} = {1}{text=\clap{\ch{+}}},
vline{4} = {1}{text=\clap{\ch{->}}},
vline{5} = {1}{text=\clap{\ch{+}}},
}
Equation & \ch{CH4} & \ch{2 O2} & \ch{CO2} & \ch{2 H2O} \\
Initial & $n_1$ & $n_2$ & 0 & 0 \\
Final & $n_1-x$ & $n_2-2x$ & $x$ & $2x$ \\
\end{tblr}
The abovepos and belowpos keys for vlines have similar meanings. But their initial values are 0.
\begin{tblr}{
hline{1,4} = {1}{-}{},
hline{1,4} = {2}{-}{},
hline{2,3} = {1}{-}{leftpos = -1, rightpos = -1}, Alpha Beta Gamma
hline{2,3} = {2}{-}{leftpos = -1, rightpos = -1},
vline{1,4} = {abovepos = 1, belowpos = 1}, Epsilon Zeta Eta
}
Iota Kappa Lambda
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\
Iota & Kappa & Lambda \\
\end{tblr}
There is also an endpos option for adjusting leftpos/rightpos for only the leftmost/rightmost column:
1 Code from https://tex.stackexchange.com/questions/603023/tabularray-and-tabularx-column-separator.
CHAPTER 2. BASIC INTERFACES 16
\begin{tblr}{
hline{1,4} = {1}{-}{},
hline{1,4} = {2}{-}{},
hline{2,3} = {leftpos = -1, rightpos = -1, endpos}, Alpha Beta Gamma
vline{1,4} = {abovepos = 1, belowpos = 1},
Epsilon Zeta Eta
}
Alpha & Beta & Gamma \\ Iota Kappa Lambda
Epsilon & Zeta & Eta \\
Iota & Kappa & Lambda \\
\end{tblr}
\begin{tblr}{llll}
\hline
Alpha & Beta & Gamma & Delta \\
Alpha Beta Gamma Delta
\hline[dashed]
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\hline[dotted] Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\hline[2pt,blue5]
\end{tblr}
The \cline command also has an optional argument which is the same as \hline.
\begin{tblr}{llll}
\cline{1-4}
Alpha & Beta & Gamma & Delta \\
Alpha Beta Gamma Delta
\cline[dashed]{1,3}
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\cline[dashed]{2,4} Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\cline[2pt,blue5]{-}
\end{tblr}
\begin{tblr}{llll}
\cline{1-4}
Alpha & Beta & Gamma & Delta \\
Alpha Beta Gamma Delta
\cline[dashed]{odd}
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\cline[dashed]{even} Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\cline[2pt,blue5]{-}
\end{tblr}
\begin{tblr}{llll}
\SetHline{1-3}{blue5,1pt}
Alpha & Beta & Gamma & Delta \\ Alpha Beta Gamma Delta
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\SetHline{2-4}{teal5,1pt}
\end{tblr}
\begin{tblr}{llll}
\SetHline[1]{1-3}{blue5,1pt}
\SetHline[2]{1-3}{azure5,1pt}
Alpha & Beta & Gamma & Delta \\ Alpha Beta Gamma Delta
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\SetHline[1]{2-4}{teal5,1pt}
\SetHline[2]{2-4}{green5,1pt}
\end{tblr}
Furthermore, table command \hborder{<specs>} at the beginning of row i is the same as table option
hborder{i}={<specs>}, and table command \vborder{<specs>} at the beginning of column j is the
same as table option vborder{j}={<specs>}.
CHAPTER 2. BASIC INTERFACES 18
Option cell{i}{j} is for setting some cells, where i stands for the row numbers and j stands for the
column numbers.
\begin{tblr}{
cell{1}{2-4} = {cmd=\fbox}
} Alpha Beta Gamma Delta
Alpha & Beta & Gamma & Delta
\end{tblr}
CHAPTER 2. BASIC INTERFACES 19
\begin{tblr}{
hlines = {white},
vlines = {white},
cell{1,6}{odd} = {teal7},
cell{1,6}{even} = {green7}, Alpha Beta Gamma Delta
cell{2,4}{1,4} = {red7}, Epsilon Theta
cell{3,5}{1,4} = {purple7},
cell{2}{2} = {r=4,c=2}{c,azure7}, Iota Mu
Zeta
} Nu Pi
Alpha & Beta & Gamma & Delta \\
Rho Upsilon
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\ Phi Chi Psi Omega
Nu & Xi & Omicron & Pi \\
Rho & Sigma & Tau & Upsilon \\
Phi & Chi & Psi & Omega \\
\end{tblr}
\begin{tblr}{llll}
\hline[1pt]
Alpha & \SetCell{bg=teal2,fg=white} Beta & Gamma \\
Alpha Beta Gamma
\hline
Epsilon & Zeta & \SetCell{r,font=\scshape} Eta \\ Epsilon Zeta Eta
\hline Iota Kappa Lambda
Iota & Kappa & Lambda \\
\hline[1pt]
\end{tblr}
The \SetCell command also has an optional argument for setting the multispan of current cell. The
available keys are described in Table 2.7.
\begin{tblr}{|X|X|X|X|X|X|}
\hline
Alpha & Beta & Gamma & Delta & Epsilon & Zeta \\
\hline
\SetCell[c=2]{c} Eta & 2-2
& \SetCell[c=2]{c} Iota & 2-4
& \SetCell[c=2]{c} Lambda & 2-6 \\
\hline
\SetCell[c=3]{c} Nu & 3-2 & 3-3
& \SetCell[c=3]{c} Pi & 3-5 & 3-6 \\
\hline
\SetCell[c=6]{c} Tau & 4-2 & 4-3 & 4-4 & 4-5 & 4-6 \\
\hline
\end{tblr}
\begin{tblr}{|X|X|X|X|X|X|}
\hline
Alpha & Beta & Gamma & Delta & Epsilon & Zeta \\
\hline
\SetCell[r=2]{m} Eta
& Theta & Iota & Kappa & Lambda & \SetCell[r=2]{m} Mu \\
\hline
Nu & Xi & Omicron & Pi & Rho & Sigma \\
\hline
\end{tblr}
In fact, table command \SetCell[<span>]{<styles>} at the beginning of cell at row i and column j is
the same as table option cell{i}{j}={<span>}{<styles>}.
Also, table command \SetCells[<span>]{<styles>} at the beginning of some cell is the same as table
option cells={<span>}{<styles>}.
\begin{tblr}{
hlines, vlines,
Alpha Beta Gamma Delta
rows = {7mm}, columns = {15mm,c},
}
Epsilon Zeta Eta Theta
Alpha & Beta & Gamma & Delta \\
Epsilon & Zeta & Eta & Theta \\
Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\end{tblr}
Options row{i} and column{j} are for setting some rows and columns, respectively.
CHAPTER 2. BASIC INTERFACES 22
\begin{tblr}{
hlines = {1pt,white},
row{odd} = {blue7}, Alpha Beta Gamma Delta
row{even} = {azure7},
column{1} = {purple7,c}, Epsilon Zeta Eta Theta
} Iota Kappa Lambda Mu
Alpha & Beta & Gamma & Delta \\
Epsilon & Zeta & Eta & Theta \\ Nu Xi Omicron Pi
Iota & Kappa & Lambda & Mu \\ Rho Sigma Tau Upsilon
Nu & Xi & Omicron & Pi \\
Phi Chi Psi Omega
Rho & Sigma & Tau & Upsilon \\
Phi & Chi & Psi & Omega \\
\end{tblr}
The following example demonstrates the usages of bg, fg and font keys:
\begin{tblr}{
row{odd} = {bg=azure8},
row{1} = {bg=azure3, fg=white, font=\sffamily},
}
Alpha & Beta & Gamma \\
Delta & Epsilon & Zeta \\
Eta & Theta & Iota \\
Kappa & Lambda & Mu \\
Nu Xi Omicron & Pi Rho Sigma & Tau Upsilon Phi \\
\end{tblr}
$\begin{tblr}{
column{1} = {mode=text},
column{3} = {mode=dmath}, 1
Alpha 1
} 2 2
\hline 3
Epsilon 3
Alpha & \frac12 & \frac12 \\ 4 4
Epsilon & \frac34 & \frac34 \\ 5
Iota 5
Iota & \frac56 & \frac56 \\ 6 6
\hline
\end{tblr}$
The following example demonstrates the usages of abovesep, belowsep, leftsep, rightsep keys:
CHAPTER 2. BASIC INTERFACES 23
\begin{tblr}{
hlines, vlines,
rows = {abovesep=1pt,belowsep=5pt}, Alpha Beta Gamma Delta
columns = {leftsep=1pt,rightsep=5pt},
} Epsilon Zeta Eta Theta
Alpha & Beta & Gamma & Delta \\ Iota Kappa Lambda Mu
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\
\end{tblr}
The following example shows that we can replace \\[dimen] with belowsep+ key.
\begin{tblr}{
hlines, row{2} = {belowsep+=5pt}, Alpha Beta Gamma Delta
}
Alpha & Beta & Gamma & Delta \\ Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\
Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\end{tblr}
\begin{tblr}{llll}
\hline[1pt]
\SetRow{azure8} Alpha & Beta & Gamma & Delta \\
Alpha Beta Gamma Delta
\hline
\SetRow{blue8,c} Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\hline Iota Kappa Lambda Mu
\SetRow{violet8} Iota & Kappa & Lambda & Mu \\
\hline[1pt]
\end{tblr}
In fact, table command \SetRow{<styles>} at the beginning of row i is the same as table option
row{i}={<styles>}.
Also, table command \SetRows{<styles>} at the beginning of some row is the same as table option
rows={<styles>}.
The usages of table commands \SetColumn and \SetColumns are similar to those of \SetRow and
\SetRows, respectively. But normally you don’t need to use them.
\begin{tblr}{width=0.8\textwidth, colspec={|l|X[2]|X[3]|X[-1]|}}
Alpha & Beta & Gamma & Delta \\
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\
\end{tblr}
You can omit colspec name if it is the only key you use inside the mandatory argument. The following
example demonstrates the usages of $ and $$ keys:
\begin{tblr}{Q[l]Q[r,$]Q[r,$$]}
1
\hline Alpha 1
2 2
Alpha & \frac12 & \frac12 \\
3
Epsilon & \frac34 & \frac34 \\ Epsilon 3
4 4
Iota & \frac56 & \frac56 \\
5
\hline Iota 5
6
\end{tblr} 6
\NewColumnType{l}{Q[l]}
\NewColumnType{c}{Q[c]}
\NewColumnType{r}{Q[r]}
\NewColumnType{t}[1]{Q[t,wd=#1]}
\NewColumnType{m}[1]{Q[m,wd=#1]}
\NewColumnType{b}[1]{Q[b,wd=#1]}
\NewColumnType{h}[1]{Q[h,wd=#1]}
\NewColumnType{f}[1]{Q[f,wd=#1]}
\NewColumnType{X}[1][]{Q[co=1,#1]}
Gamma
\begin{tblr}{|t{15mm}|m{15mm}|b{20mm}|} Alpha Beta Gamma
Alpha & Beta & {Gamma\\Gamma} \\
Eta
Epsilon & Zeta & {Eta\\Eta} \\
Epsilon Zeta Eta
Iota & Kappa & {Lambda\\Lambda} \\
\end{tblr} Lambda
Iota Kappa Lambda
Any new column type must be defined with \NewColumnType command. It can have an optional argument
when it’s defined.
\NewRowType{l}{Q[l]}
\NewRowType{c}{Q[c]}
\NewRowType{r}{Q[r]}
\NewRowType{t}[1]{Q[t,ht=#1]}
\NewRowType{m}[1]{Q[m,ht=#1]}
\NewRowType{b}[1]{Q[b,ht=#1]}
\NewRowType{h}[1]{Q[h,ht=#1]}
\NewRowType{f}[1]{Q[f,ht=#1]}
Any new row type must be defined with \NewRowType command. It can have an optional argument when
it’s defined.
Chapter 3
Extra Interfaces
In general, tblr environment can accepts both inner and outer specifications:
Inner specifications are all specifications written in the mandatory argument of tblr environment,
which include new interfaces described in Chapter 2.
Outer specifications are all specifications written in the optional argument of tblr environment, most
of which are used for long tables (see Chapter 4).
You can use \SetTblrInner and \SetTblrOuter commands to set default inner and outer specifications
of tables, respectively (see Section 3.3).
26
CHAPTER 3. EXTRA INTERFACES 27
\begin{tblr}{
colspec={||llll||},rowspec={|QQQ|},rulesep=4pt,
} Alpha Beta Gamma Delta
Alpha & Beta & Gamma & Delta \\ Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\ Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\end{tblr}
By replacing stretch with row heights, we can get perfect vertical centering for your numerical tables.
\SetTblrInner{rowsep=2pt,colsep=2pt}
\begin{tblr}{hlines,vlines} Alpha Beta Gamma Delta
Alpha & Beta & Gamma & Delta \\
Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\end{tblr}
The following examples show the results from different vspan values.
If there is no hline above the first row, you get the same result with either t or T. But you get different
results if there are one or more hlines above the row:
Baseline\begin{tblr}{hlines,baseline=T}
Baseline Alpha Beta Gamma Baseline
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\ Epsilon Zeta Eta
Iota & Kappa & Lambda \\ Iota Kappa Lambda
\end{tblr}Baseline
CHAPTER 3. EXTRA INTERFACES 30
The differences between b and B are similar to t and T. In fact, these two values T and B are better
replacements for currently obsolete \firsthline and \lasthline commands.
Baseline\begin{tblr}[m]{hlines}
Alpha Beta Gamma
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta \\ Baseline Epsilon Zeta Eta Baseline
Iota & Kappa & Lambda \\ Iota Kappa Lambda
\end{tblr}Baseline
\begin{longtblr}{lcr}
Alpha & Beta & Gamma
\end{longtblr}
\begin{tblr}[long]{lcr}
Alpha & Beta & Gamma
\end{tblr}
\newcommand*\tblrrowa{
20 & 30 & 40 \\
}
\newcommand*\tblrrowb{
50 & 60 & 70 \\
}
\newcommand*\tblrbody{ AA BB CC
\hline
\tblrrowa 20 30 40
\tblrrowb 50 60 70
\hline
DD EE FF
}
\SetTblrOuter{expand=\tblrbody\tblrrowa} 20 30 40
\begin{tblr}[expand+=\tblrrowb]{ccc} 50 60 70
\hline
GG HH II
AA & BB & CC \\
\tblrbody
DD & EE & FF \\
\tblrbody
GG & HH & II \\
\hline
\end{tblr}
To expand commands with optional arguments, you can not define them with \newcommand. But you can
define them with \NewExpandableDocumentCommand, and use option expand=\expanded to do exhaustive
expansions.
\NewExpandableDocumentCommand\yes{O{Yes}m}{\SetCell{bg=green9}#1}
\NewExpandableDocumentCommand\no{O{No}m}{\SetCell{bg=red9}#1}
\begin{tblr}[expand=\expanded]{hlines}
What I get & is below \\
\expanded{\yes{}} & \expanded{\no{}} \\
\expanded{\yes[Great]{}} & \expanded{\no[Bad]{}}
\end{tblr}
Note that you need to protect fragile commands (if any) inside them with \unexpanded command.
\SetTblrInner{hlines,vlines}
\SetTblrOuter{baseline=B}
And the following example sets zero rowsep for all tblr and longtblr tables created afterwards.
CHAPTER 3. EXTRA INTERFACES 32
\SetTblrInner[tblr,longtblr]{rowsep=0pt}
\NewTblrEnviron{mytblr}
\SetTblrInner[mytblr]{hlines,vlines}
\SetTblrOuter[mytblr]{baseline=B} Alpha Beta Gamma Delta
Text \begin{mytblr}{cccc}
Epsilon Zeta Eta Theta
Alpha & Beta & Gamma & Delta \\
Epsilon & Zeta & Eta & Theta \\ Text Iota Kappa Lambda Mu Text
Iota & Kappa & Lambda & Mu \\
\end{mytblr} Text
\NewDocumentEnvironment{fancytblr}{+b}{
Before Text
\begin{tblr}{hlines}
#1
\end{tblr}
After Text
}{}
\begin{fancytblr}
One & Two & Three \\ One Two Three
Four & Five & Six \\ Before Text Four Five Six After Text
Seven & Eight & Nine \\ Seven Eight Nine
\end{fancytblr}
\NewTableCommand\myhline{\hline[0.1em,red5]}
\begin{tblr}{llll}
\myhline Alpha Beta Gamma Delta
Alpha & Beta & Gamma & Delta \\
Epsilon Zeta Eta Theta
Epsilon & Zeta & Eta & Theta \\
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\myhline
\end{tblr}
\begin{tblr}{
cell{odd}{1} = {red9},
cell{odd[4]}{2} = {green9}, Head Head Head
cell{odd[3-X]}{3} = {blue9}, Talk A Place A Date A
} Talk B Place B Date B
Head & Head & Head \\
Talk A & Place A & Date A \\ Talk C Place C Date C
Talk B & Place B & Date B \\ Talk D Place D Date D
Talk C & Place C & Date C \\ Talk E Place E Date E
Talk D & Place D & Date D \\
Talk E & Place E & Date E \\ Talk F Place F Date F
Talk F & Place F & Date F \\ Talk G Place G Date G
Talk G & Place G & Date G \\ Talk H Place H Date H
Talk H & Place H & Date H \\
\end{tblr}
\begin{tblr}{
cell{even}{1} = {yellow9},
cell{even[4]}{2} = {cyan9}, Head Head Head
cell{even[3-X]}{3} = {purple9}, Talk A Place A Date A
} Talk B Place B Date B
Head & Head & Head \\
Talk A & Place A & Date A \\ Talk C Place C Date C
Talk B & Place B & Date B \\ Talk D Place D Date D
Talk C & Place C & Date C \\ Talk E Place E Date E
Talk D & Place D & Date D \\
Talk E & Place E & Date E \\ Talk F Place F Date F
Talk F & Place F & Date F \\ Talk G Place G Date G
Talk G & Place G & Date G \\ Talk H Place H Date H
Talk H & Place H & Date H \\
\end{tblr}
\begin{tblr}{hlines}
Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
Row=\arabic{rowcount}, Col=\arabic{colcount} &
Row=\arabic{rowcount}, Col=\arabic{colcount} &
Row=\arabic{rowcount}, Col=\arabic{colcount} &
Row=\arabic{rowcount}, Col=\arabic{colcount} \\
Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
\end{tblr}
Also, lengths \leftsep, \rightsep, \abovesep, \belowsep can be used in cell text.
CHAPTER 3. EXTRA INTERFACES 34
Table 4.1: A Long Long Long Long Long Long Long Table
Head Head Head
Head Head Head
Alpha Beta Gamma
Epsilon Zetaa Eta
Iota Kappa† Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Foot Foot Foot
Continued on next page
35
CHAPTER 4. USE LONG TABLES 36
Table 4.1: A Long Long Long Long Long Long Long Table (Continued)
Head Head Head
Head Head Head
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Foot Foot Foot
Continued on next page
CHAPTER 4. USE LONG TABLES 37
Table 4.1: A Long Long Long Long Long Long Long Table (Continued)
Head Head Head
Head Head Head
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Alpha Beta Gamma
Epsilon Zeta Eta
Iota Kappa Lambda
Nu Xi Omicron
Rho Sigma Tau
Phi Chi Psi
Foot Foot Foot
a
It is the first footnote.
†
It is the second long long long long long long footnote.
Note: Some general note. Some general note. Some general note.
Source: Made up by myself. Made up by myself. Made up by myself.
As you can see in the above example, the appearance of long tables of tabularray package is similar to
that of threeparttablex packages. It supports table footnotes, but not page footnotes.
CHAPTER 4. USE LONG TABLES 38
The source code for the above long table is shown below. It is mainly self-explanatory.
\NewTblrTheme{fancy}{
\SetTblrStyle{firsthead}{font=\bfseries}
\SetTblrStyle{firstfoot}{fg=blue2}
\SetTblrStyle{middlefoot}{\itshape}
\SetTblrStyle{caption-tag}{red2}
}
\begin{longtblr}[
theme = fancy,
caption = {A Long Long Long Long Long Long Long Table},
entry = {Short Caption},
label = {tblr:test},
note{a} = {It is the first footnote.},
note{$\dag$} = {It is the second long long long long long long footnote.},
remark{Note} = {Some general note. Some general note. Some general note.},
remark{Source} = {Made up by myself. Made up by myself. Made up by myself.},
]{
colspec = {XXX}, width = 0.85\linewidth,
rowhead = 2, rowfoot = 1,
row{odd} = {gray9}, row{even} = {brown9},
row{1-2} = {purple7}, row{Z} = {blue7},
}
\hline
Head & Head & Head \\
\hline
Head & Head & Head \\
\hline
Alpha & Beta & Gamma \\
\hline
Epsilon & Zeta\TblrNote{a} & Eta \\
\hline
Iota & Kappa\TblrNote{$\dag$} & Lambda \\
\hline
Nu & Xi & Omicron \\
\hline
Rho & Sigma & Tau \\
\hline
Phi & Chi & Psi \\
\hline
......
\hline
Alpha & Beta & Gamma \\
\hline
Epsilon & Zeta & Eta \\
\hline
Iota & Kappa & Lambda \\
\hline
Nu & Xi & Omicron \\
\hline
Rho & Sigma & Tau \\
\hline
Phi & Chi & Psi \\
\hline
Foot & Foot & Foot \\
\hline
\end{longtblr}
CHAPTER 4. USE LONG TABLES 39
As you can see in the above code, we typeset long tables with longtblr environment. And we can totally
separate contents and styles of long tables with tabularray package.
Row head and row foot consist of some lines of the table and should appear in every page. Their options
are inner specifications and should be put in the mandatory argument of the longtblr environment. In
the above example, We set rowhead=2 and rowfoot=1.
Table 4.2: Inner Specifications for Row Heads and Row Foots
Key Name Key Description Initial Value
rowhead number of the first rows of the table appear in every page 0
rowfoot number of the last rows of the table appear in every page 0
Table head and table foot consist of the caption, continuation text, footnotes and remarks. Their options
are outer specifications and should be put in the optional argument of the longtblr environment.
Table 4.3: Outer Specifications for Table Heads and Table Foots
Key Name Key Description Initial Value
headsep vertical space between table head and table body 6pt
footsep vertical space between table foot and table body 6pt
presep vertical space between table head and the above text 1.5\bigskipamount
postsep vertical space between table foot and the below text 1.5\bigskipamount
theme table theme (including settings for templates and styles) ×
caption table caption ×
entry short table caption to be put in List of Tables ×
label table label ×
note{<name>} table note with <name> as tag ×
remark{<name>} table remark with <name> as tag ×
If you write entry=none, tabularray package will not add an entry in List of Tables. Therefore
caption=text,entry=none is similar to \caption[]{text} in longtable.
If you write label=none, tabularray package will not step table counter, and set the caption-tag
and caption-sep elements (see below) to empty. Therefore caption=text,entry=none,label=none is
similar to \caption*{text} in longtable, except for the counter.
An element which only includes short text is called a sub element. Normally there is one - in the name
of a sub element. An element which includes one or more paragraphs is called a main element. Normally
there isn’t any - in the name of a main element.
For each of the above elements, two templates normal and empty are always defined. You can select one
of them with \SetTblrTemplate command.
In the above code, command \DefTblrTemplate defines the templates with name normal, and then
command \SetTblrTemplate sets the templates with name normal as default. The normal template is
always defined and set as default for any element in tabularray. Therefore you had better use another
name when defining new templates.
2 To tell the truth, the default conthead-text and contfoot-text are actually stored in commands \tblrcontheadname
and \tblrcontfootname respectively. And you may contribute your translations of them to babel package.
CHAPTER 4. USE LONG TABLES 41
If you use default as template name in \DefTblrTemplate, you define and set it as default at the same
time. Therefore the above code can be written in another way:
You may modify the code to customize continuation text to fit your needs.
The templates for contfoot and conthead normally include the templates of their sub elements with
\UseTblrTemplate commands. But you can also handle user settings such as horizontal alignment here.
\DefTblrTemplate{contfoot}{default}{\UseTblrTemplate{contfoot-text}{default}}
\DefTblrTemplate{conthead}{default}{\UseTblrTemplate{conthead-text}{default}}
\DefTblrTemplate{caption-tag}{default}{Table\hspace{0.25em}\thetable}
\DefTblrTemplate{caption-sep}{default}{:\enskip}
\DefTblrTemplate{caption-text}{default}{\InsertTblrText{caption}}
The command \InsertTblrText{caption} inserts the value of caption key, which you could write in
the optional argument of longtblr environment.
The caption template normally includes three sub templates with \UseTblrTemplate commands: The
caption template will be used in firsthead template.
\DefTblrTemplate{caption}{default}{
\UseTblrTemplate{caption-tag}{default}
\UseTblrTemplate{caption-sep}{default}
\UseTblrTemplate{caption-text}{default}
}
Furthermore capcont template includes conthead template as well. The capcont template will be used
in middlehead and lasthead templates.
\DefTblrTemplate{capcont}{default}{
\UseTblrTemplate{caption-tag}{default}
\UseTblrTemplate{caption-sep}{default}
\UseTblrTemplate{caption-text}{default}
\UseTblrTemplate{conthead-text}{default}
}
\DefTblrTemplate{note-tag}{default}{\textsuperscript{\InsertTblrNoteTag}}
\DefTblrTemplate{note-sep}{default}{\space}
\DefTblrTemplate{note-text}{default}{\InsertTblrNoteText}
CHAPTER 4. USE LONG TABLES 42
\DefTblrTemplate{note}{default}{
\MapTblrNotes{
\noindent
\UseTblrTemplate{note-tag}{default}
\UseTblrTemplate{note-sep}{default}
\UseTblrTemplate{note-text}{default}
\par
}
}
The \MapTblrNotes command loops for all table notes, which are written in the optional argument of
longtblr environment. Inside the loop, you can use \InsertTblrNoteTag and \InsertTblrNoteText
commands to insert current note tag and note text, respectively.
The definition of remark templates are similar to note templates.
\DefTblrTemplate{remark-tag}{default}{\InsertTblrRemarkTag}
\DefTblrTemplate{remark-sep}{default}{:\space}
\DefTblrTemplate{remark-text}{default}{\InsertTblrRemarkText}
\DefTblrTemplate{remark}{default}{
\MapTblrRemarks{
\noindent
\UseTblrTemplate{remark-tag}{default}
\UseTblrTemplate{remark-sep}{default}
\UseTblrTemplate{remark-text}{default}
\par
}
}
\DefTblrTemplate{firsthead}{default}{
\UseTblrTemplate{caption}{default}
}
\DefTblrTemplate{middlehead,lasthead}{default}{
\UseTblrTemplate{capcont}{default}
}
\DefTblrTemplate{firstfoot,middlefoot}{default}{
\UseTblrTemplate{contfoot}{default}
}
\DefTblrTemplate{lastfoot}{default}{
\UseTblrTemplate{note}{default}
\UseTblrTemplate{remark}{default}
}
Note that you can define the same template for multiple elements in \DefTblrTemplate command. If
you only want to show table caption in the first page, you may change the definitions of middlehead and
lasthead elements:
\DefTblrTemplate{middlehead,lasthead}{default}{
\UseTblrTemplate{conthead}{default}
}
CHAPTER 4. USE LONG TABLES 43
\SetTblrStyle{firsthead}{font=\bfseries}
\SetTblrStyle{firstfoot}{fg=blue2}
\SetTblrStyle{middlefoot}{\itshape}
\SetTblrStyle{caption-tag}{red2}
\NewTblrTheme{fancy}{
\DefTblrTemplate{conthead}{default}{[Continued]}
\SetTblrStyle{firsthead}{font=\bfseries}
\SetTblrStyle{firstfoot}{fg=blue2}
\SetTblrStyle{middlefoot}{\itshape}
\SetTblrStyle{caption-tag}{red2}
}
After defining the theme fancy, you can use it by writing theme=fancy in the optional argument of
longtblr environment.
TEXT\begin{talltblr}[
caption = {Long Long Long Long Tabular},
entry = {Short Caption},
label = {tblr:tall},
note{a} = {It is the first footnote.},
note{$\dag$} = {It is the second long long long long long long footnote.},
]{
colspec = {XXX}, width = 0.5\linewidth, hlines,
}
Alpha & Beta & Gamma \\
Epsilon & Zeta & Eta\TblrNote{a} \\
Iota & Kappa & Lambda\TblrNote{$\dag$} \\
\end{talltblr}TEXT
Table 4.6: Long Long Long Long Tabular
Alpha Beta Gamma
Epsilon Zeta Etaa
TEXT TEXT
Iota Kappa Lambda†
a
It is the first footnote.
†
It is the second long long long long long long foot-
note.
Chapter 5
The tabularray package emulates or fixes some commands in other packages. To avoid potential conflict,
you need to enable them with \UseTblrLibrary command.
$\begin{pmatrix} 2 2 1
\dfrac{2}{3} & \dfrac{2}{3} & \dfrac{1}{3} \\ 3
2 3 3
1 2
\dfrac{2}{3} & -\dfrac{1}{3} & -\dfrac{2}{3} \\
3 − −
\dfrac{1}{3} & -\dfrac{2}{3} & \dfrac{2}{3} \\ 1 3 3
2 2
\end{pmatrix}$ −
3 3 3
2 2 1
$\begin{+pmatrix}[cells={r},row{2}={purple8}] 3
\dfrac{2}{3} & \dfrac{2}{3} & \dfrac{1}{3} \\ 3 3
2 1 2
\dfrac{2}{3} & -\dfrac{1}{3} & -\dfrac{2}{3} \\
3 − −
\dfrac{1}{3} & -\dfrac{2}{3} & \dfrac{2}{3} \\ 3 3
1 2 2
\end{+pmatrix}$ −
3 3 3
$f(x)=\begin{cases}
0, x = 1;
0, & x=1; \\
1,
\dfrac{1}{3}, & x=2; \\ x = 2;
f (x) = 32
\dfrac{2}{3}, & x=3; \\ , x = 3;
1, & x=4. \\
3
\end{cases}$ 1, x = 4.
$f(x)=\begin{+cases}
0, x = 1;
0, & x=1; \\
1
, x = 2;
\dfrac{1}{3}, & x=2; \\
f (x) = 3
\dfrac{2}{3}, & x=3; \\ 2
, x = 3;
1, & x=4. \\
3
\end{+cases}$
1,
x = 4.
45
CHAPTER 5. USE SOME LIBRARIES 46
\begin{tblr}{llll}
\toprule
Alpha & Beta & Gamma & Delta \\
\midrule Alpha Beta Gamma Delta
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\cmidrule{1-3}
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\cmidrule{2-4} Nu Xi Omicron Pi
Nu & Xi & Omicron & Pi \\
\bottomrule
\end{tblr}
Just like \hline and \cline commands, you can also specify rule width and color in the optional argument
of any of these commands.
\begin{tblr}{llll}
\toprule[2pt,purple3]
Alpha & Beta & Gamma & Delta \\
Alpha Beta Gamma Delta
\midrule[blue3]
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\cmidrule[azure3]{2-3} Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\bottomrule[2pt,purple3]
\end{tblr}
If you need more than one \cmidrules, you can use \cmidrulemore command.
\begin{tblr}{llll}
\toprule
Alpha & Beta & Gamma & Delta \\ Alpha Beta Gamma Delta
\cmidrule{1-3} \cmidrulemore{2-4}
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\cmidrule{1-3} \morecmidrules \cmidrule{2-4}
Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\bottomrule
\end{tblr}
From version 2021N (2021-09-01), trim options (l, r, lr) for \cmidrule command are also supported.
\begin{tblr}{llll}
\toprule
Alpha & Beta & Gamma & Delta \\
\cmidrule[lr]{1-2} \cmidrule[lr=-0.4]{3-4} Alpha Beta Gamma Delta
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\cmidrule[r]{1-2} \cmidrule[l]{3-4} Iota Kappa Lambda Mu
Iota & Kappa & Lambda & Mu \\
\bottomrule
\end{tblr}
Note that you need to put l, r or lr option into the square brackets. and the possible values are decimal
numbers between -1 and 0, where -1 means trimming the whole colsep, and 0 means no trimming. The
default value is -0.8, which makes similar result as booktabs package does.
There is also a booktabs environment for you. With this environment, the default rowsep=0pt, but extra
CHAPTER 5. USE SOME LIBRARIES 47
vertical space will be added by \toprule, \midrule, \bottomrule and \cmidrule commands. The sizes
of vertical space are determined by \aboverulesep and \belowrulesep dimensions.
\begin{booktabs}{
colspec = lcccc,
cell{1}{1} = {r=2}{}, cell{1}{2,4} = {c=2}{},
}
\toprule I II
Sample & I & & II & \\ Sample
A B C D
\cmidrule[lr]{2-3} \cmidrule[lr]{4-5}
& A & B & C & D \\ S1 5 6 7 8
\midrule S2 6 7 8 5
S1 & 5 & 6 & 7 & 8 \\ S3 7 8 5 6
S2 & 6 & 7 & 8 & 5 \\
S3 & 7 & 8 & 5 & 6 \\
\bottomrule
\end{booktabs}
You can also use \specialrule command. The second argument sets belowsep of previous row, and the
third argument sets abovesep of current row,
\begin{booktabs}{row{2}={olive9}}
\toprule
Alpha & Beta & Gamma & Delta \\ Alpha Beta Gamma Delta
\specialrule{0.5pt}{4pt}{6pt}
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\specialrule{0.8pt,blue3}{3pt}{2pt}
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\bottomrule
\end{booktabs}
At last, there is also an \addlinespace command. You can specify the size of vertical space to be added
in its optional argument, and the default size is 0.5em. This command adds one half of the space to
belowsep of previous row, and the other half to abovesep of current row.
\begin{booktabs}{row{2}={olive9}}
\toprule
Alpha & Beta & Gamma & Delta \\ Alpha Beta Gamma Delta
\addlinespace
Epsilon & Zeta & Eta & Theta \\ Epsilon Zeta Eta Theta
\addlinespace[1em]
Iota & Kappa & Lambda & Mu \\ Iota Kappa Lambda Mu
\bottomrule
\end{booktabs}
From version 2022A (2022-03-01), there is a longtabs environment for writing long booktabs tables, and
a talltabs environment for writing tall booktabs tables.
\newcounter{mycnta}
\newcommand{\mycnta}{\stepcounter{mycnta}\arabic{mycnta}}
1 2 3
\begin{tblr}{hlines}
\mycnta & \mycnta & \mycnta \\ 4 5 6
\mycnta & \mycnta & \mycnta \\ 7 8 9
\mycnta & \mycnta & \mycnta \\
\end{tblr}
\begin{tblr}{hlines,vlines} Pp
Beta Gamma
\diagbox{Aa}{Pp} & Beta & Gamma \\ Aa
Epsilon & Zeta & Eta \\ Epsilon Zeta Eta
Iota & Kappa & Lambda \\
\end{tblr} Iota Kappa Lambda
\begin{tblr}{hlines,vlines} Pp Hh
\diagboxthree{Aa}{Pp}{Hh} & Beta & Gamma \\ Beta Gamma
Aa
Epsilon & Zeta & Eta \\
Epsilon Zeta Eta
Iota & Kappa & Lambda \\
\end{tblr} Iota Kappa Lambda
You can also use \diagbox and \diagboxthree commands in math mode.
$\begin{tblr}{|c|cc|}
\hline
\diagbox{X_1}{X_2} & 0 & 1 \\ X2
0 1
\hline X1
0 & 0.1 & 0.2 \\ 0 0.1 0.2
1 & 0.3 & 0.4 \\ 1 0.3 0.4
\hline
\end{tblr}$
\begin{filecontents*}[overwrite]{test1.tmp}
Some & Some \\
\end{filecontents*}
CHAPTER 5. USE SOME LIBRARIES 49
\begin{filecontents*}[overwrite]{test2.tmp}
Other & Other \\
\end{filecontents*}
Then you can input them with outer specification evaluate=\fileInput. The \fileInput function is
provided by functional package.
\begin{tblr}[evaluate=\fileInput]{hlines} Row1 1
Row1 & 1 \\
Some Some
\fileInput{test1.tmp}
Row3 & 3 \\ Row3 3
\fileInput{test2.tmp} Other Other
Row5 & 5 \\
\end{tblr} Row5 5
In general, you can define your functions which return parts of table contents, and use evaluate key to
evaluate them inside tables.
\IgnoreSpacesOn
\prgNewFunction \someFunc {m} {
\prgReturn {#1 & #1 \\}
} Row1 1
\IgnoreSpacesOff Text Text
\begin{tblr}[evaluate=\someFunc]{hlines}
Row3 3
Row1 & 1 \\
\someFunc{Text} Text Text
Row3 & 3 \\ Row5 5
\someFunc{Text}
Row5 & 5 \\
\end{tblr}
\IgnoreSpacesOn
\prgNewFunction \otherFunc {} {
\prgReturn {Other & Other \\}
} Row1 1
\IgnoreSpacesOff Other Other
\begin{tblr}[evaluate=\otherFunc]{hlines}
Row3 3
Row1 & 1 \\
\otherFunc Other Other
Row3 & 3 \\ Row5 5
\otherFunc
Row5 & 5 \\
\end{tblr}
You can even generate the whole table with some function.
\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}
From version 2023A, you can evaluate all functions in the table body with option evaluate=all.
CHAPTER 5. USE SOME LIBRARIES 50
• \cellGetText{<rownum>}{<colnum>}
• \cellSetText{<rownum>}{<colnum>}{<text>}
• \cellSetStyle{<rownum>}{<colnum>}{<style>}
• \rowSetStyle{<rownum>}{<style>}
• \columnSetStyle{<colnum>}{<style>}
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{tblr}{colspec={rrr},process=\funcSum}
\hline
1 & 2 & 3 \\ 1 2 3
4 & 5 & 6 \\ 4 5 6
7 & 8 & 9 \\
\hline 7 8 9
& & \\ 12 15 18
\hline
\end{tblr}
\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{tblr}{hlines,vlines,cells={r,$},process=\funcColor}
−1 2 3
-1 & 2 & 3 \\
4 & 5 & -6 \\ 4 5 −6
7 & -8 & 9 \\ 7 −8 9
\end{tblr}
CHAPTER 5. USE SOME LIBRARIES 51
We can also use color series of 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{tblr}{hlines,process=\funcSeries} Row1 1
Row1 & 1 \\ Row2 2
Row2 & 2 \\
Row3 & 3 \\ Row3 3
Row4 & 4 \\ Row4 4
Row5 & 5 \\
Row5 5
Row6 & 6 \\
\end{tblr} Row6 6
\begin{tblr}{
hlines, vlines,
colspec={S[table-format=3.2]S[table-format=3.2]} Head Head
} 111 111
{{{Head}}} & {{{Head}}} \\
111 & 111 \\ 2.1 2.2
2.1 & 2.2 \\ 33.11 33.22
33.11 & 33.22 \\
\end{tblr}
CHAPTER 5. USE SOME LIBRARIES 52
\begin{tblr}{
hlines, vlines,
colspec={Q[si={table-format=3.2},c]Q[si={table-format=3.2},c]} Head Head
} 111 111
{{{Head}}} & {{{Head}}} \\
111 & 111 \\ 2.1 2.2
2.1 & 2.2 \\ 33.11 33.22
33.11 & 33.22 \\
\end{tblr}
Note that you need to use 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 guard is provided for cells
and rows. With guard key the previous example can be largely simplified.
\begin{tblr}{
hlines, vlines,
colspec={Q[si={table-format=3.2},c]Q[si={table-format=3.2},c]}, Head Head
row{1} = {guard}
} 111 111
Head & Head \\ 2.1 2.2
111 & 111 \\
33.11 33.22
2.1 & 2.2 \\
33.11 & 33.22 \\
\end{tblr}
Also you must use l, c or r to set horizontal alignment for non-numeric cells:
\begin{tblr}{
hlines, vlines, columns={6em},
colspec={
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 \\
\end{tblr}
Both S and s columns are supported. In fact, These two columns have been defined as follows:
\NewColumnType{S}[1][]{Q[si={#1},c]}
\NewColumnType{s}[1][]{Q[si={#1},c,cmd=\TblrUnit]}
You don’t need to and are not allowed to define them again.
CHAPTER 5. USE SOME LIBRARIES 53
\begin{tblr}{hlines,measure=vbox}
Text Text Text Text Text Text Text Text Text Text Text Text Text Text
\begin{itemize}
\item List List List List List List • List List List List List List
\item List List List List List List List • List List List List List List List
\end{itemize}
Text Text Text Text Text Text Text \\ Text Text Text Text Text Text Text
\end{tblr}
From version 2022A (2022-03-01), you can remove extra space above and below lists, by adding option
stretch=-1. The following example also needs enumitem package and its nosep option:
• List List List List List oooo
• List List List List List List
• List List List List List
• List List List List List List gggg
\begin{tblr}{
hlines,vlines,rowspec={Q[l,t]Q[l,b]},
measure=vbox,stretch=-1,
}
\begin{itemize}[nosep]
\item List List List List List
\item List List List List List List
\end{itemize} & oooo \\
\begin{itemize}[nosep]
\item List List List List List
\item List List List List List List
\end{itemize} & gggg \\
\end{tblr}
Note that option stretch=-1 also removes struts from cells, therefore it may not work well in tabularray
environments with rowsep=0pt, such as booktabs/longtabs/talltabs environments from booktabs
library.
\RenewDocumentCommand\TblrAlignBoth{}{\justifying}
\RenewDocumentCommand\TblrAlignLeft{}{\RaggedRight}
\RenewDocumentCommand\TblrAlignCenter{}{\Centering}
\RenewDocumentCommand\TblrAlignRight{}{\RaggedLeft}
Please read the documentation of ragged2e package for more details of their alignment commands.
In the above example, balanced curly braces and control words (such as \bfseries) need not to be
escaped—only several special characters need to be escaped. Please read the documentation of codehigh
package for more details of \fakeverb commands.1
1 By the way, \EscVerb command from fvextra package is similar to \fakeverb command, but with \EscVerb you need
54
Chapter 7
55
Chapter 8
\RequirePackage{expl3}
\ProvidesExplPackage{tabularray}{2024-02-16}{2024A}
{Typeset tabulars and arrays with LaTeX3}
\AtBeginDocument{
\@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}
\@ifpackageloaded{hyperref}{
\newenvironment{tblrNoHyper}{\NoHyper}{\endNoHyper}
}{
\newenvironment{tblrNoHyper}{}{}
}
}
\NewDocumentCommand \TblrAlignBoth { }
{
\let \\ = \@normalcr
\leftskip = \z@skip
56
CHAPTER 8. THE SOURCE CODE 57
\@rightskip = \z@skip
\rightskip = \@rightskip
\parfillskip = \@flushglue
}
\tl_new:N \l__tblr_a_tl
\tl_new:N \l__tblr_b_tl
\tl_new:N \l__tblr_c_tl
\tl_new:N \l__tblr_d_tl
\tl_new:N \l__tblr_e_tl
CHAPTER 8. THE SOURCE CODE 58
\tl_new:N \l__tblr_f_tl
\tl_new:N \l__tblr_h_tl
\tl_new:N \l__tblr_i_tl % for row index
\tl_new:N \l__tblr_j_tl % for column index
\tl_new:N \l__tblr_k_tl
\tl_new:N \l__tblr_n_tl
\tl_new:N \l__tblr_o_tl
\tl_new:N \l__tblr_r_tl
\tl_new:N \l__tblr_s_tl
\tl_new:N \l__tblr_t_tl
\tl_new:N \l__tblr_u_tl
\tl_new:N \l__tblr_v_tl
\tl_new:N \l__tblr_w_tl
\tl_new:N \l__tblr_x_tl
\tl_new:N \l__tblr_y_tl
\int_new:N \l__tblr_a_int
\int_new:N \l__tblr_c_int % for column number
\int_new:N \l__tblr_r_int % for row number
\dim_new:N \l__tblr_d_dim % for depth
\dim_new:N \l__tblr_h_dim % for height
\dim_new:N \l__tblr_o_dim
\dim_new:N \l__tblr_p_dim
\dim_new:N \l__tblr_q_dim
\dim_new:N \l__tblr_r_dim
\dim_new:N \l__tblr_s_dim
\dim_new:N \l__tblr_t_dim
\dim_new:N \l__tblr_v_dim
\dim_new:N \l__tblr_w_dim % for width
\box_new:N \l__tblr_a_box
\box_new:N \l__tblr_b_box
\box_new:N \l__tblr_c_box % for cell box
\box_new:N \l__tblr_d_box
\dim_new:N \abovesep
\dim_new:N \belowsep
\dim_new:N \leftsep
\dim_new:N \rightsep
\cs_new_protected:Npn \__tblr_clear_prop_lists:
{
\prop_gclear_new:c { g__tblr_text_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_command_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_inner_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_note_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_remark_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_more_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_row_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_column_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_cell_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_hline_ \int_use:N \g_tblr_level_int _prop }
\prop_gclear_new:c { g__tblr_vline_ \int_use:N \g_tblr_level_int _prop }
}
\cs_new_protected:Npn \__tblr_prop_gput:nnn #1 #2 #3
{
\prop_gput:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
}
\cs_generate_variant:Nn \__tblr_prop_gput:nnn { nnx, nnV, nxn, nxx, nxV }
\cs_new:Npn \__tblr_prop_item:nn #1 #2
{
\prop_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 }
}
\cs_generate_variant:Nn \__tblr_prop_item:nn { ne }
CHAPTER 8. THE SOURCE CODE 60
\cs_new_protected:Npn \__tblr_prop_if_in:nnT #1
{
\prop_if_in:cnT { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
}
\cs_new_protected:Npn \__tblr_prop_if_in:nnF #1
{
\prop_if_in:cnF { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
}
\cs_new_protected:Npn \__tblr_prop_if_in:nnTF #1
{
\prop_if_in:cnTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
}
\prg_generate_conditional_variant:Nnn \__tblr_prop_if_in:nn { nx } { T, F, TF }
\cs_new_protected:Npn \__tblr_prop_log:n #1
{
\prop_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop }
}
\cs_new_protected:Npn \__tblr_prop_map_inline:nn #1 #2
{
\prop_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } {#2}
}
\cs_new_protected:Npn \__tblr_prop_gput_if_larger:nnn #1 #2 #3
{
\__tblr_gput_if_larger:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
}
\cs_generate_variant:Nn \__tblr_prop_gput_if_larger:nnn { nnx, nnV, nxn, nxx, nxV }
\cs_new_protected:Npn \__tblr_prop_gadd_dimen_value:nnn #1 #2 #3
{
\__tblr_gadd_dimen_value:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _prop } { #2 } { #3 }
}
\cs_generate_variant:Nn \__tblr_prop_gadd_dimen_value:nnn { nnx, nnV, nxn, nxx }
%% Put the dimension to the prop list only if it's larger than the old one
\tl_new:N \l__tblr_put_if_larger_tl
\cs_new_protected:Npn \__tblr_put_if_larger:Nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } }
\bool_lazy_or:nnT
{ \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
{ \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
{ \prop_put:Nnn #1 { #2 } { #3 } }
}
\cs_generate_variant:Nn \__tblr_put_if_larger:Nnn { Nnx, Nxn, Nxx, NnV }
\cs_new_protected:Npn \__tblr_gput_if_larger:Nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_put_if_larger_tl { \prop_item:Nn #1 { #2 } }
\bool_lazy_or:nnT
CHAPTER 8. THE SOURCE CODE 61
{ \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
{ \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
{ \prop_gput:Nnn #1 { #2 } { #3 } }
}
\cs_generate_variant:Nn \__tblr_gput_if_larger:Nnn { Nnx, Nxn, Nxx, cnn }
\cs_new_protected:Npn \__tblr_add_dimen_value:Nnn #1 #2 #3
{
\prop_put:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } }
}
\cs_generate_variant:Nn \__tblr_add_dimen_value:Nnn { cnn }
\cs_new_protected:Npn \__tblr_gadd_dimen_value:Nnn #1 #2 #3
{
\prop_gput:Nnx #1 { #2 } { \dim_eval:n { \prop_item:Nn #1 { #2 } + #3 } }
}
\cs_generate_variant:Nn \__tblr_gadd_dimen_value:Nnn { cnn }
\cs_new_protected:Npn \__tblr_clear_one_spec_lists:n #1
{
\clist_if_exist:cTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
{
\clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
{
\tl_gclear:c { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_##1_tl }
}
}
{ \clist_new:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } }
}
\cs_new_protected:Npn \__tblr_spec_gput:nnn #1 #2 #3
{
\tl_gset:cn
{ g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl } {#3}
\clist_gput_right:cx { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } {#2}
}
\cs_generate_variant:Nn \__tblr_spec_gput:nnn { nne, nnV, nen, nee, neV }
\cs_new:Npn \__tblr_spec_item:nn #1 #2
CHAPTER 8. THE SOURCE CODE 62
{
\tl_if_exist:cT { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl }
{
\exp_args:Nv \exp_not:n
{ g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl }
}
}
\cs_generate_variant:Nn \__tblr_spec_item:nn { ne }
\cs_new_protected:Npn \__tblr_spec_gput_if_larger:nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_put_if_larger_tl { \__tblr_spec_item:nn {#1} {#2} }
\bool_lazy_or:nnT
{ \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
{ \dim_compare_p:nNn {#3} > { \l__tblr_put_if_larger_tl } }
{ \__tblr_spec_gput:nnn {#1} {#2} {#3} }
}
\cs_generate_variant:Nn \__tblr_spec_gput_if_larger:nnn { nne, nnV, nen, nee, neV }
\cs_new_protected:Npn \__tblr_spec_gadd_dimen_value:nnn #1 #2 #3
{
\__tblr_spec_gput:nne {#1} {#2}
{ \dim_eval:n { \__tblr_spec_item:ne {#1} {#2} + #3 } }
}
\cs_generate_variant:Nn \__tblr_spec_gadd_dimen_value:nnn { nne, nnV, nen, nee }
\cs_new_protected:Npn \__tblr_spec_log:n #1
{
\clist_gremove_duplicates:c
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
\tl_log:x
{
The ~ spec ~ list ~ #1 _ \int_use:N \g_tblr_level_int
\space contains ~ the ~ pairs:
}
\clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
{
\tl_log:x
{
\space { ##1 } ~\space=>~\space { \__tblr_spec_item:nn {#1} {##1} }
}
}
}
\cs_new_protected:Npn \__tblr_intarray_gset:Nnn #1 #2 #3
{
\bool_lazy_or:nnTF
{ \int_compare_p:nNn {#2} < {0} }
{ \int_compare_p:nNn {#2} > {\intarray_count:N #1} }
{
\bool_if:NT \g__tblr_tracing_intarray_bool
CHAPTER 8. THE SOURCE CODE 63
\int_new:N \g__tblr_data_row_key_count_int
\__tblr_data_new_key:nnn { row } { height } { dim }
\__tblr_data_new_key:nnn { row } { coefficient } { dec }
\__tblr_data_new_key:nnn { row } { abovesep } { dim }
\__tblr_data_new_key:nnn { row } { belowsep } { dim }
\__tblr_data_new_key:nnn { row } { @row-height } { dim }
\__tblr_data_new_key:nnn { row } { @row-head } { dim }
\__tblr_data_new_key:nnn { row } { @row-foot } { dim }
\__tblr_data_new_key:nnn { row } { @row-upper } { dim }
\__tblr_data_new_key:nnn { row } { @row-lower } { dim }
\int_new:N \g__tblr_data_column_key_count_int
\__tblr_data_new_key:nnn { column } { width } { dim }
\__tblr_data_new_key:nnn { column } { coefficient } { dec }
\__tblr_data_new_key:nnn { column } { leftsep } { dim }
\__tblr_data_new_key:nnn { column } { rightsep } { dim }
\__tblr_data_new_key:nnn { column } { @col-width } { dim }
\int_new:N \g__tblr_data_cell_key_count_int
\__tblr_data_new_key:nnn { cell } { width } { dim }
\__tblr_data_new_key:nnn { cell } { rowspan } { int }
\__tblr_data_new_key:nnn { cell } { colspan } { int }
\__tblr_data_new_key:nnn { cell } { halign } { str }
\__tblr_data_new_key:nnn { cell } { valign } { str }
\__tblr_data_new_key:nnn { cell } { background } { str }
\__tblr_data_new_key:nnn { cell } { foreground } { str }
\__tblr_data_new_key:nnn { cell } { font } { str }
\__tblr_data_new_key:nnn { cell } { mode } { str }
\__tblr_data_new_key:nnn { cell } { cmd } { str }
\__tblr_data_new_key:nnn { cell } { omit } { int }
\__tblr_data_new_key:nnn { cell } { @cell-width } { dim }
\__tblr_data_new_key:nnn { cell } { @cell-height } { dim }
\__tblr_data_new_key:nnn { cell } { @cell-depth } { dim }
\cs_new_protected:Npn \__tblr_init_table_data:
{
\clist_map_function:NN \c__tblr_data_clist \__tblr_init_one_data:n
}
\cs_new_protected:Npn \__tblr_init_one_data:n #1
{
\int_gincr:N \g__tblr_array_int
\intarray_new:cn { g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray }
{
\int_use:c { g__tblr_data_#1_key_count_int }
* \tl_use:c { c__tblr_data_#1_count_tl }
}
\cs_set_eq:cc { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
{ g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray }
%\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
}
%% #1: data name; #2: data index 1; #3: data index 2; #4: key name
\cs_new:Npn \__tblr_data_key_to_int:nnnn #1 #2 #3 #4
{
( #2 - 1 ) * \c@colcount * \int_use:c { g__tblr_data_#1_key_count_int }
+ ( #3 - 1 ) * \int_use:c { g__tblr_data_#1_key_count_int }
+ \tl_use:c { c__tblr_data_#1_key_number_#4_tl }
}
\int_new:N \l__tblr_key_count_int
\int_new:N \l__tblr_key_quotient_int
\int_new:N \l__tblr_key_quotient_two_int
\int_new:N \l__tblr_key_remainder_int
{
#2 + \l__tblr_key_count_int
- \l__tblr_key_quotient_int * \l__tblr_key_count_int
}
\int_compare:nNnT { \l__tblr_key_remainder_int } = { 0 }
{ \int_set_eq:NN \l__tblr_key_remainder_int \l__tblr_key_count_int }
\tl_set:Nx #3 { \int_use:N \l__tblr_key_quotient_int }
\tl_set_eq:Nc #4
{ c__tblr_data_#1_key_name_ \int_use:N \l__tblr_key_remainder_int _tl }
}
\tl_new:N \g__tblr_data_int_from_value_tl
\cs_new_protected:Npn \__tblr_data_int_from_int:n #1
{
\tl_gset:Nn \g__tblr_data_int_from_value_tl {#1}
}
\cs_new:Npn \__tblr_data_int_to_int:n #1
{
#1
}
\cs_new_protected:Npn \__tblr_data_int_from_dim:n #1
{
\tl_gset:Nx \g__tblr_data_int_from_value_tl { \dim_to_decimal_in_sp:n {#1} }
}
\cs_new_protected:Npn \__tblr_data_int_from_dec:n #1
{
\tl_gset:Nx \g__tblr_data_int_from_value_tl
{ \dim_to_decimal_in_sp:n {#1 pt} }
}
\cs_new:Npn \__tblr_data_int_to_dec:n #1
{
\dim_to_decimal:n {#1 sp}
}
\int_new:N \g__tblr_data_str_value_count_int
\tl_gclear_new:c { g__tblr_data_0_to_str_tl }
\cs_new_protected:Npn \__tblr_data_int_from_str:n #1
{
\tl_if_exist:cTF { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
{
\tl_gset_eq:Nc \g__tblr_data_int_from_value_tl
{ g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
CHAPTER 8. THE SOURCE CODE 67
}
{
\int_gincr:N \g__tblr_data_str_value_count_int
\tl_gset:cx { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
{ \int_use:N \g__tblr_data_str_value_count_int }
\tl_gset:cn
{ g__tblr_data_ \int_use:N \g__tblr_data_str_value_count_int _to_str_tl }
{ \exp_not:n {#1} }
\tl_gset:Nx \g__tblr_data_int_from_value_tl
{ \int_use:N \g__tblr_data_str_value_count_int }
}
}
\cs_new:Npn \__tblr_data_int_to_str:n #1
{
\tl_use:c { g__tblr_data_#1_to_str_tl }
}
%% #1: data name; #2: data index; #3: key; #4: value
\cs_new_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4
{
\__tblr_data_int_from_value:nnn {#1} {#3} {#4}
\__tblr_intarray_gset:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
{ \g__tblr_data_int_from_value_tl }
}
\cs_generate_variant:Nn \__tblr_data_gput:nnnn
{ nnne, nnnV, nenn, nene, nenV, nVnn }
%% #1: data name; #2: data index 1; #3: data index 2; #4: key; #5: value
\cs_new_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5
{
\__tblr_data_int_from_value:nnn {#1} {#4} {#5}
\__tblr_intarray_gset:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
{ \__tblr_data_key_to_int:nnnn {#1} {#2} {#3} {#4} }
{ \g__tblr_data_int_from_value_tl }
}
\cs_generate_variant:Nn \__tblr_data_gput:nnnnn
{ nnnne, nnnnV, neenn, neene, neenV, neeen, nVVnn }
%% #1: data name; #2: data index 1; #3: data index 2; #4: key
\cs_new:Npn \__tblr_data_item:nnnn #1 #2 #3 #4
{
\__tblr_data_int_to_value:nne {#1} {#4}
CHAPTER 8. THE SOURCE CODE 68
{
\intarray_item:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
{ \__tblr_data_key_to_int:nnnn {#1} {#2} {#3} {#4} }
}
}
\cs_generate_variant:Nn \__tblr_data_item:nnnn { neen }
\tl_new:N \l__tblr_data_key_tl
\tl_new:N \l__tblr_data_index_tl
\tl_new:N \l__tblr_data_index_two_tl
\cs_new_protected:Npn \__tblr_data_log:n #1
{
\use:c { __tblr_data_log_ \use:c { c__tblr_data_#1_index_number_tl } :n } {#1}
\__tblr_prop_log:n {#1}
}
\cs_new_protected:cpn { __tblr_data_log_1:n } #1
{
%\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
\tl_set:Nx \l_tmpa_tl { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
\tl_log:n { ----------~----------~----------~----------~---------- }
\int_step_inline:nn
{ \intarray_count:c { \l_tmpa_tl } }
{
\__tblr_data_int_to_key:nnNN {#1} {##1}
\l__tblr_data_index_tl \l__tblr_data_key_tl
\tl_log:x
{
\space
{ #1 [\l__tblr_data_index_tl] / \l__tblr_data_key_tl }
~\space => ~\space
{
\__tblr_data_int_to_value:nVe {#1} \l__tblr_data_key_tl
{ \intarray_item:cn { \l_tmpa_tl } {##1} }
}
}
}
}
\cs_new_protected:cpn { __tblr_data_log_2:n } #1
{
%\intarray_log:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
\tl_set:Nx \l_tmpa_tl { g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
\tl_log:n { ----------~----------~----------~----------~---------- }
\int_step_inline:nn
{ \intarray_count:c { \l_tmpa_tl } }
{
\__tblr_data_int_to_key:nnNNN {#1} {##1}
\l__tblr_data_index_tl \l__tblr_data_index_two_tl \l__tblr_data_key_tl
\tl_log:x
{
\space
{
#1 [\l__tblr_data_index_tl][\l__tblr_data_index_two_tl]
/ \l__tblr_data_key_tl
}
CHAPTER 8. THE SOURCE CODE 69
%% #1: data name; #2: row index; #3: key; #4: value
\cs_new_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4
{
\__tblr_data_int_from_value:nnn {#1} {#3} {#4}
\__tblr_array_gput_if_larger:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
{ \g__tblr_data_int_from_value_tl }
}
\cs_generate_variant:Nn \__tblr_data_gput_if_larger:nnnn { nnne, nnnV, nene, nenV }
\cs_new_protected:Npn \__tblr_array_gput_if_larger:Nnn #1 #2 #3
{
\int_compare:nNnT {#3} > { \intarray_item:Nn #1 {#2} }
{ \__tblr_intarray_gset:Nnn #1 {#2} {#3} }
}
\cs_generate_variant:Nn \__tblr_array_gput_if_larger:Nnn { cnn }
%% #1: data name; #2: data index; #3: key; #4: value
\cs_new_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4
{
\__tblr_data_int_from_value:nnn {#1} {#3} {#4}
\__tblr_array_gadd_value:cnn
{ g__tblr_#1_ \int_use:N \g_tblr_level_int _intarray }
{ \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
{ \g__tblr_data_int_from_value_tl }
}
\cs_generate_variant:Nn \__tblr_data_gadd_dimen_value:nnnn
{ nnne, nnnV, nenn, nene }
\cs_new_protected:Npn \__tblr_array_gadd_value:Nnn #1 #2 #3
{
\__tblr_intarray_gset:Nnn #1 {#2} { \intarray_item:Nn #1 {#2} + #3 }
}
\cs_generate_variant:Nn \__tblr_array_gadd_value:Nnn { cnn }
\bool_new:N \g__tblr_use_intarray_bool
\bool_gset_true:N \g__tblr_use_intarray_bool
\AtBeginDocument
{
\bool_if:NF \g__tblr_use_intarray_bool
{
\cs_set_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4
{
\__tblr_spec_gput:nnn {#1} { [#2] / #3 } {#4}
}
CHAPTER 8. THE SOURCE CODE 70
\cs_set_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5
{
\__tblr_spec_gput:nnn {#1} { [#2][#3] / #4 } {#5}
}
\cs_set:Npn \__tblr_data_item:nnn #1 #2 #3
{
\__tblr_spec_item:nn {#1} { [#2] / #3 }
}
\cs_set:Npn \__tblr_data_item:nnnn #1 #2 #3 #4
{
\__tblr_spec_item:nn {#1} { [#2][#3] / #4 }
}
\cs_set_protected:Npn \__tblr_data_log:n #1
{
\__tblr_spec_log:n {#1}
}
\cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4
{
\__tblr_spec_gput_if_larger:nnn {#1} { [#2] / #3 } {#4}
}
\cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnnn #1 #2 #3 #4 #5
{
\__tblr_spec_gput_if_larger:nnn {#1} { [#2][#3] / #4 } {#5}
}
\cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4
{
\__tblr_spec_gadd_dimen_value:nnn {#1} { [#2] / #3 } {#4}
}
\cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnnn #1 #2 #3 #4 #5
{
\__tblr_spec_gadd_dimen_value:nnn {#1} { [#2][#3] / #4 } {#5}
}
}
}
\tl_new:N \l__tblr_childs_arg_spec_tl
\cs_new_protected:Npn \__tblr_new_child_selector_aux:nnnn #1 #2 #3 #4
{
\clist_if_in:NnTF \g_tblr_used_child_selectors_clist { #1 }
{
\msg_error:nnn { tabularray } { used-child-selector } { #1 }
\clist_log:N \g_tblr_used_child_selectors_clist
}
CHAPTER 8. THE SOURCE CODE 71
{
\__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_childs_arg_spec_tl
\exp_args:NcV \NewDocumentCommand
{ __tblr_child_selector_ #1 :w } \l__tblr_childs_arg_spec_tl { #4 }
\clist_gput_right:Nn \g_tblr_used_child_selectors_clist { #1 }
}
}
\cs_generate_variant:Nn \__tblr_new_child_selector_aux:nnnn { xnnn }
\clist_new:N \l_tblr_childs_clist
\tl_new:N \l_tblr_childs_total_tl
\tl_new:N \l__tblr_child_from_tl
\tl_new:N \l__tblr_child_to_tl
\tl_set:Nx \l__tblr_child_from_tl
{ \int_eval:n { \l__tblr_child_from_tl + 1 } }
}
\__tblr_child_name_to_index:VN \l__tblr_child_to_tl \l__tblr_child_to_tl
\int_step_inline:nnnn { \l__tblr_child_from_tl } {2} { \l__tblr_child_to_tl }
{ \clist_put_right:Nn \l_tblr_childs_clist {##1} }
}
\cs_new_protected:Npn \__tblr_get_childs_normal:nn #1 #2
{
\seq_set_split:Nnn \l__tblr_childs_split_seq {,} {#1}
\seq_map_inline:Nn \l__tblr_childs_split_seq
{
\tl_if_in:nnTF {##1} {-}
{ \__tblr_get_childs_normal_aux:w ##1 \scan_stop }
{ \__tblr_get_childs_normal_aux:w ##1 - ##1 \scan_stop }
}
}
\clist_new:N \g__tblr_table_commands_clist
}
}
\cs_new_protected:Npn \__tblr_enable_table_commands:
{
\clist_map_inline:Nn \g__tblr_table_commands_clist
{ \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 :w } }
}
\cs_new_protected:Npn \__tblr_disable_table_commands:
{
\clist_map_inline:Nn \g__tblr_table_commands_clist
{ \cs_set_eq:Nc ##1 { __tblr_table_command_ \cs_to_str:N ##1 _saved:w } }
}
\cs_new_protected:Npn \__tblr_execute_table_commands:
{
\__tblr_prop_map_inline:nn { command }
{
\__tblr_set_row_col_from_key_name:w ##1
##2
}
\LogTblrTracing { cell }
}
%% Add \empty as a table command so that users can write \\\empty\hline (see #328)
\NewTableCommand\empty{}
\clist_new:N \g__tblr_content_commands_clist
CHAPTER 8. THE SOURCE CODE 75
\cs_new_protected:Npn \__tblr_enable_content_commands:
{
\clist_map_inline:Nn \g__tblr_content_commands_clist
{ \cs_set_eq:Nc ##1 { __tblr_content_command_ \cs_to_str:N ##1 :w } }
}
\dim_zero_new:N \rulewidth
\dim_set:Nn \rulewidth {0.4pt}
\prop_new:N \g__tblr_defined_hdash_styles_prop
\prop_new:N \g__tblr_defined_vdash_styles_prop
\prop_gset_from_keyval:Nn \g__tblr_defined_hdash_styles_prop
{ solid = \hrule height \rulewidth }
\prop_gset_from_keyval:Nn \g__tblr_defined_vdash_styles_prop
{ solid = \vrule width \rulewidth }
\NewDocumentCommand \NewDashStyle { m m }
{
\seq_set_split:Nnn \l_tmpa_seq { ~ } {#2}
\tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {1} }
\tl_set:Nx \l__tblr_b_tl { \seq_item:Nn \l_tmpa_seq {2} }
\tl_set:Nx \l__tblr_c_tl { \seq_item:Nn \l_tmpa_seq {3} }
\tl_set:Nx \l__tblr_d_tl { \seq_item:Nn \l_tmpa_seq {4} }
\tl_if_eq:NnT \l__tblr_a_tl { on }
{
\tl_if_eq:NnT \l__tblr_c_tl { off }
{
\__tblr_dash_style_make_boxes:nxx {#1}
{ \dim_eval:n {\l__tblr_b_tl} } { \dim_eval:n {\l__tblr_d_tl} }
}
}
}
CHAPTER 8. THE SOURCE CODE 76
\cs_new_protected:Npn \__tblr_dash_style_make_boxes:nnn #1 #2 #3
{
\dim_set:Nn \l_tmpa_dim { #2 + #3 }
\tl_set:Nn \l__tblr_h_tl { \hbox_to_wd:nn }
\tl_put_right:Nx \l__tblr_h_tl { { \dim_use:N \l_tmpa_dim } }
\tl_put_right:Nn \l__tblr_h_tl
{
{ \hss \vbox:n { \hbox_to_wd:nn {#2} {} \hrule height \rulewidth } \hss }
}
\prop_gput:NnV \g__tblr_defined_hdash_styles_prop {#1} \l__tblr_h_tl
%\prop_log:N \g__tblr_defined_hdash_styles_prop
\tl_set:Nn \l__tblr_v_tl { \vbox_to_ht:nn }
\tl_put_right:Nx \l__tblr_v_tl { { \dim_use:N \l_tmpa_dim } }
\tl_put_right:Nn \l__tblr_v_tl
{
{ \vss \hbox:n { \vbox_to_ht:nn {#2} {} \vrule width \rulewidth } \vss }
}
\prop_gput:NnV \g__tblr_defined_vdash_styles_prop {#1} \l__tblr_v_tl
%\prop_log:N \g__tblr_defined_vdash_styles_prop
}
\cs_generate_variant:Nn \__tblr_dash_style_make_boxes:nnn { nxx }
\cs_new_protected:Npn \__tblr_get_hline_dash_style:N #1
{
\tl_set:Nx \l_tmpa_tl
{ \prop_item:NV \g__tblr_defined_hdash_styles_prop #1 }
\tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl }
}
\cs_new_protected:Npn \__tblr_get_vline_dash_style:N #1
{
\tl_set:Nx \l_tmpa_tl
{ \prop_item:NV \g__tblr_defined_vdash_styles_prop #1 }
\tl_if_empty:NF \l_tmpa_tl { \tl_set_eq:NN #1 \l_tmpa_tl }
}
%% We put all code inside a group to avoid affecting other table commands
\cs_new_protected:Npn \tblr_set_every_hline:nnn #1 #2 #3
{
CHAPTER 8. THE SOURCE CODE 77
\group_begin:
\int_step_inline:nn { \int_eval:n { \c@rowcount + 1 } }
{
\int_set:Nn \c@rownum {##1}
\tblr_set_hline:nnn {#1} {#2} {#3}
}
\group_end:
}
\cs_new_protected:Npn \tblr_set_hline:nnnn #1 #2 #3 #4
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@rowcount + 1 } }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\int_set:Nn \c@rownum {##1}
\tblr_set_hline:nnn {#2} {#3} {#4}
}
\group_end:
}
}
}
}
\cs_new_protected:Npn \__tblr_set_hline_num_incr:
{
\tl_set:Nx \l__tblr_hline_count_tl
{ \int_eval:n { \l__tblr_hline_count_tl + 1 } }
\__tblr_spec_gput:nee { hline }
{ [\int_use:N \c@rownum] / @hline-count } { \l__tblr_hline_count_tl }
\tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl
}
\keys_define:nn { tblr-hline }
{
dash .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 },
text .code:n = \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text #1 },
text .groups:n = { text },
wd .code:n = \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {#1} },
fg .code:n = \tl_set:Nn \l__tblr_hline_fg_tl {#1},
leftpos .code:n = \tl_set:Nx \l__tblr_hline_leftpos_tl {#1},
rightpos .code:n = \tl_set:Nx \l__tblr_hline_rightpos_tl {#1},
l .meta:n = { leftpos = #1 },
l .default:n = { -0.8 },
r .meta:n = { rightpos = #1 },
r .default:n = { -0.8 },
lr .meta:n = { leftpos = #1, rightpos = #1 },
lr .default:n = { -0.8 },
endpos .bool_set:N = \l__tblr_hline_endpos_bool,
unknown .code:n = \__tblr_hline_unknown_key:V \l_keys_key_str,
}
\cs_new_protected:Npn \__tblr_hline_unknown_key:n #1
{
\prop_if_in:NnTF \g__tblr_defined_hdash_styles_prop {#1}
{ \tl_set:Nn \l__tblr_hline_dash_tl { \exp_not:N \@tblr@dash #1 } }
{
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
{ \tl_set:Nn \l__tblr_hline_fg_tl {#1} }
{
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
\tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {\l__tblr_v_tl} }
}
}
}
\cs_generate_variant:Nn \__tblr_hline_unknown_key:n { V }
\cs_new_protected_nopar:Npn \__tblr_set_hline_cmd:n #1
{
\__tblr_get_childs:nx {#1} { \int_use:N \c@colcount }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\__tblr_set_hline_option:nnn { ##1 } { @dash } { \l__tblr_hline_dash_tl }
\tl_if_empty:NF \l__tblr_hline_wd_tl
{
\__tblr_set_hline_option:nnn { ##1 } { wd } { \l__tblr_hline_wd_tl }
}
CHAPTER 8. THE SOURCE CODE 80
\tl_if_empty:NF \l__tblr_hline_fg_tl
{
\__tblr_set_hline_option:nnn { ##1 } { fg } { \l__tblr_hline_fg_tl }
}
}
\tl_if_empty:NF \l__tblr_hline_leftpos_tl
{
\bool_if:NTF \l__tblr_hline_endpos_bool
{
\__tblr_set_hline_option:nnn
{ \clist_item:Nn \l_tblr_childs_clist {1} }
{ leftpos }
{ \l__tblr_hline_leftpos_tl }
}
{
\clist_map_inline:Nn \l_tblr_childs_clist
{
\__tblr_set_hline_option:nnn
{ ##1 } { leftpos } { \l__tblr_hline_leftpos_tl }
}
}
}
\tl_if_empty:NF \l__tblr_hline_rightpos_tl
{
\bool_if:NTF \l__tblr_hline_endpos_bool
{
\__tblr_set_hline_option:nnn
{ \clist_item:Nn \l_tblr_childs_clist {-1} }
{ rightpos }
{ \l__tblr_hline_rightpos_tl }
}
{
\clist_map_inline:Nn \l_tblr_childs_clist
{
\__tblr_set_hline_option:nnn
{ ##1 } { rightpos } { \l__tblr_hline_rightpos_tl }
}
}
}
}
%% We put all code inside a group to avoid affecting other table commands
\cs_new_protected:Npn \tblr_set_every_vline:nnn #1 #2 #3
{
\group_begin:
\int_step_inline:nn { \int_eval:n { \c@colcount + 1 } }
{
\int_set:Nn \c@colnum {##1}
\tblr_set_vline:nnn {#1} {#2} {#3}
}
\group_end:
}
\cs_new_protected:Npn \tblr_set_vline:nnnn #1 #2 #3 #4
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@colcount + 1} }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\int_set:Nn \c@colnum {##1}
\tblr_set_vline:nnn {#2} {#3} {#4}
}
\group_end:
}
{
\tl_set:Nx \l__tblr_vline_num_tl { 1 }
\__tblr_spec_gput:nen { vline }
{ [\int_use:N \c@colnum] / @vline-count } { 1 }
}
{
\tl_if_eq:nnTF {#1} {+}
{ \__tblr_set_vline_num_incr: }
{
\tl_if_eq:nnTF {#1} {=}
{ \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl }
{
\int_compare:nNnTF {#1} > { \l__tblr_vline_count_tl }
{ \__tblr_set_vline_num_incr: }
{ \tl_set:Nn \l__tblr_vline_num_tl {#1} }
}
}
}
}
\cs_new_protected:Npn \__tblr_set_vline_num_incr:
{
\tl_set:Nx \l__tblr_vline_count_tl
{ \int_eval:n { \l__tblr_vline_count_tl + 1 } }
\__tblr_spec_gput:nee { vline }
{ [\int_use:N \c@colnum] / @vline-count } { \l__tblr_vline_count_tl }
\tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl
}
\keys_define:nn { tblr-vline }
{
dash .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 },
text .code:n = \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@text #1 },
text .groups:n = { text },
wd .code:n = \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {#1} },
fg .code:n = \tl_set:Nn \l__tblr_vline_fg_tl {#1},
abovepos .code:n = \tl_set:Nx \l__tblr_vline_abovepos_tl {#1},
belowpos .code:n = \tl_set:Nx \l__tblr_vline_belowpos_tl {#1},
unknown .code:n = \__tblr_vline_unknown_key:V \l_keys_key_str,
}
\cs_new_protected:Npn \__tblr_vline_unknown_key:n #1
{
\prop_if_in:NnTF \g__tblr_defined_vdash_styles_prop {#1}
{ \tl_set:Nn \l__tblr_vline_dash_tl { \exp_not:N \@tblr@dash #1 } }
{
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
{ \tl_set:Nn \l__tblr_vline_fg_tl {#1} }
{
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
\tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {\l__tblr_v_tl} }
}
}
}
\cs_generate_variant:Nn \__tblr_vline_unknown_key:n { V }
\cs_new_protected_nopar:Npn \__tblr_set_vline_cmd:n #1
CHAPTER 8. THE SOURCE CODE 84
{
\__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\__tblr_spec_gput:nee { vline }
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / @dash }
{ \l__tblr_vline_dash_tl }
\tl_if_empty:NF \l__tblr_vline_wd_tl
{
\__tblr_spec_gput:nee { vline }
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / wd }
{ \l__tblr_vline_wd_tl }
}
\tl_if_empty:NF \l__tblr_vline_fg_tl
{
\__tblr_spec_gput:nee { vline }
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / fg }
{ \l__tblr_vline_fg_tl }
}
\tl_if_empty:NF \l__tblr_vline_abovepos_tl
{
\__tblr_spec_gput:nee { vline }
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / abovepos }
{ \l__tblr_vline_abovepos_tl }
}
\tl_if_empty:NF \l__tblr_vline_belowpos_tl
{
\__tblr_spec_gput:nee { vline }
{ [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / belowpos }
{ \l__tblr_vline_belowpos_tl }
}
}
}
\cs_new_protected:Npn \tblr_set_hborder:n #1
{
\keys_set:nn { tblr-hborder } {#1}
}
\cs_new_protected:Npn \tblr_set_hborder:nn #1 #2
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@rowcount + 1 } }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\int_set:Nn \c@rownum {##1}
\tblr_set_hborder:n {#2}
}
\group_end:
}
CHAPTER 8. THE SOURCE CODE 85
\keys_define:nn { tblr-hborder }
{
abovespace .code:n = \__tblr_row_gput_above:ne
{ belowsep } { \dim_eval:n {#1} },
belowspace .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} },
abovespace+ .code:n = \__tblr_row_gadd_dimen_above:ne
{ belowsep } { \dim_eval:n {#1} },
belowspace+ .code:n = \__tblr_row_gadd_dimen:ne
{ abovesep } { \dim_eval:n {#1} },
pagebreak .code:n = \__tblr_hborder_gput_pagebreak:n {#1},
pagebreak .default:n = yes,
baseline .code:n = \__tblr_outer_gput_spec:ne
{ baseline } { - \int_use:N \c@rownum },
}
\tl_const:Nn \c__tblr_pagebreak_yes_tl { 1 }
\tl_const:Nn \c__tblr_pagebreak_auto_tl { 0 }
\tl_const:Nn \c__tblr_pagebreak_no_tl { -1 }
\cs_new_protected:Npn \__tblr_hborder_gput_pagebreak:n #1
{
\tl_if_exist:cT { c__tblr_pagebreak_ #1 _tl }
{
\__tblr_spec_gput:nee { hline }
{ [\int_use:N \c@rownum] / @pagebreak }
{ \tl_use:c { c__tblr_pagebreak_ #1 _tl } }
}
}
\cs_new_protected:Npn \tblr_set_vborder:n #1
{
\keys_set:nn { tblr-vborder } {#1}
}
\cs_new_protected:Npn \tblr_set_vborder:nn #1 #2
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_eval:n { \c@colcount + 1 } }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\int_set:Nn \c@colnum {##1}
\tblr_set_vborder:n {#2}
}
\group_end:
}
CHAPTER 8. THE SOURCE CODE 86
\keys_define:nn { tblr-vborder }
{
leftspace .code:n = \__tblr_column_gput_left:ne
{ rightsep } { \dim_eval:n {#1} },
rightspace .code:n = \__tblr_column_gput:ne { leftsep } { \dim_eval:n {#1} },
leftspace+ .code:n = \__tblr_column_gadd_dimen_left:ne
{ rightsep } { \dim_eval:n {#1} },
rightspace+ .code:n = \__tblr_column_gadd_dimen:ne
{ leftsep } { \dim_eval:n {#1} },
}
%% We put all code inside a group to avoid affecting other table commands
\cs_new_protected:Npn \tblr_set_every_cell:nn #1 #2
{
\group_begin:
\int_step_inline:nn { \c@rowcount }
{
\int_set:Nn \c@rownum {##1}
\int_step_inline:nn { \c@colcount }
{
\int_set:Nn \c@colnum {####1}
\tblr_set_cell:nn {#1} {#2}
}
}
\group_end:
}
{
\tblr_set_cell:nn { #1 } { #2 }
}
\tl_new:N \l__tblr_row_span_num_tl
\tl_new:N \l__tblr_col_span_num_tl
\cs_new_protected:Npn \tblr_set_cell:nn #1 #2
{
\tl_set:Nn \l__tblr_row_span_num_tl { 1 }
\tl_set:Nn \l__tblr_col_span_num_tl { 1 }
\keys_set:nn { tblr-cell-span } { #1 }
\keys_set:nn { tblr-cell-spec } { #2 }
\__tblr_set_span_spec:VV \l__tblr_row_span_num_tl \l__tblr_col_span_num_tl
}
\cs_generate_variant:Nn \tblr_set_cell:nn { nV }
\cs_new_protected:Npn \tblr_set_cell:nnnn #1 #2 #3 #4
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
\clist_set_eq:NN \l_tmpa_clist \l_tblr_childs_clist
\__tblr_get_childs:nx {#2} { \int_use:N \c@colcount }
\clist_set_eq:NN \l_tmpb_clist \l_tblr_childs_clist
\clist_map_inline:Nn \l_tmpa_clist
{
\int_set:Nn \c@rownum {##1}
\clist_map_inline:Nn \l_tmpb_clist
{
\int_set:Nn \c@colnum {####1}
\tblr_set_cell:nn {#3} {#4}
}
}
\group_end:
}
\keys_define:nn { tblr-cell-span }
{
r .tl_set:N = \l__tblr_row_span_num_tl,
c .tl_set:N = \l__tblr_col_span_num_tl,
}
\keys_define:nn { tblr-cell-spec }
{
halign .code:n = \__tblr_cell_gput:nn { halign } {#1},
CHAPTER 8. THE SOURCE CODE 88
\cs_new_protected:Npn \__tblr_cell_gput:nn #1 #2
{
\__tblr_data_gput:neenn { cell }
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_cell_gput:nn { ne }
\cs_new_protected:Npn \__tblr_cell_gput:nnnn #1 #2 #3 #4
{
\__tblr_data_gput:nnnnn { cell } {#1} {#2} {#3} {#4}
}
\cs_generate_variant:Nn \__tblr_cell_gput:nnnn
{ nenn, ennn, eenn, nene, enne, eene }
\tl_new:N \l__tblr_cell_text_tl
\cs_new_protected:Npn \__tblr_cell_preto_text:n #1
{
\__tblr_cell_preto_text:een
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1}
}
\cs_new_protected:Npn \__tblr_cell_preto_text:nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:nn { text } { [#1][#2] } }
\tl_put_left:Nn \l__tblr_cell_text_tl {#3}
\__tblr_spec_gput:nnV { text } { [#1][#2] } \l__tblr_cell_text_tl
}
\cs_generate_variant:Nn \__tblr_cell_preto_text:nnn { nen, enn, een }
\cs_new_protected:Npn \__tblr_cell_appto_text:n #1
{
CHAPTER 8. THE SOURCE CODE 89
\__tblr_cell_appto_text:een
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } {#1}
}
\cs_new_protected:Npn \__tblr_cell_appto_text:nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:ne { text } { [#1][#2] } }
\tl_put_right:Nn \l__tblr_cell_text_tl {#3}
\__tblr_spec_gput:neV { text } { [#1][#2] } \l__tblr_cell_text_tl
}
\cs_generate_variant:Nn \__tblr_cell_appto_text:nnn { nen, enn, een }
\cs_new_protected:Npn \__tblr_cell_unknown_key:n #1
{
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
{
\__tblr_data_gput:neene { cell }
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { background } {#1}
}
{
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
\__tblr_data_gput:neene { cell }
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { width }
{ \dim_eval:n { \l__tblr_v_tl } }
}
}
\cs_generate_variant:Nn \__tblr_cell_unknown_key:n { V }
\cs_new_protected:Npn \__tblr_set_span_spec:nn #1 #2
{
\int_compare:nNnT { #1 } > { 1 }
{
\__tblr_prop_gput:nnn { inner } { rowspan } { true }
\__tblr_data_gput:neenn { cell }
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { rowspan } {#1}
}
\int_compare:nNnT { #2 } > { 1 }
{
\__tblr_prop_gput:nnn { inner } { colspan } { true }
\__tblr_data_gput:neenn { cell }
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { colspan } {#2}
}
\int_step_variable:nnNn
{ \int_use:N \c@rownum } { \int_eval:n { \c@rownum + #1 - 1 } } \l__tblr_i_tl
{
\int_step_variable:nnNn
{ \int_use:N \c@colnum } { \int_eval:n { \c@colnum + #2 - 1 } }
\l__tblr_j_tl
{
\bool_lazy_and:nnF
{ \int_compare_p:nNn { \l__tblr_i_tl } = { \c@rownum } }
{ \int_compare_p:nNn { \l__tblr_j_tl } = { \c@colnum } }
{
\__tblr_data_gput:neenn { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { omit } {1}
}
\int_compare:nNnF { \l__tblr_i_tl } = { \c@rownum }
CHAPTER 8. THE SOURCE CODE 90
{
\__tblr_spec_gput:nen { hline }
{ [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
}
\int_compare:nNnF { \l__tblr_j_tl } = { \c@colnum }
{
\__tblr_spec_gput:nee { vline }
{ [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
}
}
}
%% Make continuous borders for multirow cells
\tl_set:Nx \l__tblr_n_tl
{
\int_max:nn
{
\__tblr_spec_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count }
}
{ 1 }
}
\int_step_variable:nnNn
{ \c@rownum } { \int_eval:n { \c@rownum + #1 - 2 } } \l__tblr_i_tl
{
\__tblr_spec_gput:nee { vline }
{ [\l__tblr_i_tl][\int_use:N \c@colnum](\l__tblr_n_tl) / belowpos } {1}
\__tblr_spec_gput:nee { vline }
{ [\l__tblr_i_tl][\int_eval:n {\c@colnum + #2}](1) / belowpos } {1}
}
}
\cs_generate_variant:Nn \__tblr_set_span_spec:nn { VV }
%% We put all code inside a group to avoid affecting other table commands
\cs_new_protected:Npn \tblr_set_every_column:nn #1 #2
{
\group_begin:
\int_step_inline:nn { \c@colcount }
{
\int_set:Nn \c@colnum {##1}
\tblr_set_column:nn {#1} {#2}
}
\group_end:
}
\cs_new_protected:Npn \tblr_set_column:nn #1 #2
{
\keys_set:nn { tblr-column } {#2}
}
\cs_new_protected:Npn \tblr_set_column:nnn #1 #2 #3
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_use:N \c@colcount }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\int_set:Nn \c@colnum {##1}
\tblr_set_column:nn {#2} {#3}
}
\group_end:
}
\cs_generate_variant:Nn \__tblr_set_column_aux:nn { Vn }
\keys_define:nn { tblr-column }
{
halign .code:n = \__tblr_column_gput_cell:nn { halign } {#1},
valign .code:n = \__tblr_column_gput_cell:nn { valign } {#1},
j .meta:n = { halign = j },
l .meta:n = { halign = l },
c .meta:n = { halign = c },
r .meta:n = { halign = r },
t .meta:n = { valign = t },
p .meta:n = { valign = t },
m .meta:n = { valign = m },
b .meta:n = { valign = b },
h .meta:n = { valign = h },
f .meta:n = { valign = f },
bg .code:n = \__tblr_column_gput_cell:nn { background } {#1},
fg .code:n = \__tblr_column_gput_cell:nn { foreground } {#1},
font .code:n = \__tblr_column_gput_cell:nn { font } { #1 \selectfont },
mode .code:n = \__tblr_column_gput_cell:nn { mode } {#1},
$ .meta:n = { mode = math },
$$ .meta:n = { mode = dmath },
cmd .code:n = \__tblr_column_gput_cell:nn { cmd } {#1},
wd .code:n = \__tblr_column_gput:ne { width } { \dim_eval:n {#1} },
co .code:n = \__tblr_column_gput:ne { coefficient } {#1},
preto .code:n = \__tblr_preto_text_for_every_column_cell:n {#1},
appto .code:n = \__tblr_appto_text_for_every_column_cell:n {#1},
leftsep .code:n = \__tblr_column_gput:ne { leftsep } { \dim_eval:n {#1} },
rightsep .code:n = \__tblr_column_gput:ne { rightsep } { \dim_eval:n {#1} },
colsep .meta:n = { leftsep = #1, rightsep = #1},
leftsep+ .code:n = \__tblr_column_gadd_dimen:ne
{ leftsep } { \dim_eval:n {#1} },
rightsep+ .code:n = \__tblr_column_gadd_dimen:ne
{ rightsep } { \dim_eval:n {#1} },
colsep+ .meta:n = { leftsep+ = #1, rightsep+ = #1},
unknown .code:n = \__tblr_column_unknown_key:V \l_keys_key_str,
}
\cs_new_protected:Npn \__tblr_column_gput_left:nn #1 #2
{
\__tblr_data_gput:nenn { column } { \int_eval:n { \c@colnum - 1 } } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_column_gput_left:nn { ne }
\cs_new_protected:Npn \__tblr_column_gadd_dimen:nn #1 #2
{
\__tblr_data_gadd_dimen_value:nenn { column }
{ \int_use:N \c@colnum } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_column_gadd_dimen:nn { ne }
CHAPTER 8. THE SOURCE CODE 93
\cs_new_protected:Npn \__tblr_column_gadd_dimen_left:nn #1 #2
{
\__tblr_data_gadd_dimen_value:nenn { column }
{ \int_eval:n { \c@colnum - 1 } } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_column_gadd_dimen_left:nn { ne }
\cs_new_protected:Npn \__tblr_preto_text_for_every_column_cell:n #1
{
\int_step_inline:nn { \c@rowcount }
{
\__tblr_cell_preto_text:nen {##1} { \int_use:N \c@colnum } {#1}
}
}
\cs_new_protected:Npn \__tblr_appto_text_for_every_column_cell:n #1
{
\int_step_inline:nn { \c@rowcount }
{
\__tblr_cell_appto_text:nen {##1} { \int_use:N \c@colnum } {#1}
}
}
\cs_new_protected:Npn \__tblr_column_unknown_key:n #1
{
\regex_match:NnTF \c__tblr_is_number_key_regex {#1}
{ \__tblr_column_gput:ne { coefficient } {#1} }
{
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
{ \__tblr_column_gput_cell:nn { background } {#1} }
{
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
\__tblr_column_gput:ne { width } { \dim_eval:n { \l__tblr_v_tl } }
}
}
}
\cs_generate_variant:Nn \__tblr_column_unknown_key:n { V }
%% We put all code inside a group to avoid affecting other table commands
\cs_new_protected:Npn \tblr_set_every_row:nn #1 #2
{
\group_begin:
\int_step_inline:nn { \c@rowcount }
{
\int_set:Nn \c@rownum {##1}
\tblr_set_row:nn {#1} {#2}
}
\group_end:
}
\cs_new_protected:Npn \tblr_set_row:nn #1 #2
{
\keys_set:nn { tblr-row } {#2}
}
\cs_new_protected:Npn \tblr_set_row:nnn #1 #2 #3
{
\group_begin:
\__tblr_get_childs:nx {#1} { \int_use:N \c@rowcount }
\clist_map_inline:Nn \l_tblr_childs_clist
{
\int_set:Nn \c@rownum {##1}
\tblr_set_row:nn {#2} {#3}
}
\group_end:
}
\keys_define:nn { tblr-row }
{
halign .code:n = \__tblr_row_gput_cell:nn { halign } {#1},
valign .code:n = \__tblr_row_gput_cell:nn { valign } {#1},
j .meta:n = { halign = j },
l .meta:n = { halign = l },
c .meta:n = { halign = c },
r .meta:n = { halign = r },
t .meta:n = { valign = t },
p .meta:n = { valign = t },
m .meta:n = { valign = m },
b .meta:n = { valign = b },
h .meta:n = { valign = h },
f .meta:n = { valign = f },
bg .code:n = \__tblr_row_gput_cell:nn { background } {#1},
fg .code:n = \__tblr_row_gput_cell:nn { foreground } {#1},
font .code:n = \__tblr_row_gput_cell:nn { font } { #1 \selectfont },
mode .code:n = \__tblr_row_gput_cell:nn { mode } {#1},
$ .meta:n = { mode = math },
$$ .meta:n = { mode = dmath },
cmd .code:n = \__tblr_row_gput_cell:nn { cmd } {#1},
ht .code:n = \__tblr_row_gput:ne { height } { \dim_eval:n {#1} },
co .code:n = \__tblr_row_gput:ne { coefficient } {#1},
preto .code:n = \__tblr_preto_text_for_every_row_cell:n {#1},
appto .code:n = \__tblr_appto_text_for_every_row_cell:n {#1},
abovesep .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} },
belowsep .code:n = \__tblr_row_gput:ne { belowsep } { \dim_eval:n {#1} },
rowsep .meta:n = { abovesep = #1, belowsep = #1},
abovesep+ .code:n = \__tblr_row_gadd_dimen:ne { abovesep } { \dim_eval:n {#1} },
belowsep+ .code:n = \__tblr_row_gadd_dimen:ne { belowsep } { \dim_eval:n {#1} },
rowsep+ .meta:n = { abovesep+ = #1, belowsep+ = #1},
baseline .code:n = \__tblr_outer_gput_spec:ne
{ baseline } { \int_use:N \c@rownum },
unknown .code:n = \__tblr_row_unknown_key:V \l_keys_key_str,
}
\cs_new_protected:Npn \__tblr_row_gput_above:nn #1 #2
{
\__tblr_data_gput:nenn { row } { \int_eval:n { \c@rownum - 1 } } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_row_gput_above:nn { ne }
\cs_new_protected:Npn \__tblr_row_gadd_dimen:nn #1 #2
{
\__tblr_data_gadd_dimen_value:nenn { row } { \int_use:N \c@rownum } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_row_gadd_dimen:nn { ne }
\cs_new_protected:Npn \__tblr_row_gadd_dimen_above:nn #1 #2
{
CHAPTER 8. THE SOURCE CODE 96
\__tblr_data_gadd_dimen_value:nenn { row }
{ \int_eval:n { \c@rownum - 1 } } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_row_gadd_dimen_above:nn { ne }
\cs_new_protected:Npn \__tblr_preto_text_for_every_row_cell:n #1
{
\int_step_inline:nn { \c@colcount }
{
\__tblr_cell_preto_text:enn { \int_use:N \c@rownum } {##1} {#1}
}
}
\cs_new_protected:Npn \__tblr_appto_text_for_every_row_cell:n #1
{
\int_step_inline:nn { \c@colcount }
{
\__tblr_cell_appto_text:enn { \int_use:N \c@rownum } {##1} {#1}
}
}
\cs_new_protected:Npn \__tblr_row_unknown_key:n #1
{
\regex_match:NnTF \c__tblr_is_number_key_regex {#1}
{
\__tblr_data_gput:nene { row } { \int_use:N \c@rownum }
{ coefficient } {#1}
}
{
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
{ \__tblr_row_gput_cell:nn { background } {#1} }
{
\tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
\__tblr_row_gput:ne { height } { \dim_eval:n { \l__tblr_v_tl } }
}
}
}
\cs_generate_variant:Nn \__tblr_row_unknown_key:n { V }
\hborder { pagebreak = no }
}
\str_new:N \g_tblr_used_column_types_str
\str_gset_eq:NN \g_tblr_used_column_types_str \c_tblr_primitive_colrow_types_str
\str_new:N \g_tblr_used_row_types_str
\str_gset_eq:NN \g_tblr_used_row_types_str \c_tblr_primitive_colrow_types_str
\bool_new:N \g__tblr_colrow_spec_expand_stop_bool
\tl_new:N \g__tblr_column_or_row_tl
\cs_new_protected:Npn \__tblr_new_column_or_row_type:nnnn #1 #2 #3 #4
{
\str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
{
\tl_if_eq:NnTF \g__tblr_column_or_row_tl { row }
{ \msg_error:nnnn { tabularray } { used-colrow-type } { Row } {#1} }
{ \msg_error:nnnn { tabularray } { used-colrow-type } { Column } {#1} }
\str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str }
}
{
\__tblr_make_xparse_arg_spec:nnN {#2} {#3} \l__tblr_a_tl
\exp_args:NcV \NewDocumentCommand
{ tblr_ \g__tblr_column_or_row_tl _type_ #1 } \l__tblr_a_tl
{
\bool_gset_false:N \g__tblr_colrow_spec_expand_stop_bool
\tl_gput_right:Nf \g__tblr_expanded_colrow_spec_tl {#4}
\__tblr_expand_colrow_spec_next:N
}
\str_gput_right:cn
{ g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
}
}
\NewColumnRowType { l } { Q[l] }
\NewColumnRowType { c } { Q[c] }
\NewColumnRowType { r } { Q[r] }
\NewColumnRowType { j } { Q[j] }
\cs_new_protected:Npn \__tblr_parse_colrow_spec:nn #1 #2
{
\tl_gset:Nn \g__tblr_column_or_row_tl {#1}
CHAPTER 8. THE SOURCE CODE 101
\cs_new_protected:Npn \__tblr_expand_colrow_spec:N #1
{
\bool_do_until:Nn \g__tblr_colrow_spec_expand_stop_bool
{
\LogTblrTracing { colspec, rowspec }
\bool_gset_true:N \g__tblr_colrow_spec_expand_stop_bool
\tl_set_eq:NN \l_tmpa_tl #1
\tl_gclear:N #1
\exp_last_unbraced:NV
\__tblr_expand_colrow_spec_next:N \l_tmpa_tl \scan_stop:
}
}
\cs_new_protected:Npn \__tblr_expand_colrow_spec_next:N #1
{
\token_if_eq_catcode:NNTF #1 \scan_stop:
{
\token_if_eq_meaning:NNF #1 \scan_stop:
{
\msg_error:nnVn { tabularray } { unexpandable-colrow-type }
\g__tblr_column_or_row_tl {#1}
}
}
{
\str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1}
{
%% Note that #1 may be an active character (see issue #58)
\cs:w tblr_ \g__tblr_column_or_row_tl _type_ \token_to_str:N #1 \cs_end:
}
{
\msg_error:nnVn { tabularray } { unknown-colrow-type }
\g__tblr_column_or_row_tl {#1}
\str_log:c { g_tblr_used_ \g__tblr_column_or_row_tl _types_str }
}
}
}
\cs_new_protected:Npn \__tblr_execute_colrow_spec:N #1
{
\tl_if_eq:NnTF \g__tblr_column_or_row_tl { row }
{ \int_set:Nn \c@rownum {1} }
CHAPTER 8. THE SOURCE CODE 102
\cs_new_protected:Npn \__tblr_execute_colrow_spec_next:N #1
{
\token_if_eq_meaning:NNF #1 \scan_stop:
{ \cs:w tblr_primitive_ \g__tblr_column_or_row_tl _type_ #1 \cs_end: }
}
\tl_new:N \l__tblr_env_name_tl
\bool_new:N \l__tblr_math_mode_bool
\bool_new:N \lTblrMeasuringBool
\tl_new:N \l__tblr_body_tl
\seq_new:N \l__tblr_lines_seq
\tl_new:N \l__tblr_expand_tl
\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_map_inline:Nn \l__tblr_expand_tl
{
CHAPTER 8. THE SOURCE CODE 105
}
}
\cs_new_protected:Npn \__tblr_trim_par_space_tokens:N #1
{
\regex_replace_once:NnN \c__tblr_trim_left_par_space_regex {} #1
\regex_replace_once:NnN \c__tblr_trim_right_space_par_regex {} #1
}
CHAPTER 8. THE SOURCE CODE 107
\tl_new:N \l__tblr_saved_table_commands_before_cell_text_tl
\tl_new:N \l__tblr_saved_cell_text_after_table_commands_tl
\cs_new_protected:Npn \__tblr_extract_table_commands:N #1
{
\tl_clear:N \l__tblr_saved_table_commands_before_cell_text_tl
\tl_clear:N \l__tblr_saved_cell_text_after_table_commands_tl
\exp_last_unbraced:NV \__tblr_extract_table_commands_next:n #1 \q_stop
\tl_if_empty:NF \l__tblr_saved_table_commands_before_cell_text_tl
{
\__tblr_prop_gput:nxV { command }
{[\int_use:N \c@rownum][\int_use:N \c@colnum]}
\l__tblr_saved_table_commands_before_cell_text_tl
}
\tl_set_eq:NN #1 \l__tblr_saved_cell_text_after_table_commands_tl
}
\cs_new_protected:Npn \__tblr_extract_one_table_command:N #1
{
\int_set:Nn \l__tblr_a_int
{ \cs:w g__tblr_table_cmd_ \cs_to_str:N #1 _arg_numb_tl \cs_end: }
\tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl {#1}
\int_compare:nNnTF {\l__tblr_a_int} < {0}
{
\int_set:Nn \l__tblr_a_int { \int_abs:n {\l__tblr_a_int} - 1 }
\peek_charcode:NTF [
{ \__tblr_extract_table_command_arg_o:w }
{ \__tblr_extract_table_command_arg_next: }
}
{ \__tblr_extract_table_command_arg_next: }
}
\cs_new_protected:Npn \__tblr_extract_table_command_arg_m:n #1
{
\tl_put_right:Nn \l__tblr_saved_table_commands_before_cell_text_tl { {#1} }
\__tblr_extract_table_command_arg_next:
}
\cs_new_protected:Npn \__tblr_extract_table_command_arg_next:
{
\int_compare:nNnTF {\l__tblr_a_int} > {0}
{
\int_decr:N \l__tblr_a_int
\__tblr_extract_table_command_arg_m:n
}
{ \__tblr_extract_table_commands_next:n }
}
\prop_gset_from_keyval:Nn \g__tblr_initial_table_prop
{
stretch = 1,
rulesep = 2pt,
}
\prop_gset_from_keyval:Nn \g__tblr_initial_rows_prop
{
abovesep = 2pt,
belowsep = 2pt,
@row-height = 0pt,
@row-head = 0pt,
@row-foot = 0pt,
@row-upper = 0pt,
@row-lower = 0pt,
}
\prop_gset_from_keyval:Nn \g__tblr_initial_columns_prop
{
leftsep = 6pt,
rightsep = 6pt,
width = -1pt, % column width unset
coefficient = 0, % column coefficient unset
@col-width = 0pt,
CHAPTER 8. THE SOURCE CODE 109
\prop_gset_from_keyval:Nn \g__tblr_initial_cells_prop
{
halign = j,
valign = t,
width = -1pt, % cell width unset
rowspan = 1,
colspan = 1,
omit = 0,
}
\prop_gset_from_keyval:Nn \g__tblr_initial_hlines_prop
{
@hline-count = 0,
}
\prop_gset_from_keyval:Nn \g__tblr_initial_vlines_prop
{
@vline-count = 0,
}
\tl_new:N \l__tblr_inner_spec_measure_tl
\tl_new:N \l__tblr_inner_spec_verb_tl
\cs_new_protected:Npn \__tblr_init_table_inner_spec:
{
\prop_map_inline:Nn \g__tblr_initial_table_prop
{
\__tblr_prop_gput:nxn { inner } { ##1 } {##2}
}
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
{
\prop_map_inline:Nn \g__tblr_initial_rows_prop
{
\__tblr_data_gput:nVnn { row } \l__tblr_i_tl {##1} {##2}
}
\prop_map_inline:Nn \g__tblr_initial_hlines_prop
{
\__tblr_spec_gput:nen { hline } { [\l__tblr_i_tl] / ##1 } {##2}
}
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
\prop_map_inline:Nn \g__tblr_initial_cells_prop
{
\__tblr_data_gput:neeen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } {##1} {##2}
}
}
}
\prop_map_inline:Nn \g__tblr_initial_hlines_prop
{
\__tblr_spec_gput:nen { hline }
{ [\int_eval:n { \c@rowcount + 1}] / ##1 } {##2}
}
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
CHAPTER 8. THE SOURCE CODE 110
\prop_map_inline:Nn \g__tblr_initial_columns_prop
{
\__tblr_data_gput:nenn { column } { \l__tblr_j_tl } {##1} {##2}
}
\prop_map_inline:Nn \g__tblr_initial_vlines_prop
{
\__tblr_spec_gput:nen { vline } { [\l__tblr_j_tl] / ##1 } {##2}
}
}
\prop_map_inline:Nn \g__tblr_initial_vlines_prop
{
\__tblr_spec_gput:nen { vline }
{ [\int_eval:n { \c@colcount + 1}] / ##1 } {##2}
}
\tl_clear:N \l__tblr_inner_spec_measure_tl
\tl_clear:N \l__tblr_inner_spec_verb_tl
\keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _inner_tl }
}
\keys_define:nn { tblr }
{
colspec .code:n = \__tblr_parse_colrow_spec:nn { column } {#1},
rowspec .code:n = \__tblr_parse_colrow_spec:nn { row } {#1},
width .code:n = \__tblr_keys_gput:nx { width } { \dim_eval:n {#1} },
hspan .code:n = \__tblr_keys_gput:nn { hspan } {#1},
vspan .code:n = \__tblr_keys_gput:nn { vspan } {#1},
stretch .code:n = \__tblr_keys_gput:nn { stretch } {#1},
verb .tl_set:N = \l__tblr_inner_spec_verb_tl,
verb .default:n = lite,
columns .code:n = \__tblr_set_every_column_aux:n {#1},
rows .code:n = \__tblr_set_every_row_aux:n {#1},
cells .code:n = \__tblr_set_every_cell_aux:n {#1},
hlines .code:n = \__tblr_set_every_hline_aux:n {#1},
vlines .code:n = \__tblr_set_every_vline_aux:n {#1},
leftsep .code:n = \tblr_set_every_column:nn { } { leftsep = #1 },
rightsep .code:n = \tblr_set_every_column:nn { } { rightsep = #1 },
colsep .meta:n = { leftsep = #1, rightsep = #1 },
abovesep .code:n = \tblr_set_every_row:nn { } { abovesep = #1 },
belowsep .code:n = \tblr_set_every_row:nn { } { belowsep = #1 },
rowsep .meta:n = { abovesep = #1, belowsep = #1 },
rulesep .code:n = \__tblr_keys_gput:nn { rulesep } {#1},
rowhead .code:n = \__tblr_keys_gput:nn { rowhead } {#1},
rowfoot .code:n = \__tblr_keys_gput:nn { rowfoot } {#1},
delimiter .code:n = \__tblr_set_delimiter:n {#1},
baseline .code:n = \__tblr_outer_gput_spec:nn { baseline } {#1},
CHAPTER 8. THE SOURCE CODE 111
\cs_new_protected:Npn \__tblr_table_special_key:nn #1 #2
{
\regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq
{
\tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} }
\tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} }
\cs:w __tblr_set_ \l__tblr_a_tl _aux:Vn \cs_end: \l__tblr_b_tl {#2}
}
}
\cs_generate_variant:Nn \__tblr_table_special_key:nn { Vn }
\cs_new_protected:Npn \__tblr_parse_table_spec:n #1
{
\regex_extract_once:NnNTF \c__tblr_first_key_name_regex {#1} \l_tmpa_seq
{
\clist_if_in:NxTF \g__tblr_table_known_keys_clist
{ \seq_item:Nn \l_tmpa_seq {2} }
{ \keys_set:nn { tblr } {#1} }
{ \__tblr_parse_colrow_spec:nn { column } {#1} }
}
{ \__tblr_parse_colrow_spec:nn { column } {#1} }
}
\cs_new_protected:Npn \__tblr_keys_gput:nn #1 #2
{
\__tblr_prop_gput:nnn { inner } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_keys_gput:nn { nx }
\keys_define:nn { tblr-delimiter }
{
left .code:n = \__tblr_keys_gput:nn { delim-left } { \left #1 },
right .code:n = \__tblr_keys_gput:nn { delim-right } { \right #1 }
}
\cs_new_protected:Npn \__tblr_set_delimiter:n #1
{
\keys_set:nn { tblr-delimiter } {#1}
}
CHAPTER 8. THE SOURCE CODE 112
\cs_new_protected:Npn \__tblr_use_theme:n #1
{
\ignorespaces
\tl_use:c { g__tblr_theme_ #1 _code_tl }
}
\cs_new_protected:Npn \__tblr_init_table_outer_spec:
{
\keys_set:nv { tblr-outer } { l__tblr_default_ \l__tblr_env_name_tl _outer_tl }
}
\cs_new_protected:Npn \__tblr_parse_table_option:n #1
{
\keys_set:nn { tblr-outer } {#1}
}
\keys_define:nn { tblr-outer }
{
long .code:n = \__tblr_outer_gput_spec:nn { long } { true },
tall .code:n = \__tblr_outer_gput_spec:nn { tall } { true },
halign .code:n = \__tblr_outer_gput_spec:nn { halign } {#1},
baseline .code:n = \__tblr_outer_gput_spec:nn { baseline } {#1},
l .meta:n = { halign = l },
c .meta:n = { halign = c },
r .meta:n = { halign = r },
t .meta:n = { baseline = t },
T .meta:n = { baseline = T },
m .meta:n = { baseline = m },
M .meta:n = { baseline = M },
b .meta:n = { baseline = b },
B .meta:n = { baseline = B },
valign .meta:n = { baseline = #1 }, % obsolete, will be removed some day
expand .code:n = \__tblr_outer_gput_spec:nn { expand } {#1},
expand+ .code:n = \__tblr_outer_gconcat_spec:nn { expand } {#1},
headsep .code:n = \__tblr_outer_gput_spec:nn { headsep } {#1},
footsep .code:n = \__tblr_outer_gput_spec:nn { footsep } {#1},
presep .code:n = \__tblr_outer_gput_spec:nn { presep } {#1},
postsep .code:n = \__tblr_outer_gput_spec:nn { postsep } {#1},
theme .code:n = \__tblr_use_theme:n {#1},
caption .code:n = \__tblr_outer_gput_spec:nn { caption } {#1},
entry .code:n = \__tblr_outer_gput_spec:nn { entry } {#1},
CHAPTER 8. THE SOURCE CODE 113
\cs_new_protected:Npn \__tblr_outer_gput_spec:nn #1 #2
{
\__tblr_spec_gput:nen { outer } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_outer_gput_spec:nn { ne }
\cs_new_protected:Npn \__tblr_outer_gconcat_spec:nn #1 #2
{
\__tblr_outer_gput_spec:ne {#1} { \__tblr_spec_item:nn { outer } { #1 } \exp_not:n { #2 } }
}
\cs_new_protected:Npn \__tblr_table_option_key:nn #1 #2
{
\regex_match:NnTF \c__tblr_option_key_name_regex {#1}
{ \msg_error:nnn { tabularray } { unknown-outer-key } {#1} }
{
\regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq
{
\tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} }
\tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} }
\tl_set:Nx \l__tblr_c_tl { \tl_head:N \l__tblr_b_tl }
\use:c { __tblr_outer_gput_ \l__tblr_a_tl :Vn } \l__tblr_c_tl {#2}
}
}
}
\cs_generate_variant:Nn \__tblr_table_option_key:nn { Vn }
\cs_new_protected:Npn \__tblr_outer_gput_note:nn #1 #2
{
\__tblr_prop_gput:nnn { note } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_outer_gput_note:nn { Vn }
\cs_new_protected:Npn \__tblr_outer_gput_remark:nn #1 #2
{
\__tblr_prop_gput:nnn { remark } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_outer_gput_remark:nn { Vn }
\cs_new_protected:Npn \__tblr_outer_gput_more:nn #1 #2
{
\__tblr_prop_gput:nnn { more } {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_outer_gput_more:nn { Vn }
CHAPTER 8. THE SOURCE CODE 114
\cs_new_protected:Npn \__tblr_calc_cell_and_line_sizes:
{
\__tblr_prepare_stretch:
\__tblr_calculate_line_sizes:
\__tblr_calculate_cell_sizes:
\LogTblrTracing { cell, row, column, hline, vline }
\__tblr_compute_extendable_column_width:
\__tblr_adjust_sizes_for_span_cells:
}
- \box_ht:N \l_tmpa_box
+ \l__tblr_strut_ht_dim
}
\box_set_ht:Nn \l_tmpa_box { \l__tblr_strut_ht_dim }
%% return vbox for vertical-align: \c__tblr_middle_m_tl
\vbox_set_top:Nn \l_tmpa_box { \box_use:N \l_tmpa_box }
\vbox_set:Nn \l_tmpb_box { \box_use:N \l_tmpb_box }
}
}
\cs_new_eq:NN \__tblr_process_stretch: \__tblr_process_stretch_real:
{
\__tblr_spec_item:nn { vline } { [#2](##1) / @vline-width }
}
\dim_add:Nn \l__tblr_w_dim { \l__tblr_s_tl }
}
\dim_add:Nn \l__tblr_w_dim { - \l__tblr_s_tl }
}
\__tblr_spec_gput_if_larger:nee { vline }
{ [#2]/ @vline-width } { \dim_use:N \l__tblr_w_dim }
}
{
\hbox_set_to_wd:Nnn \l__tblr_b_box {1pt}
{ \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1} }
\tl_set:Nx \l__tblr_h_tl
{
\dim_eval:n
{ \box_ht:N \l__tblr_b_box + \box_dp:N \l__tblr_b_box }
}
\__tblr_spec_gput_if_larger:nee { hline }
{ [#1](##1) / @hline-height } { \l__tblr_h_tl }
\dim_add:Nn \l__tblr_h_dim
{
\__tblr_spec_item:nn { hline } { [#1](##1) / @hline-height }
}
\dim_add:Nn \l__tblr_h_dim { \l__tblr_s_tl }
}
\dim_add:Nn \l__tblr_h_dim { - \l__tblr_s_tl }
}
\__tblr_spec_gput_if_larger:nee { hline }
{ [#1] / @hline-height } { \dim_use:N \l__tblr_h_dim }
}
\tl_const:Nn \c__tblr_valign_h_tl { h }
\tl_const:Nn \c__tblr_valign_m_tl { m }
\tl_const:Nn \c__tblr_valign_f_tl { f }
\tl_const:Nn \c__tblr_valign_t_tl { t }
\tl_const:Nn \c__tblr_valign_b_tl { b }
CHAPTER 8. THE SOURCE CODE 118
\tl_const:Nn \c__tblr_middle_t_tl { t }
\tl_const:Nn \c__tblr_middle_m_tl { m }
\tl_const:Nn \c__tblr_middle_b_tl { b }
\cs_new_protected:Npn \__tblr_update_rowsep_registers:
{
\dim_set:Nn \abovesep
{ \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { abovesep } }
\dim_set:Nn \belowsep
{ \__tblr_data_item:nen { row } { \int_use:N \c@rownum } { belowsep } }
}
\cs_new_protected:Npn \__tblr_update_colsep_registers:
{
\dim_set:Nn \leftsep
{ \__tblr_data_item:nen { column } { \int_use:N \c@colnum } { leftsep } }
\dim_set:Nn \rightsep
{ \__tblr_data_item:nen { column } { \int_use:N \c@colnum } { rightsep } }
}
\tl_new:N \l__tblr_cell_fg_tl
\tl_new:N \l__tblr_cell_cmd_tl
\tl_new:N \l__tblr_cell_mode_tl
\bool_new:N \l__tblr_cell_math_mode_bool
\tl_const:Nn \l__tblr_cell_math_style_tl { \relax }
\tl_const:Nn \l__tblr_cell_imath_style_tl { \textstyle }
\tl_const:Nn \l__tblr_cell_dmath_style_tl { \displaystyle }
\tl_put_left:Nv \l__tblr_c_tl
{ l__tblr_cell_ \l__tblr_cell_mode_tl _style_tl }
\tl_put_left:Nn \l__tblr_c_tl { $ }
\tl_put_right:Nn \l__tblr_c_tl { $ }
}
\tl_set:Nx \l__tblr_f_tl { \__tblr_data_item:neen { cell } {#1} {#2} { font } }
\tl_set:Nx \l__tblr_w_tl
{ \__tblr_data_item:neen { cell } {#1} {#2} { width } }
\dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % cell width unset
{
\int_compare:nNnT
{ \__tblr_data_item:neen { cell } {#1} {#2} { colspan } } < {2}
{
\tl_set:Nx \l__tblr_w_tl
{ \__tblr_data_item:nen { column } {#2} { width } }
}
}
\dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % column width unset
{
\__tblr_save_counters:n { cell }
\bool_if:NTF \l__tblr_cell_math_mode_bool
{
%% Note that font = \boldmath will increase cell width (issue #137)
\hbox_set:Nn \l_tmpa_box { \l__tblr_f_tl \l__tblr_c_tl }
\tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box }
}
{
\__tblr_get_cell_size_with_box:
}
\__tblr_restore_counters:n { cell }
}
\tl_put_left:NV \l__tblr_c_tl \l__tblr_f_tl
\tl_set:Nx \l__tblr_cell_fg_tl
{ \__tblr_data_item:neen { cell } {#1} {#2} { foreground } }
\tl_if_empty:NF \l__tblr_cell_fg_tl
{ \exp_args:NV \color \l__tblr_cell_fg_tl }
\__tblr_get_vcell_and_sizes:NN \l__tblr_c_tl \l__tblr_w_tl
\group_end:
}
\cs_new_protected:Npn \__tblr_get_cell_size_with_box:
{
\tl_if_eq:NnTF \l__tblr_inner_spec_measure_tl { vbox }
{ \__tblr_get_cell_size_with_vbox: }
{ \__tblr_get_cell_size_with_hbox: }
}
\NewDocumentCommand \__tblr_fake_color_command:w { o m } { }
\cs_new_protected:Npn \__tblr_get_cell_size_with_vbox:
{
\hbox_set:Nn \l_tmpa_box
{
\cs_set_eq:NN \color \__tblr_fake_color_command:w
\begin{tblrNoHyper}
\begin{varwidth}{\paperwidth}
\l__tblr_f_tl
\__tblr_rescan_cell_tokens:N \l__tblr_c_tl
\end{varwidth}
\end{tblrNoHyper}
}
\tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box }
}
\cs_new_protected:Npn \__tblr_get_cell_size_with_hbox:
{
\tl_set_eq:NN \l_tmpb_tl \l__tblr_c_tl
\__tblr_insert_braces:N \l_tmpb_tl
\seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpb_tl
\tl_set:Nn \l__tblr_w_tl { 0pt }
\seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl
{
\__tblr_remove_braces:N \l_tmpa_tl
\hbox_set:Nn \l_tmpa_box
{
\l__tblr_f_tl
\__tblr_rescan_cell_tokens:N \l_tmpa_tl
}
\tl_set:Nx \l__tblr_w_tl
{ \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } }
}
}
{ \box_use:N \l_tmpa_box }
\c__tblr_middle_m_tl
{
\tl_set:Nx \l__tblr_b_tl
{
\dim_eval:n
{
( \g__tblr_cell_ht_dim - \g__tblr_cell_head_dim
- \g__tblr_cell_foot_dim ) / 2
}
}
\box_set_ht:Nn \l_tmpb_box
{ \g__tblr_cell_head_dim + \l__tblr_b_tl }
\box_set_dp:Nn \l_tmpb_box
{ \g__tblr_cell_foot_dim + \l__tblr_b_tl }
\box_use:N \l_tmpb_box
}
\c__tblr_middle_b_tl
{ \box_use:N \l_tmpb_box }
}
}
\c__tblr_valign_f_tl
{ \box_use:N \l_tmpb_box }
}
\group_end:
}
%% #1: total height dimension; #2: head dimension; #3: foot dimension;
%% #4: tl for resulting upper size; #5: tl for resulting lower size
\tl_new:N \l__tblr_middle_body_tl
\cs_new_protected:Npn \__tblr_get_middle_cell_upper_lower:NNNNN #1 #2 #3 #4 #5
{
\tl_case:Nn \g__tblr_cell_middle_tl
{
\c__tblr_middle_t_tl
{
\tl_set:Nx #4 { \dim_use:N #2 }
\tl_set:Nx #5 { \dim_eval:n { #1 - #2 } }
}
\c__tblr_middle_m_tl
{
\tl_set:Nx \l__tblr_middle_body_tl { \dim_eval:n { #1 - #2 - #3 } }
\tl_set:Nx #4 { \dim_eval:n { #2 + \l__tblr_middle_body_tl / 2 } }
\tl_set:Nx #5 { \dim_eval:n { #3 + \l__tblr_middle_body_tl / 2 } }
}
\c__tblr_middle_b_tl
{
\tl_set:Nx #4 { \dim_eval:n { #1 - #3 } }
\tl_set:Nx #5 { \dim_use:N #3 }
}
}
}
%% Update size of the row. #1: row number; #2: column number;
%% #3: total height dimension; #4: head dimension; #5: foot dimension
\cs_new_protected:Npn \__tblr_update_row_size:nnNNN #1 #2 #3 #4 #5
{
\group_begin:
%% Note that \l__tblr_h_tl may be empty
\tl_set:Nx \l__tblr_h_tl
{ \__tblr_data_item:nen { row } {#1} { @row-height } }
\tl_if_eq:NNTF \g__tblr_cell_valign_tl \c__tblr_valign_m_tl
{
\tl_set:Nx \l__tblr_a_tl
{ \__tblr_data_item:nen { row } {#1} { @row-upper } }
\tl_set:Nx \l__tblr_b_tl
{ \__tblr_data_item:nen { row } {#1} { @row-lower } }
\__tblr_get_middle_cell_upper_lower:NNNNN
#3 #4 #5 \l__tblr_u_tl \l__tblr_v_tl
\dim_compare:nNnT { \l__tblr_u_tl } > { \l__tblr_a_tl }
{
\tl_set_eq:NN \l__tblr_a_tl \l__tblr_u_tl
\__tblr_data_gput:nenV { row } {#1} { @row-upper } \l__tblr_a_tl
}
\dim_compare:nNnT { \l__tblr_v_tl } > { \l__tblr_b_tl }
{
\tl_set_eq:NN \l__tblr_b_tl \l__tblr_v_tl
\__tblr_data_gput:nenV { row } {#1} { @row-lower } \l__tblr_b_tl
}
\dim_compare:nNnT
{ \l__tblr_a_tl + \l__tblr_b_tl } > { \l__tblr_h_tl + 0pt }
{
\__tblr_data_gput:nene { row } {#1} { @row-height }
{ \dim_eval:n { \l__tblr_a_tl + \l__tblr_b_tl } }
}
}
CHAPTER 8. THE SOURCE CODE 126
{
\tl_set:Nx \l__tblr_e_tl
{ \__tblr_data_item:nen { row } {#1} { @row-head } }
\tl_set:Nx \l__tblr_f_tl
{ \__tblr_data_item:nen { row } {#1} { @row-foot } }
\dim_compare:nNnT {#4} > {\l__tblr_e_tl}
{
\__tblr_data_gput:nene { row } {#1} { @row-head } { \dim_use:N #4 }
}
\dim_compare:nNnT {#5} > {\l__tblr_f_tl}
{
\__tblr_data_gput:nene { row } {#1} { @row-foot } { \dim_use:N #5 }
}
\tl_set:Nx \l__tblr_x_tl { \dim_max:nn {#4} { \l__tblr_e_tl } }
\tl_set:Nx \l__tblr_y_tl { \dim_max:nn {#5} { \l__tblr_f_tl } }
\dim_compare:nNnT
{ #3 - #4 - #5 } > { \l__tblr_h_tl - \l__tblr_x_tl - \l__tblr_y_tl }
{
\__tblr_data_gput:nene { row } {#1} { @row-height }
{
\dim_eval:n
{
\l__tblr_x_tl
+ \dim_use:N #3 - \dim_use:N #4 - \dim_use:N #5
+ \l__tblr_y_tl
}
}
}
}
\group_end:
}
%% Update size of the column. #1: column number; #2: width dimension
\cs_new_protected:Npn \__tblr_update_col_size:nN #1 #2
{
\tl_set:Nx \l_tmpb_tl
{ \__tblr_data_item:nen { column } {#1} { @col-width } }
\bool_lazy_or:nnT
{ \tl_if_empty_p:N \l_tmpb_tl }
{ \dim_compare_p:nNn { \dim_use:N #2 } > { \l_tmpb_tl } }
{
\__tblr_data_gput:nene { column } {#1} { @col-width } { \dim_use:N #2 }
}
}
\dim_new:N \l__column_target_dim
\prop_new:N \l__column_coefficient_prop
\prop_new:N \l__column_natural_width_prop
\prop_new:N \l__column_computed_width_prop
\cs_new_protected:Npn \__tblr_compute_extendable_column_width:
{
\__tblr_collect_extendable_column_width:
\dim_compare:nNnTF { \l__column_target_dim } < { 0pt }
{
\msg_warning:nnx { tabularray } { table-width-too-small }
{ \dim_abs:n { \l__column_target_dim } }
}
{
\prop_if_empty:NF \l__column_coefficient_prop
{ \__tblr_adjust_extendable_column_width: }
}
}
\cs_new_protected:Npn \__tblr_collect_extendable_column_width:
{
\tl_set:Nx \l_tmpa_tl { \__tblr_prop_item:nn { inner } { width } }
\tl_if_empty:NTF \l_tmpa_tl
{ \dim_set_eq:NN \l__column_target_dim \linewidth }
{ \dim_set:Nn \l__column_target_dim { \l_tmpa_tl } }
\prop_clear:N \l__column_coefficient_prop
\prop_clear:N \l__column_natural_width_prop
\prop_clear:N \l__column_computed_width_prop
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
\tl_set:Nx \l__tblr_a_tl
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { width } }
\tl_set:Nx \l__tblr_b_tl
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { coefficient } }
\tl_set:Nx \l__tblr_c_tl
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { @col-width } }
\dim_compare:nNnTF { \l__tblr_a_tl } < { 0pt } % column width unset
{
\dim_compare:nNnTF { \l__tblr_b_tl pt } = { 0pt }
{ \dim_sub:Nn \l__column_target_dim { \l__tblr_c_tl } }
{
\prop_put:Nxx \l__column_coefficient_prop
{ \l__tblr_j_tl } { \l__tblr_b_tl }
\prop_put:Nxn \l__column_computed_width_prop
{ \l__tblr_j_tl } { 0pt }
\dim_compare:nNnF { \l__tblr_b_tl pt } > { 0pt }
{
\prop_put:Nxx \l__column_natural_width_prop
{ \l__tblr_j_tl } { \l__tblr_c_tl }
}
}
}
{ \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
\tl_set:Nx \l__tblr_a_tl
{ \__tblr_spec_item:ne { vline } { [\l__tblr_j_tl] / @vline-width } }
\tl_set:Nx \l__tblr_b_tl
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep } }
\tl_set:Nx \l__tblr_c_tl
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { rightsep } }
\dim_set:Nn \l__column_target_dim
{ \l__column_target_dim - \l__tblr_a_tl - \l__tblr_b_tl - \l__tblr_c_tl }
CHAPTER 8. THE SOURCE CODE 128
}
\tl_set:Nx \l__tblr_a_tl
{
\__tblr_spec_item:ne { vline }
{ [\int_eval:n {\c@colcount + 1}] / @vline-width }
}
\tl_if_empty:NF \l__tblr_a_tl
{ \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
\LogTblrTracing { target }
}
}
{
\tl_set:Nx \l__tblr_b_tl
{ \prop_item:Nn \l__column_natural_width_prop { ##1 } }
\tl_set:Nx \l__tblr_c_tl
{ \prop_item:Nn \l__column_computed_width_prop { ##1 } }
\dim_compare:nNnTF { \l__tblr_a_tl + \l__tblr_c_tl } > { \l__tblr_b_tl }
{
\prop_put:Nnx \l__column_computed_width_prop
{ ##1 } { \l__tblr_b_tl }
\dim_add:Nn \l__column_target_dim
{ \l__tblr_a_tl + \l__tblr_c_tl - \l__tblr_b_tl }
\prop_remove:Nn \l__column_coefficient_prop { ##1 }
}
{
\__tblr_add_dimen_value:Nnn
\l__column_computed_width_prop { ##1 } { \l__tblr_a_tl }
}
}
}
\LogTblrTracing { target }
}
\cs_new_protected:Npn \__tblr_adjust_extendable_column_width_negative:
{
\dim_zero:N \l_tmpa_dim
\prop_map_inline:Nn \l__column_natural_width_prop
{ \dim_add:Nn \l_tmpa_dim { ##2 } }
\tl_set:Nx \l_tmpa_tl
{ \dim_ratio:nn { \l__column_target_dim } { \l_tmpa_dim } }
\dim_zero:N \l__column_target_dim
\prop_map_inline:Nn \l__column_natural_width_prop
{
\tl_set:Nx \l_tmpb_tl { \dim_eval:n { ##2 * \l_tmpa_tl } }
\__tblr_add_dimen_value:Nnn
\l__column_computed_width_prop { ##1 } { \l_tmpb_tl }
}
\LogTblrTracing { target }
}
\cs_new_protected:Npn \__tblr_adjust_sizes_for_span_cells:
{
\__tblr_prop_if_in:nnT { inner } { colspan }
{
\__tblr_collect_column_widths_skips:
\str_if_eq:xnTF
{ \__tblr_prop_item:ne { inner } { hspan } } { minimal }
{
\__tblr_set_span_widths_from_column_widths:
CHAPTER 8. THE SOURCE CODE 130
}
{
\__tblr_collect_span_widths:
\__tblr_set_column_widths_from_span_widths:
}
\LogTblrTracing { column }
\__tblr_calculate_cell_sizes:
}
\__tblr_prop_if_in:nnT { inner } { rowspan }
{
\__tblr_collect_row_heights_skips:
\__tblr_collect_span_heights:
\__tblr_set_row_heights_from_span_heights:
\LogTblrTracing { row }
}
}
\prop_new:N \l__tblr_col_item_skip_size_prop
\prop_new:N \l__tblr_col_span_size_prop
\prop_new:N \l__tblr_row_item_skip_size_prop
\prop_new:N \l__tblr_row_span_size_prop
\cs_new_protected:Npn \__tblr_collect_column_widths_skips:
{
\prop_clear:N \l__tblr_col_item_skip_size_prop
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
\int_compare:nNnTF { \l__tblr_j_tl } > { 1 }
{
\prop_put:Nxx \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] }
{
\dim_eval:n
{
\__tblr_data_item:nen { column }
{ \int_eval:n { \l__tblr_j_tl - 1 } } { rightsep }
+
\__tblr_spec_item:ne { vline }
{ [\l__tblr_j_tl] / @vline-width }
+
\__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep }
}
}
}
{
\prop_put:Nxn \l__tblr_col_item_skip_size_prop { skip[\l__tblr_j_tl] }
{ 0pt }
}
\prop_put:Nxx \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] }
{ \__tblr_data_item:nen { column } { \l__tblr_j_tl } { @col-width } }
}
\__tblr_do_if_tracing:nn { cellspan }
{ \prop_log:N \l__tblr_col_item_skip_size_prop }
}
\cs_new_protected:Npn \__tblr_collect_row_heights_skips:
{
\prop_clear:N \l__tblr_row_item_skip_size_prop
CHAPTER 8. THE SOURCE CODE 131
\cs_new_protected:Npn \__tblr_collect_span_widths:
{
\prop_clear:N \l__tblr_col_span_size_prop
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
{
\tl_set:Nx \l__tblr_a_tl
{
\__tblr_data_item:neen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { colspan }
}
\int_compare:nNnT { \l__tblr_a_tl } > {1}
{
\__tblr_put_if_larger:Nxx \l__tblr_col_span_size_prop
{
( \l__tblr_j_tl -
\int_eval:n {\l__tblr_j_tl + \l__tblr_a_tl - 1} )
}
{
\__tblr_data_item:neen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-width }
CHAPTER 8. THE SOURCE CODE 132
}
}
}
}
\__tblr_do_if_tracing:nn { cellspan }
{ \prop_log:N \l__tblr_col_span_size_prop }
}
\prop_new:N \l__tblr_row_span_to_row_prop
\cs_new_protected:Npn \__tblr_collect_span_heights:
{
\prop_clear:N \l__tblr_row_span_to_row_prop
\prop_clear:N \l__tblr_row_span_size_prop
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
{
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
\tl_set:Nx \l__tblr_a_tl
{
\__tblr_data_item:neen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { rowspan }
}
\int_compare:nNnT { \l__tblr_a_tl } > {1}
{
\tl_set:Nx \l__tblr_v_tl
{
\__tblr_data_item:neen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { valign }
}
\tl_if_eq:NnT \l__tblr_v_tl { h }
{
\tl_set:Nx \l__tblr_h_tl
{
\__tblr_data_item:nen { row }
{ \l__tblr_i_tl } { @row-head }
}
\__tblr_data_gput:neenV { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-height }
\l__tblr_h_tl
}
\tl_if_eq:NnT \l__tblr_v_tl { f }
{
\tl_set:Nx \l__tblr_d_tl
{
\__tblr_data_item:nen
{ row }
{ \int_eval:n { \l__tblr_i_tl + \l__tblr_a_tl - 1 } }
{ @row-foot }
}
\__tblr_data_gput:neenV { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-depth }
\l__tblr_d_tl
}
\__tblr_put_if_larger:Nxx \l__tblr_row_span_size_prop
{
( \l__tblr_i_tl -
\int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} )
CHAPTER 8. THE SOURCE CODE 133
}
{
\dim_eval:n
{
\__tblr_data_item:neen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-height }
+
\__tblr_data_item:neen { cell }
{ \l__tblr_i_tl } { \l__tblr_j_tl } { @cell-depth }
}
}
\prop_put:Nxx \l__tblr_row_span_to_row_prop
{ [\l__tblr_i_tl][\l__tblr_j_tl] }
{ \int_eval:n {\l__tblr_i_tl + \l__tblr_a_tl - 1} }
}
}
}
\__tblr_do_if_tracing:nn { cellspan }
{
\prop_log:N \l__tblr_row_span_to_row_prop
\prop_log:N \l__tblr_row_span_size_prop
}
}
\__tblr_distribute_span_sizes_default:xNN
{ \int_use:N \c@rowcount }
\l__tblr_row_item_skip_size_prop
\l__tblr_row_span_size_prop
}
\__tblr_set_all_row_heights:
}
}
}
\__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 }
}
\cs_generate_variant:Nn \__tblr_distribute_span_sizes_default:nNN { x }
\cs_new_protected:Npn \__tblr_set_all_column_widths:
{
\int_step_variable:nNn { \c@colcount } \l__tblr_j_tl
{
\__tblr_data_gput:nene { column }
CHAPTER 8. THE SOURCE CODE 136
{ \l__tblr_j_tl } { width }
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] } }
}
}
\cs_new_protected:Npn \__tblr_set_all_row_heights:
{
\int_step_variable:nNn { \c@rowcount } \l__tblr_i_tl
{
\tl_set:Nx \l__tblr_h_tl
{
\__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-head }
}
\tl_set:Nx \l__tblr_d_tl
{
\__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-foot }
}
\tl_set:Nx \l__tblr_a_tl
{
\prop_item:Ne \l__tblr_row_item_skip_size_prop { item[\l__tblr_i_tl] }
}
\__tblr_collect_one_row_height:NN \l__tblr_i_tl \l__tblr_t_tl
\__tblr_data_gput:nene { row }
{ \l__tblr_i_tl } { @row-height } { \l__tblr_a_tl }
}
}
\int_step_inline:nnn { #1 + 1 } { #2 }
{
\tl_set:Nx \l_tmpa_tl
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] } }
\tl_set:Nx \l_tmpb_tl
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } }
\dim_add:Nn #3 { \dim_eval:n { \l_tmpa_tl + \l_tmpb_tl } }
}
}
\cs_generate_variant:Nn \__tblr_calc_span_widths:nnN { xxN }
\cs_new_protected:Npn \__tblr_style_put:nn #1 #2
{
\prop_put:Nnn \l__tblr_element_styles_prop {#1} {#2}
}
\cs_generate_variant:Nn \__tblr_style_put:nn { nV, ne, en, eV }
\cs_new:Npn \__tblr_style_item:n #1
{
\prop_item:Nn \l__tblr_element_styles_prop {#1}
}
\cs_new_protected:Npn \__tblr_style_log:
{
\prop_log:N \l__tblr_element_styles_prop
}
\tl_new:N \l__tblr_element_name_tl
\tl_new:N \l__tblr_element_styles_tl
\keys_define:nn { tblr-element }
{
head .meta:n = { firsthead, middlehead, lasthead },
foot .meta:n = { firstfoot, middlefoot, lastfoot },
unknown .code:n = \__tblr_set_element_styles:V \l_keys_key_str,
}
\cs_new_protected:Npn \__tblr_set_element_styles:n #1
{
\tl_set:Nn \l__tblr_element_name_tl {#1}
\keys_set:nV { tblr-style } \l__tblr_element_styles_tl
}
\cs_generate_variant:Nn \__tblr_set_element_styles:n { V }
CHAPTER 8. THE SOURCE CODE 138
\keys_define:nn { tblr-style }
{
halign .code:n = \__tblr_element_gput_style:nn { halign } {#1},
l .meta:n = { halign = l },
c .meta:n = { halign = c },
r .meta:n = { halign = r },
j .meta:n = { halign = j },
fg .code:n = \__tblr_element_gput_style:nn { fg } {#1},
font .code:n = \__tblr_element_gput_style:nn { font } {#1},
hang .code:n = \__tblr_element_gput_style:nn { hang } {#1},
indent .code:n = \__tblr_element_gput_style:nn { indent } {#1},
unknown .code:n = \__tblr_element_unknown_key:Vn \l_keys_key_str {#1},
}
\cs_new_protected:Npn \__tblr_element_gput_style:nn #1 #2
{
\__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2}
}
\cs_new_protected:Npn \__tblr_element_unknown_key:nn #1 #2
{
\regex_match:NnTF \c__tblr_is_color_key_regex {#1}
{ \__tblr_style_put:en { \l__tblr_element_name_tl / fg } {#1} }
{
%% unknown key name has been changed to string in \l_keys_key_str
\tl_set_rescan:Nnn \l__tblr_f_tl {} {#1}
\tl_if_head_eq_catcode:VNTF \l__tblr_f_tl \scan_stop:
{
\__tblr_style_put:eV { \l__tblr_element_name_tl / font } \l__tblr_f_tl
}
{
\__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2}
}
}
}
\cs_generate_variant:Nn \__tblr_element_unknown_key:nn { Vn }
\keys_define:nn { tblr-def-template }
{
unknown .code:n = \__tblr_def_template:V \l_keys_key_str,
}
}
\cs_new_eq:NN \DeclareTblrTemplate \DefTblrTemplate
\cs_new_protected:Npn \__tblr_def_template:n #1
{
\tl_set_eq:cN { l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl }
\l__tblr_template_code_tl
}
\cs_generate_variant:Nn \__tblr_def_template:n { V }
\keys_define:nn { tblr-set-template }
{
unknown .code:n = \__tblr_set_template:V \l_keys_key_str,
}
\cs_new_protected:Npn \__tblr_set_template:n #1
{
\tl_set_eq:cc { l__tblr_template_ #1 _default_tl }
{ l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl }
}
\cs_generate_variant:Nn \__tblr_set_template:n { V }
\NewExpandableDocumentCommand \GetTblrStyle { m m }
{
\__tblr_style_item:n { #1 / #2 }
}
\NewDocumentCommand \UseTblrFont { m }
{
\GetTblrStyle {#1} { font } \selectfont
}
\tl_new:N \l__tblr_use_color_tl
\NewDocumentCommand \UseTblrColor { m }
{
\tl_set:Nx \l__tblr_use_color_tl { \GetTblrStyle {#1} { fg } }
\tl_if_empty:NF \l__tblr_use_color_tl { \color { \l__tblr_use_color_tl } }
}
\tl_new:N \l__tblr_use_hang_tl
CHAPTER 8. THE SOURCE CODE 140
\NewDocumentCommand \UseTblrHang { m }
{
\tl_set:Nx \l__tblr_use_hang_tl { \GetTblrStyle {#1} { hang } }
\tl_if_empty:NF \l__tblr_use_hang_tl
{
\tl_put_left:Nn \l__tblr_use_hang_tl
{ \hangafter = 1 \relax \hangindent = }
\tl_put_right:Nn \l__tblr_use_hang_tl { \relax }
\exp_args:NV \everypar \l__tblr_use_hang_tl
}
}
\tl_new:N \l__tblr_use_indent_tl
\NewDocumentCommand \UseTblrIndent { m }
{
\tl_set:Nx \l__tblr_use_indent_tl { \GetTblrStyle {#1} { indent } }
\tl_if_empty:NF \l__tblr_use_indent_tl
{ \exp_args:NNV \setlength \parindent \l__tblr_use_indent_tl }
}
\AtBeginDocument
{
\@ifpackageloaded{xcolor}{}{\RenewDocumentCommand \UseTblrColor {m} {}}
}
\NewDocumentCommand \MapTblrNotes { +m }
{
\__tblr_prop_map_inline:nn { note }
{
\tl_set_rescan:Nnn \InsertTblrNoteTag {} {##1}
\tl_set:Nn \InsertTblrNoteText {##2}
#1
}
}
\NewDocumentCommand \MapTblrRemarks { +m }
{
\__tblr_prop_map_inline:nn { remark }
{
CHAPTER 8. THE SOURCE CODE 141
\NewExpandableDocumentCommand \InsertTblrText { m }
{
\__tblr_spec_item:nn { outer } {#1}
}
\NewExpandableDocumentCommand \InsertTblrMore { m }
{
\__tblr_prop_item:nn { more } {#1}
}
\tl_if_exist:NF \tblrcontheadname
{
\tl_set:Nn \tblrcontheadname { ( Continued ) }
}
\box_new:N \l__tblr_caption_box
CHAPTER 8. THE SOURCE CODE 143
\box_new:N \l__tblr_caption_left_box
\leavevmode
\UseTblrTemplate { caption-tag } { default }
\UseTblrTemplate { caption-sep } { default }
\UseTblrTemplate { caption-text } { default }
\par
}
\SetTblrTemplate { caption } { normal }
\centering
\makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
\par
}
}
\DefTblrTemplate { capcont } { simple }
{
\UseTblrAlign { caption }
\UseTblrIndent { caption }
\UseTblrHang { caption }
\leavevmode
\UseTblrTemplate { caption-tag } { default }
\UseTblrTemplate { caption-sep } { default }
\UseTblrTemplate { caption-text } { default }
\UseTblrTemplate { conthead-pre } { default }
\UseTblrTemplate { conthead-text } { default }
\par
}
\SetTblrTemplate { capcont} { normal }
\cs_new_protected:Npn \__tblr_hyper_link:nn #1 #2
{
\cs_if_exist:NTF \hyperlink
{
\hyperlink
{ tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} }
{ #2 }
}
{ #2 }
}
{
\hypersetup { pdfborder = { 0 ~ 0 ~ 1 } }
}
\SetTblrTemplate { note-border } { empty }
\NewDocumentCommand \TblrNote { m }
{
\cs_if_exist:NT \hypersetup { \ExpTblrTemplate { note-border }{ default } }
\TblrOverlap
{
\__tblr_hyper_link:nn {#1}
{ \textsuperscript { \sffamily \UseTblrFont { note-tag } #1 } }
}
}
{
\hangindent = 0.7em
\hangafter = 1
\UseTblrHang { note }
\leavevmode
\hbox_to_wd:nn { \the\hangindent }
{
\UseTblrTemplate { note-tag } { default }
\UseTblrTemplate { note-target } { default }
\hfil
}
\UseTblrTemplate { note-text } { default }
\par
}
}
\DefTblrTemplate { note } { inline }
{
\UseTblrAlign { note }
\UseTblrIndent { note }
\UseTblrHang { note }
\leavevmode
\MapTblrNotes
{
\UseTblrTemplate { note-tag } { default }
\UseTblrTemplate { note-target } { default }
\UseTblrTemplate { note-sep } { default }
\UseTblrTemplate { note-text } { default }
\quad
}
\par
}
\SetTblrTemplate { note } { normal }
\keys_define:nn { tblr-def-template }
{
head .meta:n = { firsthead, middlehead, lasthead },
foot .meta:n = { firstfoot, middlefoot, lastfoot },
}
\keys_define:nn { tblr-set-template }
{
CHAPTER 8. THE SOURCE CODE 149
\cs_new_protected:Npn \__tblr_build_head_foot:
{
\__tblr_build_row_head_foot:
\__tblr_build_table_head_foot:
}
\tl_new:N \l__tblr_row_head_tl
\tl_new:N \l__tblr_row_foot_tl
\box_new:N \l__tblr_row_head_box
\box_new:N \l__tblr_row_foot_box
\dim_new:N \l__tblr_row_head_foot_dim
\cs_new_protected:Npn \__tblr_build_row_head_foot:
{
%% \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 } }
CHAPTER 8. THE SOURCE CODE 150
\dim_new:N \tablewidth
\cs_new_protected:Npn \__tblr_get_table_width:
{
\dim_zero:N \tablewidth
\int_step_inline:nn { \c@colcount }
{
\dim_add:Nn \tablewidth
{
\__tblr_spec_item:nn { vline } { [##1] / @vline-width }
+
\__tblr_data_item:nnn { column } {##1} { leftsep }
+
\__tblr_data_item:nnn { column } {##1} { @col-width }
+
\__tblr_data_item:nnn { column } {##1} { rightsep }
}
}
\dim_add:Nn \tablewidth
{
\__tblr_spec_item:ne { vline }
{ [\int_eval:n { \c@colcount + 1 }] / @vline-width }
}
}
\box_new:N \l__tblr_table_firsthead_box
\box_new:N \l__tblr_table_middlehead_box
\box_new:N \l__tblr_table_lasthead_box
\box_new:N \l__tblr_table_firstfoot_box
\box_new:N \l__tblr_table_middlefoot_box
\box_new:N \l__tblr_table_lastfoot_box
\cs_new_protected:Npn \__tblr_build_table_head_foot:
{
CHAPTER 8. THE SOURCE CODE 151
\__tblr_get_table_width:
% make each of \lTblrCaptionTl, \lTblrEntryTl, \lTblrLabelTl and the
% three corresponding booleans available in all head-foot templates
\__tblr_set_table_label_entry:
\__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box
{
\__tblr_build_table_label_entry:
\UseTblrTemplate { firsthead } { default }
}
\__tblr_build_table_head_aux:Nn \l__tblr_table_middlehead_box
{
\UseTblrTemplate { middlehead } { default }
}
\__tblr_build_table_head_aux:Nn \l__tblr_table_lasthead_box
{
\UseTblrTemplate { lasthead } { default }
}
\__tblr_build_table_foot_aux:Nn \l__tblr_table_firstfoot_box
{
\UseTblrTemplate { firstfoot } { default }
}
\__tblr_build_table_foot_aux:Nn \l__tblr_table_middlefoot_box
{
\UseTblrTemplate { middlefoot } { default }
}
\__tblr_build_table_foot_aux:Nn \l__tblr_table_lastfoot_box
{
\UseTblrTemplate { lastfoot } { default }
}
}
\bool_new:N \l__tblr_table_no_title_bool
\bool_new:N \l__tblr_table_no_entry_bool
\bool_new:N \l__tblr_table_no_label_bool
\tl_const:Nn \c_tblr_none_tl { none }
\cs_new_protected:Npn \__tblr_set_table_label_entry:
{
\tl_set:Nx \lTblrCaptionTl { \InsertTblrText { caption } }
\tl_set:Nx \lTblrEntryTl { \InsertTblrText { entry } }
\tl_set:Nx \lTblrLabelTl { \InsertTblrText { label } }
\bool_set:Nn \l__tblr_table_no_title_bool
{ \tl_if_empty_p:N \lTblrCaptionTl }
\bool_set:Nn \l__tblr_table_no_entry_bool
{ \tl_if_eq_p:NN \lTblrEntryTl \c_tblr_none_tl }
\bool_set:Nn \l__tblr_table_no_label_bool
{ \tl_if_eq_p:NN \lTblrLabelTl \c_tblr_none_tl }
\bool_if:NT \l__tblr_table_no_title_bool
{
\SetTblrTemplate { conthead-pre } { empty }
}
\bool_if:NT \l__tblr_table_no_label_bool
{
\SetTblrTemplate { caption-tag }{ empty }
\SetTblrTemplate { caption-sep }{ empty }
}
}
CHAPTER 8. THE SOURCE CODE 152
\cs_new_protected:Npn \__tblr_build_tall_table_head_foot:
{
\__tblr_get_table_width:
\__tblr_set_table_label_entry:
\__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box
{
\__tblr_build_table_label_entry:
\UseTblrTemplate { firsthead } { default }
}
\__tblr_build_table_foot_aux:Nn
\l__tblr_table_lastfoot_box { \UseTblrTemplate { lastfoot } { default } }
}
\tl_new:N \lTblrCaptionTl
\tl_new:N \lTblrEntryTl
\tl_new:N \lTblrLabelTl
\clist_new:N \lTblrRefMoreClist
\cs_new_protected:Npn \__tblr_build_table_label_entry:
{
\bool_if:NF \l__tblr_table_no_label_bool
{
\refstepcounter { table }
\tl_if_empty:NF \lTblrLabelTl
{
\clist_map_inline:Nn \lTblrRefMoreClist
{ \ExpTblrTemplate { caption-ref } { ##1 } }
\exp_args:NV \label \lTblrLabelTl
}
}
%% We put caption-lot code at last, so that a user can modify \lTblrEntryTl
%% in a caption-label template. For example, a user may want to use
%% short caption in nameref, but at the same time not to add LoT entry.
\bool_if:NF \l__tblr_table_no_entry_bool
{ \UseTblrTemplate { caption-lot } { default } }
}
\cs_new_protected:Npn \__tblr_build_table_head_aux:Nn #1 #2
{
\vbox_set:Nn #1
{
\hsize = \tablewidth
\TblrParboxRestore % it will set \linewidth = \hsize
\vbox_set:Nn \l_tmpa_box {#2}
\box_use:N \l_tmpa_box
\dim_compare:nNnT
{ \box_ht:N \l_tmpa_box + \box_dp:N \l_tmpa_box } > { 0pt }
{ \skip_vertical:n { \__tblr_spec_item:nn { outer } { headsep } } }
}
}
\cs_new_protected:Npn \__tblr_build_table_foot_aux:Nn #1 #2
{
\vbox_set:Nn #1
{
\hsize = \tablewidth
\TblrParboxRestore % it will set \linewidth = \hsize
CHAPTER 8. THE SOURCE CODE 153
\cs_new_protected:Npn \__tblr_build_whole:
{
\__tblr_hook_use:n { tabularray/table/before }
\tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { long } } { true }
{ \__tblr_build_long_table:e { \__tblr_spec_item:nn { outer } { halign } } }
{
\tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { tall } } { true }
{
\__tblr_build_tall_table:e
{ \__tblr_spec_item:nn { outer } { baseline } }
}
{
\__tblr_build_short_table:e
{ \__tblr_spec_item:nn { outer } { baseline } }
}
}
\__tblr_hook_use:n { tabularray/table/after }
}
\dim_new:N \l__tblr_remain_height_dim
\int_new:N \l__tblr_long_from_int
\int_new:N \l__tblr_long_to_int
\int_new:N \l__tblr_curr_i_int
\int_new:N \l__tblr_prev_i_int
\int_new:N \l__tblr_table_page_int
\bool_new:N \l__tblr_page_break_curr_bool
\bool_new:N \l__tblr_page_break_prev_bool
\dim_set:Nn \l__tblr_remain_height_dim
{ \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim }
\int_set:Nn \l__tblr_long_from_int { \l__tblr_row_head_tl + 1 }
\int_set:Nn \l__tblr_long_to_int { \c@rowcount - ( \l__tblr_row_foot_tl + 0 ) }
\int_set:Nn \l__tblr_curr_i_int { \l__tblr_long_from_int - 1 }
\int_do_while:nNnn { \l__tblr_curr_i_int } < { \l__tblr_long_to_int }
{
\int_set_eq:NN \l__tblr_prev_i_int \l__tblr_curr_i_int
\__tblr_get_next_table_rows:NNNN
\l__tblr_long_to_int \l__tblr_curr_i_int
\l_tmpa_dim \l__tblr_page_break_curr_bool
\__tblr_check_table_page_break:NNN
\l__tblr_remain_height_dim \l_tmpa_dim \l__tblr_page_break_prev_bool
\__tblr_do_if_tracing:nn { page } { \int_log:N \l__tblr_curr_i_int }
\bool_if:NTF \l__tblr_page_break_prev_bool
{
\int_compare:nNnTF
{ \l__tblr_long_from_int } > { \l__tblr_prev_i_int }
{
% See issue #42: if longtblr starts at the bottom of a page,
% \pagetotal maybe exceed \pagegoal after adding presep,
% or after adding rowhead or rowfoot of the table.
% In these cases, we will not typeset table in this page,
% but rather force a page break.
\group_begin:
\dim_set:Nn \l_tmpb_dim
{
% Enough to overfill the page (including shrink).
\pagegoal - \pagetotal + \l_tmpa_dim
+ \__tblr_box_height:N \l__tblr_table_firsthead_box
+ \__tblr_box_height:N \l__tblr_table_firstfoot_box
}
\skip_vertical:n { \l_tmpb_dim }
\tex_penalty:D 9999
\skip_vertical:n { -\l_tmpb_dim }
\group_end:
}
{
\__tblr_build_page_table:nnx {#1}
{ \int_use:N \l__tblr_long_from_int }
{ \int_use:N \l__tblr_prev_i_int }
\int_incr:N \l__tblr_table_page_int
\int_set:Nn \l__tblr_long_from_int { \l__tblr_prev_i_int + 1 }
\TblrNewPage
}
\hbox{}\kern-\topskip\nobreak
\noindent
\LogTblrTracing { page }
\dim_set:Nn \l__tblr_remain_height_dim
{ \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim - \l_tmpa_dim }
}
{
\bool_if:NTF \l__tblr_page_break_curr_bool
{
\__tblr_build_page_table:nnx {#1}
{ \int_use:N \l__tblr_long_from_int }
{ \int_use:N \l__tblr_curr_i_int }
\int_incr:N \l__tblr_table_page_int
CHAPTER 8. THE SOURCE CODE 155
\TblrNewPage
\hbox{}\kern-\topskip\nobreak
\noindent
\LogTblrTracing { page }
\dim_set:Nn \l__tblr_remain_height_dim
{ \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim }
\int_set:Nn \l__tblr_long_from_int { \l__tblr_curr_i_int + 1 }
}
{ \dim_add:Nn \l__tblr_remain_height_dim { -\l_tmpa_dim } }
}
}
\int_compare:nNnTF { \l__tblr_table_page_int } = {1}
{
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box
}
{
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_lasthead_box
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box
}
\__tblr_build_page_table:nnn {#1}
{ \int_use:N \l__tblr_long_from_int } { \int_use:N \l__tblr_long_to_int }
\skip_vertical:n { \__tblr_spec_item:nn { outer } { postsep } }
% In the past we used "\hrule height ~ 0pt" to get strict postsep,
% but the postsep was not discarded when page breaks, see issue #39.
% Therefore we use \nointerlineskip here.
\nointerlineskip
}
\cs_generate_variant:Nn \__tblr_build_long_table:n { e }
%% #1: int with index of the last row; #2: int with index of current row;
%% #3: row dimension; #4: break page or not.
\cs_new_protected:Npn \__tblr_get_next_table_rows:NNNN #1 #2 #3 #4
{
\bool_set_true:N \l_tmpa_bool
\dim_zero:N #3
\bool_set_false:N #4
\bool_while_do:Nn \l_tmpa_bool
{
\int_incr:N #2
\dim_add:Nn #3
{
\__tblr_data_item:nen { row } { \int_use:N #2 } { abovesep }
+
\__tblr_data_item:nen { row } { \int_use:N #2 } { @row-height }
+
\__tblr_data_item:nen { row } { \int_use:N #2 } { belowsep }
+
\__tblr_spec_item:ne { hline }
{ [ \int_eval:n { #2 + 1 } ] / @hline-height }
}
\int_compare:nNnTF {#2} < {#1}
{
\tl_set:Nx \l__tblr_b_tl
{
\__tblr_spec_item:ne { hline }
{ [ \int_eval:n { #2 + 1 } ] / @pagebreak }
}
CHAPTER 8. THE SOURCE CODE 156
\box_new:N \l__tblr_table_head_box
\box_new:N \l__tblr_table_foot_box
\dim_new:N \l__tblr_table_head_foot_dim
\dim_new:N \l__tblr_table_head_body_foot_dim
%% #1: remain dimension; #2: row dimension; #3: break page or not
\cs_new_protected:Npn \__tblr_check_table_page_break:NNN #1 #2 #3
{
\int_compare:nNnTF { \l__tblr_table_page_int } = {1}
{
\dim_set:Nn \l__tblr_table_head_body_foot_dim
{
\__tblr_box_height:N \l__tblr_table_firsthead_box
+ #2 + \__tblr_box_height:N \l__tblr_table_firstfoot_box
}
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box
\dim_compare:nNnTF
{ \l__tblr_table_head_body_foot_dim } > {#1}
{
\bool_set_true:N #3
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_firstfoot_box
}
{ \bool_set_false:N #3 }
}
{
\dim_set:Nn \l__tblr_table_head_body_foot_dim
{
\__tblr_box_height:N \l__tblr_table_middlehead_box
+ #2 + \__tblr_box_height:N \l__tblr_table_middlefoot_box
}
\box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_middlehead_box
\dim_compare:nNnTF
{ \l__tblr_table_head_body_foot_dim } > {#1}
{
\bool_set_true:N #3
\box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_middlefoot_box
}
{ \bool_set_false:N #3 }
}
}
\box_new:N \l__tblr_table_box
\cs_new_protected:Npn \__tblr_build_page_table:nnn #1 #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
\__tblr_cover_two_vboxes:NN \l__tblr_row_head_box \l__tblr_table_box
\box_use:N \l__tblr_row_foot_box
\hrule height ~ 0pt
\box_use:N \l__tblr_table_foot_box
}
\__tblr_halign_whole:Nn \l__tblr_table_box {#1}
}
\cs_generate_variant:Nn \__tblr_build_page_table:nnn { nnx }
%% To solve the problem of missing hlines of long tables in some PDF readers,
%% We need to draw body rows before head rows (see issue #88).
\cs_new_protected:Npn \__tblr_cover_two_vboxes:NN #1 #2
{
\dim_set:Nn \l_tmpa_dim { \box_ht:N #1 + \box_dp:N #1 }
\dim_set:Nn \l_tmpb_dim { \box_ht:N #2 + \box_dp:N #2 }
\skip_vertical:N \l_tmpa_dim
\hrule height ~ 0pt
\box_use:N #2
\skip_vertical:n { - \l_tmpa_dim - \l_tmpb_dim }
\hrule height ~ 0pt
\box_use:N #1
\skip_vertical:N \l_tmpb_dim
\hrule height ~ 0pt
}
\cs_new_protected:Npn \__tblr_halign_whole:Nn #1 #2
{
\noindent
\hbox_to_wd:nn { \linewidth }
{
\tl_if_eq:nnF {#2} {l} { \hfil }
\box_use:N #1
\tl_if_eq:nnF {#2} {r} { \hfil }
}
}
\box_use:N \l__tblr_table_lastfoot_box
}
\__tblr_valign_whole:Nn \l__tblr_table_box {#1}
}
\cs_generate_variant:Nn \__tblr_build_tall_table:n { e }
\box_new:N \l__tblr_table_hlines_box
\box_new:N \l__tblr_hline_box
\box_new:N \l__tblr_row_box
\cs_new_protected:Npn \__tblr_put_one_hline:n #1
{
\hbox_set:Nn \l__tblr_hline_box {#1}
\skip_vertical:n { \box_ht:N \l__tblr_hline_box + \box_dp:N \l__tblr_hline_box }
CHAPTER 8. THE SOURCE CODE 159
\vbox_set:Nn \l__tblr_table_hlines_box
{
\vbox_unpack:N \l__tblr_table_hlines_box
\box_use:N \l__tblr_hline_box
}
}
\cs_new_protected:Npn \__tblr_put_one_row:n #1
{
\hbox_set:Nn \l__tblr_row_box {#1}
\vbox_set:Nn \l__tblr_table_hlines_box
{
\vbox_unpack:N \l__tblr_table_hlines_box
\skip_vertical:n
{ \box_ht:N \l__tblr_row_box + \box_dp:N \l__tblr_row_box }
}
\box_use:N \l__tblr_row_box
}
\tl_new:N \__tblr_vbox_align_tl
\tl_const:Nn \__tblr_vbox_t_tl {t}
\tl_const:Nn \__tblr_vbox_T_tl {T}
\tl_const:Nn \__tblr_vbox_m_tl {m}
\tl_const:Nn \__tblr_vbox_M_tl {M}
\tl_const:Nn \__tblr_vbox_c_tl {c}
\tl_const:Nn \__tblr_vbox_b_tl {b}
\tl_const:Nn \__tblr_vbox_B_tl {B}
\tl_new:N \l__tblr_delim_left_tl
\tl_new:N \l__tblr_delim_right_tl
\cs_new_protected:Npn \__tblr_valign_whole:Nn #1 #2
{
\group_begin:
\tl_set:Nx \l__tblr_delim_left_tl
{ \__tblr_prop_item:nn { inner } { delim-left } }
\tl_set:Nx \l__tblr_delim_right_tl
{ \__tblr_prop_item:nn { inner } { delim-right } }
\tl_set:Nn \__tblr_vbox_align_tl {#2}
\dim_set:Nn \l__tblr_t_dim { \box_ht:N #1 + \box_dp:N #1 }
\tl_case:NnF \__tblr_vbox_align_tl
{
\__tblr_vbox_m_tl
{ \__tblr_valign_whole_middle:N #1 }
\__tblr_vbox_c_tl
{ \__tblr_valign_whole_middle:N #1 }
\__tblr_vbox_M_tl
CHAPTER 8. THE SOURCE CODE 160
{ \__tblr_valign_whole_middle_row_or_border:N #1 }
\__tblr_vbox_t_tl
{ \__tblr_valign_whole_top:N #1 }
\__tblr_vbox_T_tl
{
\tl_set:Nn \__tblr_vbox_align_tl {1}
\__tblr_valign_whole_at_row_from_above:N #1
}
\__tblr_vbox_b_tl
{ \__tblr_valign_whole_bottom:N #1 }
\__tblr_vbox_B_tl
{
\tl_set:Nx \__tblr_vbox_align_tl { \int_use:N \c@rowcount }
\__tblr_valign_whole_at_row_from_below:N #1
}
}
{
\regex_match:NVTF \c__tblr_is_positive_integer_regex \__tblr_vbox_align_tl
{ \__tblr_valign_whole_at_row:N #1 }
{
\regex_match:NVTF
\c__tblr_is_negative_integer_regex \__tblr_vbox_align_tl
{ \__tblr_valign_whole_at_border:N #1 }
{ \__tblr_valign_whole_middle:N #1 }
}
}
%% we have done the job when valign is m or c
\box_if_empty:NF #1 { \__tblr_add_delimiters_to_box:N #1 }
\group_end:
}
\cs_new_protected:Npn \__tblr_get_vcenter_box:N #1
{
\hbox:n
{
$ \m@th \l__tblr_delim_left_tl
\tex_vcenter:D { \vbox_unpack_drop:N #1 }
\l__tblr_delim_right_tl $
}
}
CHAPTER 8. THE SOURCE CODE 161
\cs_new_protected:Npn \__tblr_valign_whole_middle:N #1
{
\__tblr_get_vcenter_box:N #1
}
\cs_new_protected:Npn \__tblr_valign_whole_top:N #1
{
\dim_set:Nn \l__tblr_h_dim { \__tblr_valign_get_hline_total:n {1} }
\dim_compare:nNnT \l__tblr_h_dim = { 0pt }
{ \dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_row_height:n {1} } }
\box_set_ht:Nn #1 { \l__tblr_h_dim }
\box_set_dp:Nn #1 { \l__tblr_t_dim - \l__tblr_h_dim }
}
\cs_new_protected:Npn \__tblr_valign_whole_bottom:N #1
{
\dim_set:Nn \l__tblr_d_dim
{ \__tblr_valign_get_hline_total:n { \int_eval:n { \c@rowcount + 1 } } }
\dim_compare:nNnTF \l__tblr_d_dim = { 0pt }
{
\dim_set:Nn \l__tblr_d_dim
{ \__tblr_valign_get_row_depth:n { \int_use:N \c@rowcount } }
}
{ \dim_zero:N \l__tblr_d_dim }
\box_set_ht:Nn #1 { \l__tblr_t_dim - \l__tblr_d_dim }
\box_set_dp:Nn #1 { \l__tblr_d_dim }
}
\cs_new_protected:Npn \__tblr_valign_whole_middle_row_or_border:N #1
{
\int_if_odd:nTF { \c@rowcount }
{
\tl_set:Nx \__tblr_vbox_align_tl { \int_eval:n { (\c@rowcount + 1) / 2 } }
\__tblr_valign_whole_at_row_from_above:N #1
}
{
\tl_set:Nx \__tblr_vbox_align_tl { \int_eval:n { \c@rowcount / 2 + 1 } }
\__tblr_valign_whole_at_border_from_above:N #1
}
}
\cs_new_protected:Npn \__tblr_valign_whole_at_row:N #1
{
\int_compare:nNnTF { 2 * \__tblr_vbox_align_tl } > { \c@rowcount }
{ \__tblr_valign_whole_at_row_from_below:N #1 }
{ \__tblr_valign_whole_at_row_from_above:N #1 }
}
\cs_new_protected:Npn \__tblr_valign_whole_at_row_from_above:N #1
{
\dim_set:Nn \l__tblr_h_dim
{ \__tblr_valign_get_hline_total:n { \__tblr_vbox_align_tl } }
\dim_add:Nn \l__tblr_h_dim
{ \__tblr_valign_get_row_height:n { \__tblr_vbox_align_tl } }
\int_step_inline:nn { \__tblr_vbox_align_tl - 1 }
{
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_hline_total:n {##1} }
CHAPTER 8. THE SOURCE CODE 162
\cs_new_protected:Npn \__tblr_valign_whole_at_row_from_below:N #1
{
\dim_set:Nn \l__tblr_d_dim
{ \__tblr_valign_get_hline_total:n { \int_eval:n {\c@rowcount + 1} } }
\dim_add:Nn \l__tblr_d_dim
{ \__tblr_valign_get_row_depth:n { \__tblr_vbox_align_tl } }
\int_step_inline:nnn { \__tblr_vbox_align_tl + 1 } { \c@rowcount }
{
\dim_add:Nn \l__tblr_d_dim { \__tblr_valign_get_hline_total:n {##1} }
\dim_add:Nn \l__tblr_d_dim { \__tblr_valign_get_row_total:n {##1} }
}
\box_set_dp:Nn #1 { \l__tblr_d_dim }
\box_set_ht:Nn #1 { \l__tblr_t_dim - \l__tblr_d_dim }
}
\cs_new_protected:Npn \__tblr_valign_whole_at_border:N #1
{
\tl_set:Nx \__tblr_vbox_align_tl { \int_eval:n { - \__tblr_vbox_align_tl } }
\int_compare:nNnTF { 2 * \__tblr_vbox_align_tl - 2 } > { \c@rowcount }
{ \__tblr_valign_whole_at_border_from_below:N #1 }
{ \__tblr_valign_whole_at_border_from_above:N #1 }
}
\cs_new_protected:Npn \__tblr_valign_whole_at_border_from_above:N #1
{
\dim_set:Nn \l__tblr_h_dim
{ \__tblr_valign_get_hline_total:n { \__tblr_vbox_align_tl } }
\int_step_inline:nn { \__tblr_vbox_align_tl - 1 }
{
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_hline_total:n {##1} }
\dim_add:Nn \l__tblr_h_dim { \__tblr_valign_get_row_total:n {##1} }
}
\box_set_ht:Nn #1 { \l__tblr_h_dim }
\box_set_dp:Nn #1 { \l__tblr_t_dim - \l__tblr_h_dim }
}
\cs_new_protected:Npn \__tblr_valign_whole_at_border_from_below:N #1
{
\dim_zero:N \l__tblr_d_dim
\int_step_inline:nnn { \__tblr_vbox_align_tl } { \c@rowcount }
{
\dim_add:Nn \l__tblr_d_dim { \__tblr_valign_get_row_total:n {##1} }
\dim_add:Nn \l__tblr_d_dim
{ \__tblr_valign_get_hline_total:n { \int_eval:n { ##1 + 1 } } }
}
\box_set_dp:Nn #1 { \l__tblr_d_dim }
\box_set_ht:Nn #1 { \l__tblr_t_dim - \l__tblr_d_dim }
}
\cs_new_nopar:Npn \__tblr_valign_get_hline_total:n #1
{
CHAPTER 8. THE SOURCE CODE 163
\cs_new_nopar:Npn \__tblr_valign_get_row_total:n #1
{
\__tblr_data_item:nnn { row } {#1} { abovesep }
+
\__tblr_data_item:nnn { row } {#1} { @row-height }
+
\__tblr_data_item:nnn { row } {#1} { belowsep }
}
\cs_new_nopar:Npn \__tblr_valign_get_row_height:n #1
{
\__tblr_data_item:nnn { row } {#1} { abovesep }
+
( \__tblr_data_item:nnn { row } {#1} { @row-height }
+
\__tblr_data_item:nnn { row } {#1} { @row-upper }
-
\__tblr_data_item:nnn { row } {#1} { @row-lower }
) / 2
}
\cs_new_nopar:Npn \__tblr_valign_get_row_depth:n #1
{
( \__tblr_data_item:nen { row } {#1} { @row-height }
-
\__tblr_data_item:nen { row } {#1} { @row-upper }
+
\__tblr_data_item:nen { row } {#1} { @row-lower }
) / 2
+
\__tblr_data_item:nnn { row } {#1} { belowsep }
}
%% Read from table specifications and calculate the widths of row and border
%% column outer width = content width + colsep width + border width
%% #1: the column number, #2: outer width, #3: border width
\cs_new_protected:Npn \__tblr_get_col_outer_width_border_width:nNN #1 #2 #3
{
CHAPTER 8. THE SOURCE CODE 165
\dim_set:Nn #3
{ \__tblr_spec_item:ne { vline } { [\int_eval:n {#1 + 1}] / @vline-width } }
\dim_set:Nn #2
{
\__tblr_spec_item:ne { vline } { [#1] / @vline-width }
+
\__tblr_data_item:nen { column } {#1} { leftsep }
+
\__tblr_data_item:nen { column } {#1} { @col-width }
+
\__tblr_data_item:nen { column } {#1} { rightsep }
+
#3
}
}
\dim_new:N \l__tblr_hline_leftskip_dim
\dim_new:N \l__tblr_hline_rightskip_dim
%% Calculate left and right skips from leftpos and rightpos specifications
%% #1: row number; #2: column number; #3: hline index;
\cs_new_protected:Npn \__tblr_get_hline_left_right_skips:nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_hline_leftpos_tl
{ \__tblr_spec_item:ne { hline } { [#1][#2](#3) / leftpos } }
\tl_if_empty:NT \l__tblr_hline_leftpos_tl
{ \tl_set:Nn \l__tblr_hline_leftpos_tl {1} } % default position
\tl_set:Nx \l__tblr_hline_rightpos_tl
{ \__tblr_spec_item:ne { hline } { [#1][#2](#3) / rightpos } }
\tl_if_empty:NT \l__tblr_hline_rightpos_tl
{ \tl_set:Nn \l__tblr_hline_rightpos_tl {1} } % default position
\fp_compare:nNnT { \l__tblr_hline_leftpos_tl } < {1}
{
\dim_set:Nn \l_tmpa_dim
{ \__tblr_spec_item:ne { vline } { [#2] / @vline-width } }
\dim_set:Nn \l_tmpb_dim
{ \__tblr_data_item:nen { column } {#2} { leftsep } }
\fp_compare:nNnTF { \l__tblr_hline_leftpos_tl } < {0}
{
\dim_set:Nn \l__tblr_hline_leftskip_dim
{ \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpb_dim }
}
{
\dim_set:Nn \l__tblr_hline_leftskip_dim
{ \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpa_dim }
}
}
\fp_compare:nNnT { \l__tblr_hline_rightpos_tl } < {1}
{
\dim_set:Nn \l_tmpa_dim
{
\__tblr_spec_item:ne { vline }
{ [\int_eval:n { #2 + 1 }] / @vline-width }
}
\dim_set:Nn \l_tmpb_dim
{ \__tblr_data_item:nen { column } {#2} { rightsep } }
\fp_compare:nNnTF { \l__tblr_hline_rightpos_tl } < {0}
{
CHAPTER 8. THE SOURCE CODE 166
\dim_set:Nn \l__tblr_hline_rightskip_dim
{ \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpb_dim }
}
{
\dim_set:Nn \l__tblr_hline_rightskip_dim
{ \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpa_dim }
}
}
}
\dim_new:N \l__tblr_row_ht_dim
\dim_new:N \l__tblr_row_dp_dim
\dim_new:N \l__tblr_row_abovesep_dim
\dim_new:N \l__tblr_row_belowsep_dim
\box_new:N \l__tblr_row_vlines_box
\box_new:N \l__tblr_vline_box
\box_new:N \l__tblr_cell_box
%% Read from table specifications and calculate inner height/depth of the row
%% inner height = abovesep + above vspace + row upper
%% inner depth = row lower + below vspace + belowsep
%% #1: the row number; #2: resulting inner height; #3: resulting inner depth;
%% #4: restulting abovesep; #5: restulting belowsep.
\dim_new:N \l__row_upper_dim
\dim_new:N \l__row_lower_dim
\dim_new:N \l__row_vpace_dim
CHAPTER 8. THE SOURCE CODE 167
\cs_new_protected:Npn \__tblr_get_row_inner_height_depth:nNNNN #1 #2 #3 #4 #5
{
\dim_set:Nn #4
{ \__tblr_data_item:nen { row } {#1} { abovesep } }
\dim_set:Nn #5
{ \__tblr_data_item:nen { row } {#1} { belowsep } }
\dim_set:Nn \l__row_upper_dim
{ \__tblr_data_item:nen { row } {#1} { @row-upper } }
\dim_set:Nn \l__row_lower_dim
{ \__tblr_data_item:nen { row } {#1} { @row-lower } }
\dim_set:Nn \l__row_vpace_dim
{
( \__tblr_data_item:nen { row } {#1} { @row-height }
- \l__row_upper_dim - \l__row_lower_dim ) / 2
}
\dim_set:Nn #2 { #4 + \l__row_vpace_dim + \l__row_upper_dim }
\dim_set:Nn #3 { \l__row_lower_dim + \l__row_vpace_dim + #5 }
}
\cs_generate_variant:Nn \__tblr_get_row_inner_height_depth:nNNNN { V }
\cs_new_protected:Npn \__tblr_put_one_vline:n #1
{
\hbox_set:Nn \l__tblr_vline_box {#1}
\skip_horizontal:n { \box_wd:N \l__tblr_vline_box }
\hbox_set:Nn \l__tblr_row_vlines_box
{
\hbox_unpack:N \l__tblr_row_vlines_box
\box_use:N \l__tblr_vline_box
}
}
\cs_new_protected:Npn \__tblr_put_one_cell:n #1
{
\hbox_set:Nn \l__tblr_cell_box {#1}
\hbox_set:Nn \l__tblr_row_vlines_box
{
\hbox_unpack:N \l__tblr_row_vlines_box
\skip_horizontal:n { \box_wd:N \l__tblr_cell_box }
}
\box_use:N \l__tblr_cell_box
}
\dim_new:N \l__tblr_vline_aboveskip_dim
\dim_new:N \l__tblr_vline_belowskip_dim
%% Calculate above and below skips from abovepos and belowpos specifications
%% #1: row number; #2: column number; #3: vline index;
\cs_new_protected:Npn \__tblr_get_vline_above_below_skips:nnn #1 #2 #3
{
\tl_set:Nx \l__tblr_vline_abovepos_tl
{ \__tblr_spec_item:ne { vline } { [#1][#2](#3) / abovepos } }
\tl_if_empty:NT \l__tblr_vline_abovepos_tl
{
CHAPTER 8. THE SOURCE CODE 169
\dim_new:N \l__tblr_cell_wd_dim
\dim_new:N \l__tblr_cell_ht_dim
\cs_new_protected:Npn \__tblr_build_cell:NN #1 #2
CHAPTER 8. THE SOURCE CODE 170
{
\int_set:Nn \c@colnum {#2}
\__tblr_update_colsep_registers:
\group_begin:
\tl_set:Nx \l__tblr_w_tl
{ \__tblr_data_item:nen { column } {#2} { @col-width } }
\tl_set:Nx \l__tblr_h_tl
{ \__tblr_data_item:nen { row } {#1} { @row-height } }
\tl_set:Nx \l__tblr_x_tl
{ \__tblr_data_item:nen { column } {#2} { leftsep} }
\tl_set:Nx \l__tblr_y_tl
{ \__tblr_data_item:nen { column } {#2} { rightsep } }
\tl_set:Nx \lTblrCellColSpanTl
{ \__tblr_data_item:neen { cell } {#1} {#2} { colspan } }
\int_compare:nNnTF { \lTblrCellColSpanTl } < {2}
{ \dim_set:Nn \l__tblr_cell_wd_dim { \l__tblr_w_tl } }
{
\__tblr_get_span_horizontal_sizes:NNNNN #1 #2
\l__tblr_o_dim \l__tblr_cell_wd_dim \l__tblr_q_dim
}
\tl_set:Nx \lTblrCellRowSpanTl
{ \__tblr_data_item:neen { cell } {#1} {#2} { rowspan } }
\int_compare:nNnTF { \lTblrCellRowSpanTl } < {2}
{ \dim_set:Nn \l__tblr_cell_ht_dim { \l__tblr_h_tl } }
{
\__tblr_get_span_vertical_sizes:NNNNN #1 #2
\l__tblr_r_dim \l__tblr_cell_ht_dim \l__tblr_t_dim
}
\__tblr_get_cell_alignments:nn {#1} {#2}
\__tblr_build_cell_background:NN #1 #2
\__tblr_build_cell_content:NN #1 #2
\group_end:
}
%% These public variables are updated by html library before building a cell
\tl_new:N \lTblrCellAboveBorderStyleTl
\tl_new:N \lTblrCellAboveBorderWidthTl
\tl_new:N \lTblrCellAboveBorderColorTl
\tl_new:N \lTblrCellBelowBorderStyleTl
\tl_new:N \lTblrCellBelowBorderWidthTl
\tl_new:N \lTblrCellBelowBorderColorTl
\tl_new:N \lTblrCellLeftBorderStyleTl
\tl_new:N \lTblrCellLeftBorderWidthTl
\tl_new:N \lTblrCellLeftBorderColorTl
\tl_new:N \lTblrCellRightBorderStyleTl
\tl_new:N \lTblrCellRightBorderWidthTl
\tl_new:N \lTblrCellRihgtBorderColorTl
\tl_new:N \l__tblr_dash_value_tl
\tl_new:N \l__tblr_dash_value_head_tl
\tl_new:N \l__tblr_dash_value_tail_tl
\tl_new:N \l__tblr_width_value_tl
\tl_new:N \l__tblr_color_value_tl
\cs_new_protected:Npn \__tblr_build_cell_content:NN #1 #2
{
\bool_if:NT \l__tblr_html_variables_bool
{ \__tblr_expose_cell_properties:NN #1 #2 }
\__tblr_hook_use:n { tabularray/cell/before }
\hbox_set_to_wd:Nnn \l__tblr_a_box { \l__tblr_cell_wd_dim }
{
\tl_if_eq:NnTF \g__tblr_cell_halign_tl {j}
% cell width may be less than column width for j cells
{ \__tblr_get_cell_text:nn {#1} {#2} \hfil }
{
\tl_if_eq:NnF \g__tblr_cell_halign_tl {l} { \hfil }
\__tblr_get_cell_text:nn {#1} {#2}
\tl_if_eq:NnF \g__tblr_cell_halign_tl {r} { \hfil }
}
}
\vbox_set_to_ht:Nnn \l__tblr_b_box { \l__tblr_cell_ht_dim }
{
\tl_case:Nn \g__tblr_cell_valign_tl
CHAPTER 8. THE SOURCE CODE 172
{
\c__tblr_valign_m_tl
{
\vfil
\int_compare:nNnT { \lTblrCellRowSpanTl } < {2}
{
\box_set_ht:Nn \l__tblr_a_box
{ \__tblr_data_item:nen { row } {#1} { @row-upper } }
\box_set_dp:Nn \l__tblr_a_box
{ \__tblr_data_item:nen { row } {#1} { @row-lower } }
}
\box_use:N \l__tblr_a_box
\vfil
}
\c__tblr_valign_h_tl
{
\box_set_ht:Nn \l__tblr_a_box
{ \__tblr_data_item:nen { row } {#1} { @row-head } }
\box_use:N \l__tblr_a_box
\vfil
}
\c__tblr_valign_f_tl
{
\vfil
\int_compare:nNnTF { \lTblrCellRowSpanTl } < {2}
{
\box_set_dp:Nn \l__tblr_a_box
{ \__tblr_data_item:nen { row } {#1} { @row-foot } }
}
{
\box_set_dp:Nn \l__tblr_a_box
{
\__tblr_data_item:nen
{ row }
{ \int_eval:n { #1 + \lTblrCellRowSpanTl - 1 } }
{ @row-foot }
}
}
\box_use:N \l__tblr_a_box
}
}
\hrule height ~ 0pt %% zero depth
}
\vbox_set_to_ht:Nnn \l__tblr_c_box
{ \l__tblr_row_ht_dim - \l__tblr_row_abovesep_dim }
{
\box_use:N \l__tblr_b_box
\vss
}
\skip_horizontal:n { \l__tblr_x_tl }
\box_use:N \l__tblr_c_box
\skip_horizontal:n { \l__tblr_y_tl - \l__tblr_cell_wd_dim + \l__tblr_w_tl }
\__tblr_hook_use:n { tabularray/cell/after }
}
\cs_new_protected:Npn \__tblr_build_cell_background:NN #1 #2
{
\bool_set:Nn \lTblrCellOmittedBool
CHAPTER 8. THE SOURCE CODE 173
{
\int_compare_p:nNn
{ \__tblr_data_item:neen { cell } {#1} {#2} { omit } } = {1}
}
\bool_if:NF \lTblrCellOmittedBool
{
\tl_set:Nx \lTblrCellBackgroundTl
{ \__tblr_data_item:neen { cell } {#1} {#2} { background } }
\group_begin:
\tl_if_empty:NF \lTblrCellBackgroundTl
{
\__tblr_get_cell_background_width:NNN #1 #2 \l_tmpa_dim
\__tblr_get_cell_background_depth:NNN #1 #2 \l_tmpb_dim
\__tblr_build_cell_background:nnnn
{ \dim_use:N \l_tmpa_dim }
{ \l__tblr_row_ht_dim }
{ \dim_use:N \l_tmpb_dim }
{ \lTblrCellBackgroundTl }
}
\group_end:
}
}
\skip_horizontal:n { - #1 }
}
%% #1: row number; #2: column number; #3: dimen register for rowsep above.
%% #4: dimen register for total height; #5: dimen register for rowsep below.
%% We can use \l__tblr_row_item_skip_size_prop which was made before
%% But when vspan=even, there are no itemskip in the prop list.
%% Therefore we need to calculate them from the sizes of items and skips
\cs_new_protected:Npn \__tblr_get_span_vertical_sizes:NNNNN #1 #2 #3 #4 #5
{
\dim_set:Nn #3
{ \__tblr_data_item:nen { row } {#1} { abovesep } }
\dim_zero:N #4
\dim_add:Nn #4
{ \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[#1] } }
\int_step_inline:nnn { #1 + 1 } { #1 + \lTblrCellRowSpanTl - 1 }
{
\dim_add:Nn #4
{
\prop_item:Ne \l__tblr_row_item_skip_size_prop { skip[##1] }
+
\prop_item:Ne \l__tblr_row_item_skip_size_prop { item[##1] }
}
}
\dim_set:Nn #5
{
\__tblr_data_item:nen { row }
{ \int_eval:n { #1 + \lTblrCellRowSpanTl - 1 } } { belowsep }
}
%\tl_log:x { cell[#1][#2] ~:~ \dim_use:N #3, \dim_use:N #4, \dim_use:N #5 }
}
%% #1: row number; #2: column number; #3: dimen register for colsep left.
%% #4: dimen register for total width; #5: dimen register for colsep right.
%% We can use \l__tblr_col_item_skip_size_prop which was made before
%% But when hspan=even or hspan=minimal, there are no itemskip in the prop list.
%% Therefore we need to calculate them from the sizes of items and skips
\cs_new_protected:Npn \__tblr_get_span_horizontal_sizes:NNNNN #1 #2 #3 #4 #5
{
\dim_set:Nn #3
{ \__tblr_data_item:nen { column } {#2} { leftsep } }
\dim_zero:N #4
\dim_add:Nn #4
{ \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#2] } }
\int_step_inline:nnn { #2 + 1 } { #2 + \lTblrCellColSpanTl - 1 }
{
\dim_add:Nn #4
{
\prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] }
+
\prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] }
}
}
\dim_set:Nn #5
{
\__tblr_data_item:nen { column }
{ \int_eval:n {#2 + \lTblrCellColSpanTl - 1} } { rightsep }
}
CHAPTER 8. THE SOURCE CODE 175
\bool_new:N \g__tblr_tracing_text_bool
\bool_new:N \g__tblr_tracing_command_bool
\bool_new:N \g__tblr_tracing_option_bool
\bool_new:N \g__tblr_tracing_theme_bool
\bool_new:N \g__tblr_tracing_outer_bool
\bool_new:N \g__tblr_tracing_inner_bool
\bool_new:N \g__tblr_tracing_column_bool
\bool_new:N \g__tblr_tracing_row_bool
\bool_new:N \g__tblr_tracing_cell_bool
\bool_new:N \g__tblr_tracing_vline_bool
\bool_new:N \g__tblr_tracing_hline_bool
\bool_new:N \g__tblr_tracing_colspec_bool
\bool_new:N \g__tblr_tracing_rowspec_bool
\bool_new:N \g__tblr_tracing_target_bool
\bool_new:N \g__tblr_tracing_cellspan_bool
\bool_new:N \g__tblr_tracing_intarray_bool
\bool_new:N \g__tblr_tracing_page_bool
\bool_new:N \g__tblr_tracing_step_bool
\bool_gset_true:N \g__tblr_tracing_step_bool
\keys_define:nn { tblr-set-tracing }
{
+text .code:n = \bool_gset_true:N \g__tblr_tracing_text_bool,
-text .code:n = \bool_gset_false:N \g__tblr_tracing_text_bool,
+command .code:n = \bool_gset_true:N \g__tblr_tracing_command_bool,
-command .code:n = \bool_gset_false:N \g__tblr_tracing_command_bool,
+option .code:n = \bool_gset_true:N \g__tblr_tracing_option_bool,
-option .code:n = \bool_gset_false:N \g__tblr_tracing_option_bool,
+theme .code:n = \bool_gset_true:N \g__tblr_tracing_theme_bool,
-theme .code:n = \bool_gset_false:N \g__tblr_tracing_theme_bool,
+outer .code:n = \bool_gset_true:N \g__tblr_tracing_outer_bool,
-outer .code:n = \bool_gset_false:N \g__tblr_tracing_outer_bool,
+inner .code:n = \bool_gset_true:N \g__tblr_tracing_inner_bool,
-inner .code:n = \bool_gset_false:N \g__tblr_tracing_inner_bool,
+column .code:n = \bool_gset_true:N \g__tblr_tracing_column_bool,
-column .code:n = \bool_gset_false:N \g__tblr_tracing_column_bool,
+row .code:n = \bool_gset_true:N \g__tblr_tracing_row_bool,
-row .code:n = \bool_gset_false:N \g__tblr_tracing_row_bool,
+cell .code:n = \bool_gset_true:N \g__tblr_tracing_cell_bool,
-cell .code:n = \bool_gset_false:N \g__tblr_tracing_cell_bool,
+vline .code:n = \bool_gset_true:N \g__tblr_tracing_vline_bool,
-vline .code:n = \bool_gset_false:N \g__tblr_tracing_vline_bool,
+hline .code:n = \bool_gset_true:N \g__tblr_tracing_hline_bool,
-hline .code:n = \bool_gset_false:N \g__tblr_tracing_hline_bool,
+colspec .code:n = \bool_gset_true:N \g__tblr_tracing_colspec_bool,
CHAPTER 8. THE SOURCE CODE 176
\cs_new_protected_nopar:Npn \__tblr_enable_all_tracings:
{
\bool_gset_true:N \g__tblr_tracing_text_bool
\bool_gset_true:N \g__tblr_tracing_command_bool
\bool_gset_true:N \g__tblr_tracing_option_bool
\bool_gset_true:N \g__tblr_tracing_theme_bool
\bool_gset_true:N \g__tblr_tracing_outer_bool
\bool_gset_true:N \g__tblr_tracing_inner_bool
\bool_gset_true:N \g__tblr_tracing_column_bool
\bool_gset_true:N \g__tblr_tracing_row_bool
\bool_gset_true:N \g__tblr_tracing_cell_bool
\bool_gset_true:N \g__tblr_tracing_vline_bool
\bool_gset_true:N \g__tblr_tracing_hline_bool
\bool_gset_true:N \g__tblr_tracing_colspec_bool
\bool_gset_true:N \g__tblr_tracing_rowspec_bool
\bool_gset_true:N \g__tblr_tracing_target_bool
\bool_gset_true:N \g__tblr_tracing_cellspan_bool
\bool_gset_true:N \g__tblr_tracing_intarray_bool
\bool_gset_true:N \g__tblr_tracing_page_bool
\bool_gset_true:N \g__tblr_tracing_step_bool
}
\cs_new_protected_nopar:Npn \__tblr_disable_all_tracings:
{
\bool_gset_false:N \g__tblr_tracing_text_bool
\bool_gset_false:N \g__tblr_tracing_command_bool
\bool_gset_false:N \g__tblr_tracing_option_bool
\bool_gset_false:N \g__tblr_tracing_theme_bool
\bool_gset_false:N \g__tblr_tracing_outer_bool
\bool_gset_false:N \g__tblr_tracing_inner_bool
\bool_gset_false:N \g__tblr_tracing_column_bool
\bool_gset_false:N \g__tblr_tracing_row_bool
\bool_gset_false:N \g__tblr_tracing_cell_bool
\bool_gset_false:N \g__tblr_tracing_vline_bool
\bool_gset_false:N \g__tblr_tracing_hline_bool
\bool_gset_false:N \g__tblr_tracing_colspec_bool
\bool_gset_false:N \g__tblr_tracing_rowspec_bool
\bool_gset_false:N \g__tblr_tracing_target_bool
\bool_gset_false:N \g__tblr_tracing_cellspan_bool
\bool_gset_false:N \g__tblr_tracing_intarray_bool
\bool_gset_false:N \g__tblr_tracing_page_bool
CHAPTER 8. THE SOURCE CODE 177
\bool_gset_false:N \g__tblr_tracing_step_bool
}
\NewDocumentCommand \LogTblrTracing { m }
{
\keys_set:nn { tblr-log-tracing } {#1}
}
\keys_define:nn { tblr-log-tracing }
{
step .code:n = \__tblr_log_tracing_step:n {#1},
unknown .code:n = \__tblr_log_tracing:N \l_keys_key_str
}
\cs_new_protected:Npn \__tblr_log_tracing:N #1
{
\bool_if:cT { g__tblr_tracing_ #1 _bool }
{ \cs:w __tblr_log_tracing _ #1 : \cs_end: }
}
\cs_new_protected:Npn \__tblr_log_tracing_text:
{
\__tblr_spec_log:n { text }
}
\cs_new_protected:Npn \__tblr_log_tracing_command:
{
\__tblr_prop_log:n { command }
}
\cs_new_protected:Npn \__tblr_log_tracing_option:
{
\__tblr_prop_log:n { note }
\__tblr_prop_log:n { remark }
\__tblr_prop_log:n { more }
}
\cs_new_protected:Npn \__tblr_log_tracing_theme:
{
\__tblr_style_log:
}
\cs_new_protected:Npn \__tblr_log_tracing_outer:
{
\__tblr_spec_log:n { outer }
}
\cs_new_protected:Npn \__tblr_log_tracing_inner:
{
\__tblr_prop_log:n { inner }
}
\cs_new_protected:Npn \__tblr_log_tracing_column:
{
\__tblr_data_log:n { column }
CHAPTER 8. THE SOURCE CODE 178
\cs_new_protected:Npn \__tblr_log_tracing_row:
{
\__tblr_data_log:n { row }
}
\cs_new_protected:Npn \__tblr_log_tracing_cell:
{
\__tblr_data_log:n { cell }
}
\cs_new_protected:Npn \__tblr_log_tracing_vline:
{
\__tblr_spec_log:n { vline }
}
\cs_new_protected:Npn \__tblr_log_tracing_hline:
{
\__tblr_spec_log:n { hline }
}
\cs_new_protected:Npn \__tblr_log_tracing_colspec:
{
\tl_if_eq:NnT \g__tblr_column_or_row_tl { column }
{ \tl_log:N \g__tblr_expanded_colrow_spec_tl }
}
\cs_new_protected:Npn \__tblr_log_tracing_rowspec:
{
\tl_if_eq:NnT \g__tblr_column_or_row_tl { row }
{ \tl_log:N \g__tblr_expanded_colrow_spec_tl }
}
\cs_new_protected:Npn \__tblr_log_tracing_target:
{
\dim_log:N \l__column_target_dim
\prop_log:N \l__column_coefficient_prop
\prop_log:N \l__column_natural_width_prop
\prop_log:N \l__column_computed_width_prop
}
\cs_new_protected:Npn \__tblr_log_tracing_cellspan:
{
\prop_log:N \l__tblr_col_item_skip_size_prop
\prop_log:N \l__tblr_col_span_size_prop
\prop_log:N \l__tblr_row_item_skip_size_prop
\prop_log:N \l__tblr_row_span_size_prop
\prop_log:N \l__tblr_row_span_to_row_prop
}
\cs_new_protected:Npn \__tblr_log_tracing_page:
{
\dim_log:N \pagegoal
\dim_log:N \pagetotal
CHAPTER 8. THE SOURCE CODE 179
\cs_new_protected:Npn \__tblr_log_tracing_step:n #1
{
\bool_if:NT \g__tblr_tracing_step_bool { \tl_log:x {Step :~ #1} }
}
\cs_new_protected:Npn \__tblr_do_if_tracing:nn #1 #2
{
\bool_if:cT { g__tblr_tracing_ #1 _bool } {#2}
}
\NewDocumentCommand \NewTblrLibrary { m m }
{
\cs_new_protected:cpn { __tblr_use_lib_ #1: } {#2}
}
\NewDocumentCommand \UseTblrLibrary { m }
{
\clist_map_inline:nn {#1}
{
\use:c { __tblr_use_lib_ ##1: }
\cs_undefine:c { __tblr_use_lib_ ##1: }
}
}
\NewTblrLibrary { amsmath }
{
\RequirePackage { amsmath }
\NewTblrEnviron { +array }
\SetTblrInner[+array]{colsep = 5pt}
\NewDocumentEnvironment { +matrix } { O{} +b } {
\begin{+array}{
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
cells = {c}, ##1
}
##2
\end{+array}
} { }
\NewDocumentEnvironment { +bmatrix } { O{} +b } {
\begin{+array}{
column{1} = {leftsep = 0pt}, column{Z} = {rightsep = 0pt},
cells = {c}, delimiter = {left = [, right = ]}, ##1
}
##2
\end{+array}
} { }
\NewDocumentEnvironment { +Bmatrix } { O{} +b } {
\begin{+array} {
CHAPTER 8. THE SOURCE CODE 180
\NewTblrLibrary { booktabs }
{
% We only use dimensions \aboverulesep and \belowrulesep in booktabs package
\RequirePackage { booktabs }
\newcommand \tblr@booktabs@hline [1] [] { \hline [##1] }
\newcommand \tblr@booktabs@oldhline [1] [] {
\hline [##1]
\hborder { abovespace = \aboverulesep, belowspace = \belowrulesep }
}
\newcommand \tblr@booktabs@cline [2] [] { \cline [##1] {##2} }
\newcommand \tblr@booktabs@oldcline [2] [] {
\cline [##1] {##2}
\hborder { abovespace = \aboverulesep, belowspace = \belowrulesep }
}
\newcommand \tblr@booktabs@cline@more [2] [] { \SetHline [+] {##2} {##1} }
\newcommand \tblr@booktabs@oldcline@more [2] [] {
CHAPTER 8. THE SOURCE CODE 181
\tl_new:N \__tblr_saved_trial_counters_tl
\tl_new:N \__tblr_saved_cell_counters_tl
\cs_new_protected:Npn \__tblr_save_counters:n #1 { }
\cs_new_protected:Npn \__tblr_restore_counters:n #1 { }
%% We use code from tabularx package for resetting all LaTeX counters,
CHAPTER 8. THE SOURCE CODE 182
\NewTblrLibrary { counter }
{
\cs_set_protected:Npn \__tblr_save_counters:n ##1
{
\def \@elt ####1 { \global\value{####1} = \the\value{####1} \relax }
\tl_set:cx { __tblr_saved_ ##1 _counters_tl } { \cl@@ckpt }
\let \@elt = \relax
}
\cs_set_protected:Npn \__tblr_restore_counters:n ##1
{
\tl_use:c { __tblr_saved_ ##1 _counters_tl }
}
}
\NewTblrLibrary { diagbox }
{
\RequirePackage{ diagbox }
\cs_set_eq:NN \__tblr_lib_saved_diagbox:w \diagbox
\NewContentCommand \diagbox [3] []
{
\__tblr_lib_diagbox_fix:n
{
\__tblr_lib_saved_diagbox:w
[ leftsep=\leftsep, rightsep=\rightsep, ##1 ]
{ \__tblr_lib_diagbox_math_or_text:n {##2} }
{ \__tblr_lib_diagbox_math_or_text:n {##3} }
}
}
\NewContentCommand \diagboxthree [4] []
{
\__tblr_lib_diagbox_fix:n
{
\__tblr_lib_saved_diagbox:w
[ leftsep=\leftsep, rightsep=\rightsep, ##1 ]
{ \__tblr_lib_diagbox_math_or_text:n {##2} }
{ \__tblr_lib_diagbox_math_or_text:n {##3} }
{ \__tblr_lib_diagbox_math_or_text:n {##4} }
}
}
}
\cs_new_protected:Npn \__tblr_lib_diagbox_math_or_text:n #1
{
\bool_if:NTF \l__tblr_cell_math_mode_bool {$#1$} {#1}
}
\box_new:N \l__tblr_diag_box
\cs_new_protected:Npn \__tblr_lib_diagbox_fix:n #1
{
\hbox_set:Nn \l__tblr_diag_box {#1}
CHAPTER 8. THE SOURCE CODE 183
\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_if_empty:NF \l__tblr_evaluate_tl
{
\tl_if_eq:NnTF \l__tblr_evaluate_tl { all }
{
\tlSet \l__tblr_body_tl { \evalWhole {\expValue \l__tblr_body_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 }
CHAPTER 8. THE SOURCE CODE 184
\cs_new_protected:Npn \__tblr_hook_use:n #1 {}
\NewTblrLibrary { hook }
{
\cs_set_eq:NN \__tblr_hook_use:n \hook_use:n
\hook_new_pair:nn { tabularray/trial/before } { tabularray/trial/after }
\hook_new_pair:nn { tabularray/table/before } { tabularray/table/after }
\hook_new_pair:nn { tabularray/row/before } { tabularray/row/after }
\hook_new_pair:nn { tabularray/cell/before } { tabularray/cell/after }
}
\bool_new:N \l__tblr_html_variables_bool
\NewTblrLibrary { html }
{
\bool_set_true:N \l__tblr_html_variables_bool
}
\NewTblrLibrary { nameref }
{
\RequirePackage { nameref }
CHAPTER 8. THE SOURCE CODE 185
\NewTblrLibrary { siunitx }
{
\RequirePackage { siunitx }
\NewColumnType { S } [1] [] { Q[si = {##1}, c] }
\NewColumnType { s } [1] [] { Q[si = {##1}, c, cmd = \TblrUnit] }
\__tblr_data_new_key:nnn { cell } { si } { str }
\keys_define:nn { tblr-column }
{
si .code:n = \__tblr_siunitx_setcolumn:n {##1}
}
\cs_new_protected:Npn \__tblr_siunitx_setcolumn:n ##1
{
\__tblr_column_gput_cell:nn { si } {##1}
\__tblr_column_gput_cell:nn { cmd } { \TblrNum }
}
\NewDocumentCommand \TblrNum { m }
{
\__tblr_siunitx_process:Nn \tablenum {##1}
}
\NewDocumentCommand \TblrUnit { m }
{
\__tblr_siunitx_process:Nn \si {##1}
}
\cs_new_protected:Npn \__tblr_siunitx_process:Nn ##1 ##2
{
\tl_if_head_is_group:nTF {##2}
{ ##2 }
{
\group_begin:
\tl_set:Nx \l_tmpa_tl
{
\__tblr_data_item:neen { cell }
{ \int_use:N \c@rownum } { \int_use:N \c@colnum } { si }
}
\exp_args:NV \sisetup \l_tmpa_tl
##1 {##2}
\group_end:
}
}
CHAPTER 8. THE SOURCE CODE 186
\NewTblrLibrary { varwidth }
{
\RequirePackage { varwidth }
\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 }
}
\NewTblrLibrary { zref }
{
\RequirePackage { zref-user }
\clist_if_in:NnF \lTblrRefMoreClist { zref }
{
\clist_put_right:Nn \lTblrRefMoreClist { zref }
\DefTblrTemplate { caption-ref }{ zref }
{
\exp_args:NV \zlabel \lTblrLabelTl
}
}
}