% \iffalse meta-comment % % Copyright (C) 2018-2021 by F. Pantigny % ----------------------------------- % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % \fi % \iffalse \def\myfileversion{6.1} \def\myfiledate{2021/08/20} % % %<*batchfile> \begingroup \input l3docstrip.tex \keepsilent \usedir{tex/latex/nicematrix} \preamble Copyright (C) 2018-2021 by F. Pantigny ----------------------------------- This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) any later version. The latest version of this license is in: http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. \endpreamble \askforoverwritefalse \endgroup % % %<*driver> \documentclass[dvipsnames]{l3doc}% dvipsnames is for xcolor (loaded by Tikz) \VerbatimFootnotes \usepackage{xltxtra} \usepackage[xetex]{geometry} \geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}} \usepackage{tikz} \usetikzlibrary{fit,patterns} \usepackage{nicematrix} \usepackage{siunitx} \NewDocumentEnvironment {scope} {} {} {} \def\interitem{\vspace{7mm plus 2 mm minus 3mm}} \def\emphase{\bgroup\color{RoyalPurple}\let\next=} \fvset{commandchars=\~\#\@,formatcom=\color{gray}} \usepackage{titlesec} \titlespacing*{\section}{0pt}{6.5ex plus 1ex minus .2ex}{4.3ex plus .2ex} \titlespacing*{\subsection}{0pt}{4.5ex plus 1ex minus .2ex}{2ex plus .2ex} \usepackage[hyperfootnotes=false]{footnotehyper} \usepackage{varwidth} \def\LetterAt{@} \parindent 0pt \skip \footins = 2 \bigskipamount \EnableCrossrefs \makeatletter \ExplSyntaxOn \DoNotIndex{\begin,\end} \DoNotIndex{\c@iRow,\c@jCol,\theiRow,\thejCol} \DoNotIndex{\pgfpicture,\endpgfpicture,\tikzpicture,\endtikzpicture} \DoNotIndex{\pgfpoint,\pgfnode,\pgfnodealias,\pgfcoordinate} \DoNotIndex{\pgf@x,\pgf@y} \DoNotIndex{\int_add:Nn,\int_case:nnTF,\int_compare:nNnTF,\int_compare:nTF, \int_compare_p:nNn,\int_decr:N,\int_eval:n,\int_add:Nn,\int_gdecr:N,\int_gincr:N \int_gset:Nn,\int_gset_eq:NN,\int_gzero:N,\int_gzero_new:N,\int_if_odd:nTF, \int_max:nn,\int_new:N,\int_set:Nn,\int_set_eq:NN,\int_step_inline:nnn, \int_step_variable:nNn,\int_step_variable:nnNn,\int_sub:Nn,\int_use:N,\int_zero:N, \int_zero_new:N,\g_tmpa_int,\l_tmpa_int,\l_tmpb_int} \DoNotIndex{\dim_abs:n,\dim_add:Nn,\dim_compare:nNnTF,\dim_compare_p:nNn, \dim_const:Nn,\dim_eval:n,\dim_gadd:Nn,\dim_gset:Nn,\dim_gset_eq:NN, \dim_gset:Nn,\dim_gset_eq:NN,\dim_gsub:Nn,\dim_gzero_new:N,\dim_max:nn, \dim_min:nn,\dim_new:N,\dim_ration:nn,\dim_set:Nn,\dim_set_eq:NN,\dim_sub:Nn, \dim_use:N,\dim_zero:N,\dim_zero_new:N,\g_tmpa_dim,\l_tmpa_dim,\l_tmpb_dim, \c_zero_dim} \DoNotIndex{\cs_new_protected:Npn,\cs_new:Npn,\cs_set_eq:NN, \cs_set_protected:Npn} \DoNotIndex{\bool_if:NTF,\bool_new:N,\bool_set_false:N,\bool_set_true:N,\l_tmpa_bool} \DoNotIndex{\group_begin:,\group_end:,\c_math_toggle_token} \DoNotIndex{\tl_set:Nn,\l_tmpa_tl,\l_tmpb_tl} \DoNotIndex{\tl_gput_left:Nn,\tl_gput_right:Nn} \ExplSyntaxOff \makeatother \begin{document} \DocInput{nicematrix.dtx} \end{document} % % \fi % \title{The package \pkg{nicematrix}\thanks{This document corresponds to the version~\myfileversion\space of \pkg{nicematrix}, % at the date of~\myfiledate.}} \author{F. Pantigny \\ \texttt{fpantigny@wanadoo.fr}} % % \hypersetup % { % pdfinfo = % { % Title = The package 'nicematrix' , % Subject = A LaTeX package , % Author = F. Pantigny % } % } % % % \maketitle % % \begin{abstract} % The LaTeX package \pkg{nicematrix} provides new environments similar to the % classical environments |{tabular}|, |{array}| and |{matrix}| of \pkg{array} % and \pkg{amsmath} but with extended features. % \end{abstract} % % \vspace{1cm} % \hspace{1cm} % $\begin{bNiceArray}{cccc}[first-row,first-col, % code-for-first-col=\color{blue}\scriptstyle, % code-for-first-row=\color{blue}\scriptstyle, % columns-width = auto] % & C_1 & C_2 & \Cdots & C_n \\ % L_1 & a_{11} & a_{12} & \Cdots & a_{1n} \\ % L_2 & a_{21} & a_{22} & \Cdots & a_{2n} \\ % \Vdots & \Vdots & \Vdots & \Ddots & \Vdots\\ % L_n & a_{n1} & a_{n2} & \Cdots & a_{nn} % \end{bNiceArray}$\hspace{2cm} % \begin{NiceTabular}{lSSSS}[code-before = \rowcolor{red!15}{1-2} \rowcolors{3}{blue!15}{}] % \toprule % \Block{2-1}{Product} & \multicolumn{3}{c}{dimensions (cm)} & \Block{2-1}{\rotate Price} \\ % \cmidrule(rl){2-4} % & L & l & h \\ % \midrule % small & 3 & 5.5 & 1 & 30 \\ % standard & 5.5 & 8 & 1.5 & 50.5 \\ % premium & 8.5 & 10.5 & 2 & 80 \\ % extra & 8.5 & 10 & 1.5 & 85.5 \\ % special & 12 & 12 & 0.5 & 70 \\ % \bottomrule % \end{NiceTabular} % % \vspace{1cm} % The package \pkg{nicematrix} is entirely contained in the file % |nicematrix.sty|. This file may be put in the current directory or in a % |texmf| tree. However, the best is to install \pkg{nicematrix} with a TeX % distribution such as MiKTeX, TeXlive or MacTeX. % % \bigskip % \emph{Remark}: If you use LaTeX via Internet with, for example, Overleaf, you % can upload the file |nicematrix.sty| in the repertory of your % project in order to take full advantage of the latest version de % \pkg{nicematrix}.\footnote{The latest version of the file % |nicematrix.sty| may be downloaded from the \textsc{svn} server of % TeXLive:\newline % \small % \url{https:www.tug.org/svn/texlive/trunk/Master/texmf-dist/tex/latex/nicematrix/nicematrix.sty}} % % \bigskip % This package can be used with |xelatex|, |lualatex|, |pdflatex| but also by % the classical workflow |latex|-|dvips|-|ps2pdf| (or Adobe Distiller). % \textsl{However, the file nicematrix.dtx of the present documentation should % be compiled with XeLaTeX.} % % \bigskip % This package requires and \textbf{loads} the packages \pkg{l3keys2e}, % \pkg{array}, \pkg{amsmath}, \pkg{pgfcore} and the module \pkg{shapes} of % \textsc{pgf} (\pkg{tikz}, which is a layer over \textsc{pgf} is \emph{not} % loaded). The final user only has to load the package with % |\usepackage{nicematrix}|. % % % \bigskip % The idea of \pkg{nicematrix} is to create \textsc{pgf} nodes under the cells % and the positions of the rules of the tabular created by \pkg{array} and to % use these nodes to develop new features. As usual with \textsc{pgf}, the % coordinates of these nodes are written in the |aux| to be used on the next % compilation and that's why \pkg{nicematrix} may need \textbf{several % compilations}.\footnote{If you use Overleaf, Overleaf will do automatically % the right number of compilations.} % % \bigskip % Most features of \pkg{nicematrix} may be used without explicit use of % \textsc{pgf} or Tikz (which, in fact, is not loaded by default). % % \bigskip % A command |\NiceMatrixOptions| is provided to fix the options (the % scope of the options fixed by this command is the current TeX group: they are % semi-global). % % % % \newpage % % \section{The environments of this package} % % The package \pkg{nicematrix} defines the following new environments. % % \medskip % \begin{ttfamily} % \setlength{\tabcolsep}{3mm} % \begin{tabular}{llll} % \{NiceTabular\} & \{NiceArray\} & \{NiceMatrix\} \\ % \{NiceTabular*\} & \{pNiceArray\} & \{pNiceMatrix\} \\ % \{NiceTabularX\} & \{bNiceArray\} & \{bNiceMatrix\} \\ % & \{BNiceArray\} & \{BNiceMatrix\} \\ % & \{vNiceArray\} & \{vNiceMatrix\} \\ % & \{VNiceArray\} & \{VNiceMatrix\} % \end{tabular} % \end{ttfamily} % % % % % \medskip % The environments |{NiceArray}|, |{NiceTabular}| and |{NiceTabular*}| are % similar to the environments |{array}|, |{tabular}| and |{tabular*}| of the % package \pkg{array} (which is loaded by \pkg{nicematrix}). % % \medskip % The environments |{pNiceArray}|, |{bNiceArray}|, etc. have no equivalent in % \pkg{array}. % % \medskip % The environments |{NiceMatrix}|, |{pNiceMatrix}|, etc. are similar to the % corresponding environments of \pkg{amsmath} (which is loaded by % \pkg{nicematrix}): |{matrix}|, |{pmatrix}|, etc. % % \medskip % L'environnement |{NiceTabularX}| is similar to the environment |{tabularx}| % from the eponymous package.\footnote{In fact, it's possible to use directly the % |X| columns in the environnement |{NiceTabular}| (and the required % width for the tabular is fixed by the key |width|): cf. p.~\pageref{X-columns}}. % % \medskip % \textbf{It's recommended to use primarily the classical environments and to use the % environments of \pkg{nicematrix} only when some feature provided by these % environments is used (this will save memory).} % % \medskip % All the environments of the package \pkg{nicematrix} accept, between square % brackets, an optional list of \textsl{key=value} pairs. \textbf{There must be % no space before the opening bracket (|[|) of this list of options.} % % % \section{The vertical space between the rows} % % \label{cell-space} % % It's well known that some rows of the arrays created by default with LaTeX % are, by default, too close to each other. Here is a classical example. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % $\begin{pmatrix} % \frac12 & -\frac12 \\ % \frac13 & \frac14 \\ % \end{pmatrix}$ % \end{BVerbatim} % $\begin{pmatrix} % \frac12 & -\frac12 \\ % \frac13 & \frac14 \\ % \end{pmatrix}$ % % \bigskip % Inspired by the package \pkg{cellspace} which deals with that problem, the % package \pkg{nicematrix} provides two keys |cell-space-top-limit| and % |cell-space-bottom-limit| similar to the parameters |\cellspacetoplimit| and % |\cellspacebottomlimit| of \pkg{cellspace}. % % There is also a key |cell-space-limits| to set both parameters at once. % % The initial value of these parameters is $0$~pt in order to have for the % environments of \pkg{nicematrix} the same behaviour as those of \pkg{array} % and \pkg{amsmath}. However, a value of $1$~pt would probably be a good choice % and we suggest to set them with |\NiceMatrixOptions|.\footnote{One should % remark that these parameters apply also to the columns of type |S| of % \pkg{siunitx} whereas the package \pkg{cellspace} is not able to act on such % columns of type~|S|.} % % \medskip % \begin{Verbatim} % \NiceMatrixOptions{~emphase#cell-space-limits = 1pt@} % \end{Verbatim} % % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % $\begin{pNiceMatrix} % \frac12 & -\frac12 \\ % \frac13 & \frac14 \\ % \end{pNiceMatrix}$ % \end{BVerbatim} % \begin{scope} % \NiceMatrixOptions{cell-space-limits = 1pt} % $\begin{pNiceMatrix} % \frac12 & -\frac12 \\ % \frac13 & \frac14 \\ % \end{pNiceMatrix}$ % \end{scope} % % % % % % \bigskip % \section{The vertical position of the arrays} % % The package \pkg{nicematrix} provides a option |baseline| for the vertical % position of the arrays. This option takes in as value an integer which is the % number of the row on which the array will be aligned. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % $A = \begin{pNiceMatrix}[~emphase#baseline=2@] % \frac{1}{\sqrt{1+p^2}} & p & 1-p \\ % 1 & 1 & 1 \\ % 1 & p & 1+p % \end{pNiceMatrix}$ % \end{BVerbatim} % $A = \begin{pNiceMatrix}[baseline=2] % \frac{1}{\sqrt{1+p^2}} & p & 1-p \\ % 1 & 1 & 1 \\ % 1 & p & 1+p % \end{pNiceMatrix}$ % % % \medskip % It's also possible to use the option |baseline| with one of the special values % |t|, |c| or |b|. These letters may also be used absolutely like the option of % the environments |{tabular}| and |{array}| of \pkg{array}. The initial value % of |baseline| is~|c|. % % % \medskip % In the following example, we use the option |t| (equivalent to |baseline=t|) % immediately after an |\item| of list. One should remark that the presence of a % |\hline| at the beginning of the array doesn't prevent the alignment of the % baseline with the baseline of the first row (with |{tabular}| or |{array}| of % \pkg{array}, one must use |\firsthline|). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % \begin{enumerate} % \item an item % \smallskip % \item \renewcommand{\arraystretch}{1.2} % $\begin{NiceArray}~emphase#[t]@{lcccccc} % \hline % n & 0 & 1 & 2 & 3 & 4 & 5 \\ % u_n & 1 & 2 & 4 & 8 & 16 & 32 % \hline % \end{NiceArray}$ % \end{enumerate} % \end{BVerbatim} % \begin{minipage}{5cm} % \begin{enumerate} % \item an item % \smallskip % \item \renewcommand{\arraystretch}{1.2} % $\begin{NiceArray}[t]{lcccccc} % \hline % n & 0 & 1 & 2 & 3 & 4 & 5 \\ % u_n & 1 & 2 & 4 & 8 & 16 & 32 \\ % \hline % \end{NiceArray}$ % \end{enumerate} % \end{minipage} % % \medskip % However, it's also possible to use the tools of % \pkg{booktabs}\footnote{The extension \pkg{booktabs} is \emph{not} loaded % by \pkg{nicematrix}.}: |\toprule|, % |\bottomrule|, |\midrule|, etc.\par\nobreak % % \smallskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % \begin{enumerate} % \item an item % \smallskip % \item % $\begin{NiceArray}[t]{lcccccc} % ~emphase#\toprule@ % n & 0 & 1 & 2 & 3 & 4 & 5 \\ % ~emphase#\midrule@ % u_n & 1 & 2 & 4 & 8 & 16 & 32 % ~emphase#\bottomrule@ % \end{NiceArray}$ % \end{enumerate} % \end{BVerbatim} % \begin{minipage}{5cm} % \begin{enumerate} % \item an item % \smallskip % \item % $\begin{NiceArray}[t]{lcccccc} % \toprule % n & 0 & 1 & 2 & 3 & 4 & 5 \\ % \midrule % u_n & 1 & 2 & 4 & 8 & 16 & 32 \\ % \bottomrule % \end{NiceArray}$ % \end{enumerate} % \end{minipage} % % \bigskip % It's also possible to use the key |baseline| to align a matrix on an % horizontal rule (drawn by |\hline|). In this aim, one should give the value % |line-|\textsl{i} where \textsl{i} is the number of the row \emph{following} the % horizontal rule. % % \smallskip % \begin{Verbatim} % \NiceMatrixOptions{cell-space-limits=1pt} % \end{Verbatim} % % \smallskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % $A=\begin{pNiceArray}{cc|cc}~emphase#[baseline=line-3]@ % \dfrac1A & \dfrac1B & 0 & 0 \\ % \dfrac1C & \dfrac1D & 0 & 0 \\ % \hline % 0 & 0 & A & B \\ % 0 & 0 & D & D \\ % \end{pNiceArray}$ % \end{BVerbatim} % \begin{scope} % \NiceMatrixOptions{cell-space-limits=1pt} % \raisebox{-5mm}{$A=\begin{pNiceArray}{cc|cc}[baseline=line-3] % \dfrac1A & \dfrac1B & 0 & 0 \\ % \dfrac1C & \dfrac1D & 0 & 0 \\ % \hline % 0 & 0 & A & B \\ % 0 & 0 & D & D \\ % \end{pNiceArray}$} % \end{scope} % % % \section{The blocks} % \label{Block} % % \subsection{General case} % % In the environments of \pkg{nicematrix}, it's possible to use the command % |\Block| in order to place an element in the center of a rectangle of merged % cells of the array.\footnote{The spaces after a command |\Block| are deleted.} % % The command |\Block| must be used in the upper leftmost cell of the array with % two arguments. % % \begin{itemize} % \item The first argument is the size of the block with the syntax % $i$|-|$j$ where $i$ is the number of rows of the block and $j$ its number % of columns. % % If this argument is empty, its default % value is |1-1|. If the number of rows is not specified, or equal to |*|, the % block extends until the last row (idem for the columns). % % \item The second argument is the content of the block. It's possible to use % |\\| in that content to have a content on several lines. In |{NiceTabular}| % the content of the block is composed in text mode whereas, in the other % environments, it is composed in math mode. % \end{itemize} % % % \interitem % Here is an example of utilisation of the command |\Block| in mathematical matrices. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] % $\begin{bNiceArray}{ccc|c}[margin] % ~emphase#\Block{3-3}{A}@ & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % \hline % 0 & \Cdots& 0 & 0 % \end{bNiceArray}$ % \end{BVerbatim} % $\begin{bNiceArray}{ccc|c}[margin] % \Block{3-3}{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % \hline % 0 & \Cdots& 0 & 0 % \end{bNiceArray}$ % % \bigskip % One may wish to raise the size of the ``$A$'' placed in the block of the % previous example. Since this element is composed in math mode, it's not % possible to use directly a command like |\large|, |\Large| and |\LARGE|. % That's why the command |\Block| provides an option between angle brackets to % specify some TeX code which will be inserted before the beginning of the % math mode.\footnote{This argument between angular brackets may also be used to % insert a command of font such as |\bfseries| when the command |\\| is used in % the content of the block.} % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] % $\begin{bNiceArray}{ccc|c}[margin] % \Block{3-3}~emphase#<\Large>@{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % \hline % 0 & \Cdots& 0 & 0 % \end{bNiceArray}$ % \end{BVerbatim} % \begin{scope} % $\begin{bNiceArray}{ccc|c}[margin] % \Block{3-3}<\Large>{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % \hline % 0 & \Cdots& 0 & 0 % \end{bNiceArray}$ % \end{scope} % % \medskip % It's possible to set the horizontal position of the block with one of the keys % |l|, |c| and |r|. % % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] % $\begin{bNiceArray}{ccc|c}[margin] % \Block~emphase#[r]@{3-3}<\LARGE>{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % \hline % 0 & \Cdots& 0 & 0 % \end{bNiceArray}$ % \end{BVerbatim} % $\begin{bNiceArray}{ccc|c}[margin] % \Block[r]{3-3}<\LARGE>{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % \hline % 0 & \Cdots& 0 & 0 % \end{bNiceArray}$ % % \interitem % In fact, the command |\Block| accepts as first optional argument (between % square brackets) a list of couples key-value. The available keys are as % follows: % \begin{itemize} % \item the keys |l|, |c| and |r| are used to fix the horizontal position of the % content of the block, as explained previously; % \item the key |fill| takes in as value a color and fills the block with that % color; % \item the key |draw| takes in as value a color and strokes the frame of the % block with that color (the default value of that key is the current color of % the rules of the array); % \item the key |color| takes in as value a color and apply that color the % content of the block but draws also the frame of the block with that color; % \item the key |line-width| is the width (thickness) of the frame (this key % should be used only when the key |draw| or the key |hvlines| is in force); % \item the key |rounded-corners| requires rounded corners (for the frame drawn % by |draw| and the shape drawn by |fill|) with a radius equal to the value of % that key (the default value is 4~pt\footnote{This value is the initial value % of the \emph{rounded corners} of Tikz.}); % \item the key |borders| provides the ability to draw only some borders of the % blocks; the value of that key is a (comma-separated) list of elements covered % by |left|, |right|, |top| and |bottom|; % \item the keys |t| and |b| fix the base line that will be given to the block % when it has a multi-line content (the lines are separated by |\\|); % \item the keys |hvlines| draws all the vertical and horizontal rules in the % block; % \item \colorbox{yellow!50}{\textbf{New 5.19}}\enskip when the key |tikz| is % used, the Tikz path corresponding of the rectangle which delimits the block is % executed with Tikz\footnote{Tikz should be loaded (by default, % \pkg{nicematrix} only loads \textsc{pgf}) and, if it's not, an error will be % raised.} by using as options the value of that key |tikz| (which must be a % list of keys allowed for a Tikz path). For examples, cf. % p.~\pageref{tikz-key-examples}. % \end{itemize} % % \interitem % {\bfseries One must remark that, by default, the commands |\Blocks| don't create space}. % There is exception only for the blocks mono-row and the blocks mono-column as % explained just below. % % \medskip % In the following example, we have had to enlarge by hand the columns 2 and 3 % (with the construction |wc{...}| of \pkg{array}). % % \bigskip % \begin{BVerbatim} % \begin{NiceTabular}{cwc{2cm}wc{3cm}c} % rose & tulipe & marguerite & dahlia \\ % violette % & ~emphase#\Block[draw=red,fill=[RGB]{204,204,255},rounded-corners]{2-2}@ % ~emphase#{\LARGE De très jolies fleurs}@ % & & souci \\ % pervenche & & & lys \\ % arum & iris & jacinthe & muguet % \end{NiceTabular} % \end{BVerbatim} % % \medskip % \begin{center} % \begin{NiceTabular}{cwc{2cm}wc{3cm}c} % rose & tulipe & marguerite & dahlia \\ % violette & \Block[draw=red,fill=[RGB]{204,204,255},rounded-corners]{2-2} % {\LARGE De très jolies fleurs} & & souci \\ % pervenche & & & lys \\ % arum & iris & jacinthe & muguet % \end{NiceTabular} % \end{center} % % \subsection{The mono-column blocks} % % The mono-column blocks have a special behaviour. % % \begin{itemize} % \item The natural width of the contents of these blocks is taken into account % for the width of the current column. % % \colorbox{yellow!50}{\textbf{New 6.0}}\enskip In the columns with a fixed % width (columns |w{...}{...}|, |p{...}|, |b{...}|, |m{...}| and |X|), the % content of the block is formatted as a paragraph of that width. % % \item The specification of the horizontal position provided by the type of % column (|c|, |r| or |l|) is taken into account for the blocks. % % \item The specifications of font specified for the column by a construction % |>{...}| in the preamble of the array are taken into account for the % mono-column blocks of that column (this behaviour is probably expected). % \end{itemize} % % % \bigskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[baseline=c,boxwidth=12cm] % \begin{NiceTabular}{~LetterAt{}>{\bfseries}lr~LetterAt{}} \hline % \Block{2-1}{John} & 12 \\ % & 13 \\ \hline % Steph & 8 \\ \hline % \Block{3-1}{Sarah} & 18 \\ % & 17 \\ % & 15 \\ \hline % Ashley & 20 \\ \hline % Henry & 14 \\ \hline % \Block{2-1}{Madison} & 15 \\ % & 19 \\ \hline % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{@{}>{\bfseries}lr@{}}[baseline=c] \hline % \Block{2-1}{John} & 12 \\ % & 13 \\ \hline % Steph & 8 \\ \hline % \Block{3-1}{Sarah} & 18 \\ % & 17 \\ % & 15 \\ \hline % Ashley & 20 \\ \hline % Henry & 14 \\ \hline % \Block{2-1}{Madison} & 15 \\ % & 19 \\ \hline % \end{NiceTabular} % \end{scope} % % % \subsection{The mono-row blocks} % % For the mono-row blocks, the natural height and depth are taken into account % for the height and depth of the current row (as does a standard |\multicolumn| % of LaTeX). % % \subsection{The mono-cell blocks} % % A mono-cell block inherits all the properties of the mono-row blocks and % mono-column blocks. % % \medskip % At first sight, one may think that there is no point using a mono-cell block. % However, there are some good reasons to use such a block. % \begin{itemize} % \item It's possible to use the command |\\| in a (mono-cell) block. % % \item It's possible to use the option of horizontal alignment of the block in % derogation of the type of column given in the preamble of the array. % % \item It's possible do draw a frame around the cell with the key |draw| of the % command |\Block| and to fill the background with rounded corners with the keys % |fill| and |rounded-corners|.\footnote{If one simply wishes to color the % background of a unique cell, there is no point using the command |\Block|: % it's possible to use the command |\cellcolor| (when the key |colortbl-like| is % used).} % % \item It's possible to draw one or several borders of the cell with the key |borders|. % \end{itemize} % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{NiceTabular}{cc} % \toprule % Writer & ~emphase#\Block[l]{}{year\\ of birth}@ \\ % \midrule % Hugo & 1802 \\ % Balzac & 1799 \\ % \bottomrule % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{cc} % \toprule % Writer & \Block[l]{}{year\\ of birth} \\ % \midrule % Hugo & 1802 \\ % Balzac & 1799 \\ % \bottomrule % \end{NiceTabular} % % \medskip % We recall that if the first mandatory argument of |\Block| is left blank, the % block is mono-cell.\footnote{One may consider that the default value of the % first mandatory argument of |\Block| is |1-1|.} % % % % % \subsection{Horizontal position of the content of the block} % % By default, the horizontal position of the content of a block is computed % by using the positions of the \emph{contents} of the columns implied in that % block. That's why, in the following example, the header ``First group'' is % correctly centered despite the instruction |!{\qquad}| in the preamble which % has been used to increase the space between the columns (this % is not the behaviour of |\multicolumn|). % % \medskip % \begin{center} % \fvset{commandchars=\~\#\+} % \begin{BVerbatim} % \begin{NiceTabular}{@{}c!{\qquad}ccc~emphase#!{\qquad}+ccc@{}} % \toprule % Rank & ~emphase#\Block{1-3}{First group}+ & & & \Block{1-3}{Second group} \\ % & 1A & 1B & 1C & 2A & 2B & 2C \\ % \midrule % 1 & 0.657 & 0.913 & 0.733 & 0.830 & 0.387 & 0.893\\ % 2 & 0.343 & 0.537 & 0.655 & 0.690 & 0.471 & 0.333\\ % 3 & 0.783 & 0.885 & 0.015 & 0.306 & 0.643 & 0.263\\ % 4 & 0.161 & 0.708 & 0.386 & 0.257 & 0.074 & 0.336\\ % \bottomrule % \end{NiceTabular} % \end{BVerbatim} % \end{center} % % \bigskip % \begin{center} % \begin{NiceTabular}{@{}c!{\qquad}ccc!{\qquad}ccc@{}} % \toprule % Rank & \Block{1-3}{First group} & & & \Block{1-3}{Second group} \\ % & 1A & 1B & 1C & 2A & 2B & 2C \\ % \midrule % 1 & 0.657 & 0.913 & 0.733 & 0.830 & 0.387 & 0.893\\ % 2 & 0.343 & 0.537 & 0.655 & 0.690 & 0.471 & 0.333\\ % 3 & 0.783 & 0.885 & 0.015 & 0.306 & 0.643 & 0.263\\ % 4 & 0.161 & 0.708 & 0.386 & 0.257 & 0.074 & 0.336\\ % \bottomrule % \end{NiceTabular} % \end{center} % % \medskip % In order to have an horizontal positionning of the content of the block % computed with the limits of the columns of the LaTeX array (and not with the % contents of those columns), one may use the key |L|, |R| and |C| of the % command |\Block|. % % % \section{The rules} % % The usual techniques for the rules may be used in the environments of % \pkg{nicematrix} (excepted |\vline|). However, there is some small differences % with the classical environments. % % \bigskip % \subsection{Some differences with the classical environments} % % \subsubsection{The vertical rules} % % In the environments of \pkg{nicematrix}, the vertical rules specified by % \verb+|+ in the preambles of the environments are never broken, even by an % incomplete row or by a double horizontal rule specified by |\hline\hline| % (there is no need to use \pkg{hhline}). % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{NiceTabular}{|c|c|} \hline % First & Second \\ ~emphase#\hline\hline@ % Peter \\ \hline % Mary & George\\ \hline % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{|c|c|}[c] \hline % First & Second \\ \hline\hline % Peter \\ \hline % Mary & George \\ \hline % \end{NiceTabular} % % % \bigskip % However, the vertical rules are not drawn in the blocks (created by |\Block|: % cf.~p.~\pageref{Block}) nor in the corners (created by the key |corner|: % cf.~p.~\pageref{corners}). % % \bigskip % If you use \pkg{booktabs} (which provides |\toprule|, |\midrule|, % |\bottomrule|, etc.) and if you really want to add vertical rules (which is % not in the spirit of \pkg{booktabs}), you should notice that the vertical rules % drawn by \pkg{nicematrix} are compatible with \pkg{booktabs}. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.5cm] % $\begin{NiceArray}{~emphase#|cccc|@} \toprule % a & b & c & d \\ \midrule % 1 & 2 & 3 & 4 \\ % 1 & 2 & 3 & 4 \\ \bottomrule % \end{NiceArray}$ % \end{BVerbatim} % $\begin{NiceArray}{|cccc|} % \toprule % a & b & c & d \\ % \midrule % 1 & 2 & 3 & 4 \\ % 1 & 2 & 3 & 4 \\ % \bottomrule % \end{NiceArray}$ % % \bigskip % However, it's still possible to define a specifier (named, for instance, |I|) % to draw vertical rules with the standard behaviour of \pkg{array}. % % \begin{Verbatim} % \newcolumntype{I}{!{\vrule}} % \end{Verbatim} % % However, in this case, it is probably more clever to add a command % |\OnlyMainNiceMatrix| (cf. p.~\pageref{OnlyMainNiceMatrix}): % \begin{Verbatim} % \newcolumntype{I}{!{\OnlyMainNiceMatrix{\vrule}}} % \end{Verbatim} % % % \bigskip % \subsubsection{The command \textbackslash cline} % %\label{remark-cline} % % The horizontal and vertical rules drawn by |\hline| and the specifier % ``\verb+|+'' make the array larger or wider by a quantity equal to the width % of the rule (with \pkg{array} and also with \pkg{nicematrix}). % % \smallskip % For historical reasons, this is not the case with the command |\cline|, as % shown by the following example. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \setlength{\arrayrulewidth}{2pt} % \begin{tabular}{cccc} \hline % A&B&C&D \\ ~emphase#\cline{2-2}@ % A&B&C&D \\ \hline % \end{tabular} % \end{BVerbatim} % \begin{scope} % \setlength{\arrayrulewidth}{2pt} % \begin{tabular}[c]{cccc} % \hline % A&B&C&D \\ % \cline{2-2} % A&B&C&D \\ % \hline % \end{tabular} % \end{scope} % % \medskip % In the environments of \pkg{nicematrix}, this situation is corrected (it's % still possible to go to the standard behaviour of |\cline| with the key |standard-cline|). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \setlength{\arrayrulewidth}{2pt} % \begin{NiceTabular}{cccc} \hline % A&B&C&D \\ ~emphase#\cline{2-2}@ % A&B&C&D \\ \hline % \end{NiceTabular} % \end{BVerbatim} % \begin{scope} % \setlength{\arrayrulewidth}{2pt} % \begin{NiceTabular}[c]{cccc} % \hline % A&B&C&D \\ % \cline{2-2} % A&B&C&D \\ % \hline % \end{NiceTabular} % \end{scope} % % % \subsection{The thickness and the color of the rules} % % The environments of \pkg{nicematrix} provide a key |rules/width| to set the % width (in fact the thickness) of the rules in the current environment. In % fact, this key merely sets the value of the length |\arrayrulewidth|. % % \smallskip % It's well known that \pkg{colortbl} provides the command |\arrayrulecolor| in % order to specify the color of the rules. % % \smallskip % With \pkg{nicematrix}, it's possible to specify the color of the rules even % when \pkg{colortbl} is not loaded. For sake of compatibility, the command is % also named |\arrayrulecolor|. The environments of \pkg{nicematrix} also % provide a key |rules/color| to fix the color of the rules in the current % environment. This key sets the value locally (whereas |\arrayrulecolor| acts % globally). % % \medskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[baseline=c,boxwidth=9.5cm] % \begin{NiceTabular}{|ccc|}[~emphase#rules/color=[gray]{0.9},rules/width=1pt@] % \hline % rose & tulipe & lys \\ % arum & iris & violette \\ % muguet & dahlia & souci \\ % \hline % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{|ccc|}[rules/color=[gray]{0.9},rules/width=1pt] % \hline % rose & tulipe & lys \\ % arum & iris & violette \\ % muguet & dahlia & souci \\ % \hline % \end{NiceTabular} % \end{scope} % % \medskip % If one wishes to define new specifiers for columns in order to draw vertical % rules (for example with a specific color or thicker than the standard rules), % he should consider the command |\OnlyMainNiceMatrix| described on % page~\pageref{OnlyMainNiceMatrix}. % % % \subsection{The tools of nicematrix for the rules} % % Here are the tools provided by \pkg{nicematrix} for the rules. % \begin{itemize} % \item the keys |hlines|, |vlines|, |hvlines| and |hvlines-except-borders|; % \item the specifier ``\verb+|+'' in the preamble (for the environments with % preamble); % \item the command |\Hline|. % \end{itemize} % % \medskip % \textbf{All these tools don't draw the rules in the blocks nor in the % empty corners (when the key |corners| is used).} % \begin{itemize} % \item These blocks are: % \begin{itemize} % \item the blocks created by the command |\Block|\footnote{And also the command |\multicolumn| but % it's recommended to use instead |\Block| in the environments of % \pkg{nicematrix}.} presented % p.~\pageref{Block}; % \item the blocks implicitely delimited by the continuous dotted lines created % by |\Cdots|, |Vdots|, etc. (cf.~p.~\pageref{Cdots}). % \end{itemize} % \item The corners are created by the key |corners| explained below (see p.~\pageref{corners}). % \end{itemize} % % In particular, this remark explains the difference between the standard % command |\hline| and the command |\Hline| provided by \pkg{nicematrix}. % % % \subsubsection{The keys hlines and vlines} % % The keys |hlines| and |vlines| (which draw, of course, horizontal and vertical % rules) take in as value a list of numbers which are the numbers of the rules % to draw. % % In fact, for the environments with delimiters (such as |{pNiceMatrix}| or % |{bNiceArray}|), the key |vlines| don't draw the exterior rules (this is % certainly the expected behaviour). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] % $\begin{pNiceMatrix}[~emphase#vlines@,rules/width=0.2pt] % 1 & 2 & 3 & 4 & 5 & 6 \\ % 1 & 2 & 3 & 4 & 5 & 6 \\ % 1 & 2 & 3 & 4 & 5 & 6 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix}[vlines,rules/width=0.2pt] % 1 & 2 & 3 & 4 & 5 & 6 \\ % 1 & 2 & 3 & 4 & 5 & 6 \\ % 1 & 2 & 3 & 4 & 5 & 6 % \end{pNiceMatrix}$ % % % % \subsubsection{The keys hvlines and hvlines-except-borders} % \label{hvlines} % % The key |hvlines| (no value) is the conjonction of the keys |hlines| and |vlines|. % % \smallskip % \begin{Verbatim} % \setlength{\arrayrulewidth}{1pt} % \begin{NiceTabular}{cccc}[~emphase#hvlines@,rules/color=blue] % rose & tulipe & marguerite & dahlia \\ % violette & \Block[draw=red]{2-2}{\LARGE fleurs} & & souci \\ % pervenche & & & lys \\ % arum & iris & jacinthe & muguet % \end{NiceTabular} % \end{Verbatim} % % \begin{center} % \setlength{\arrayrulewidth}{1pt} % \begin{NiceTabular}{cccc}[hvlines,rules/color=blue] % rose & tulipe & marguerite & dahlia \\ % violette & \Block[draw=red]{2-2}{\LARGE fleurs} & & souci \\ % pervenche & & & lys \\ % arum & iris & jacinthe & muguet % \end{NiceTabular} % \end{center} % % \bigskip % The key |hvlines-except-borders| is similar to the key |hvlines| but does not % draw the rules on the horizontal and vertical borders of the array. % % \subsubsection{The (empty) corners} % % \label{corners} % % The four |corners| of an array will be designed by |NW|, |SW|, |NE| and |SE| % (\emph{north west}, \emph{south west}, \emph{north east} and \emph{south east}). % % For each of these corners, we will call \emph{empty corner} (or simply % \emph{corner}) the reunion of all the empty rectangles starting from the cell % actually in the corner of the array.\footnote{For sake of completeness, we % should also say that a cell contained in a block (even an empty cell) is not % taken into account for the determination of the corners. That behaviour is natural.} % % However, it's possible, for a cell without content, to require \pkg{nicemarix} % to consider that cell as not empty with the key |\NotEmpty|. % %\bigskip % \begin{minipage}{9cm} % In the example on the right (where B is in the center of a block of size % $2\times2$), we have colored in blue the four (empty) corners of the array. % \end{minipage}\hspace{2cm}% % \begin{NiceTabular}{*{6}{c}}[cell-space-top-limit=3pt] % \CodeBefore % \rectanglecolor{blue!10}{1-1}{4-2} % \rectanglecolor{blue!10}{1-1}{1-4} % \rectanglecolor{blue!10}{1-6}{3-6} % \rectanglecolor{blue!10}{7-1}{9-1} % \rectanglecolor{blue!10}{7-5}{9-6} % \Body % & & & & A \\ % & & A & A & A \\ % & & & A \\ % & & A & A & A & A \\ % A & A & A & A & A & A \\ % A & A & A & A & A & A \\ % & A & A & A \\ % & \Block{2-2}{B} & & A \\ % & & & A \\ % \end{NiceTabular} % % \bigskip % When the key |corners| is used, \pkg{nicematrix} computes the (empty) corners % and these corners will be taken into account by the tools for drawing the % rules (the rules won't be drawn in the corners). \emph{Remark}: In the % previous versions of \pkg{nicematrix}, there was only a key % |hvlines-except-corners| (now considered as obsolete). % % \bigskip % \begin{BVerbatim}[boxwidth=11cm,baseline=c] % \NiceMatrixOptions{cell-space-top-limit=3pt} % \begin{NiceTabular}{*{6}{c}}[~emphase#corners@,hvlines] % & & & & A \\ % & & A & A & A \\ % & & & A \\ % & & A & A & A & A \\ % A & A & A & A & A & A \\ % A & A & A & A & A & A \\ % & A & A & A \\ % & \Block{2-2}{B} & & A \\ % & & & A \\ % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{*{6}{c}}[corners,hvlines,cell-space-top-limit=3pt] % & & & & A \\ % & & A & A & A \\ % & & & A \\ % & & A & A & A & A \\ % A & A & A & A & A & A \\ % A & A & A & A & A & A \\ % & A & A & A \\ % & \Block{2-2}{B} & & A \\ % & & & A \\ % \end{NiceTabular} % % % \bigskip % It's also possible to provide to the key |corners| a (comma-separated) list of % corners (designed by |NW|, |SW|, |NE| and |SE|). % % \medskip % \begin{BVerbatim}[boxwidth=11cm,baseline=c] % \NiceMatrixOptions{cell-space-top-limit=3pt} % \begin{NiceTabular}{*{6}{c}}[~emphase#corners=NE@,hvlines] % 1\\ % 1&1\\ % 1&2&1\\ % 1&3&3&1\\ % 1&4&6&4&1\\ % & & & & &1 % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{*{6}{c}}[c,corners=NE,hvlines,cell-space-top-limit=3pt] % 1\\ % 1&1\\ % 1&2&1\\ % 1&3&3&1\\ % 1&4&6&4&1\\ % & & & & &1 % \end{NiceTabular} % % % \medskip % $\triangleright$ The corners are also taken into account by the tools provided % by \pkg{nicematrix} to color cells, rows and columns. These tools don't color % the cells which are in the corners (cf.~p.~\pageref{color-in-code-before}). % % \subsection{The command \textbackslash diagbox} % % The command |\diagbox| (inspired by the package \pkg{diagbox}), allows, when % it is used in a cell, to slash that cell diagonally downwards.\footnote{The % author of this document considers that type of construction as graphically % poor.}. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $\begin{NiceArray}{*{5}{c}}[hvlines] % ~emphase#\diagbox{x}{y}@ & e & a & b & c \\ % e & e & a & b & c \\ % a & a & e & c & b \\ % b & b & c & e & a \\ % c & c & b & a & e % \end{NiceArray}$ % \end{BVerbatim} % $\begin{NiceArray}{*{5}{c}}[hvlines] % \diagbox{x}{y} & e & a & b & c \\ % e & e & a & b & c \\ % a & a & e & c & b \\ % b & b & c & e & a \\ % c & c & b & a & e % \end{NiceArray}$ % % \medskip % It's possible to use the command |\diagbox| in a |\Block|. % % % \subsection{Dotted rules} % % % In the environments of the package \pkg{nicematrix}, it's possible to use % the command |\hdottedline| (provided by \pkg{nicematrix}) which is a % counterpart of the classical commands |\hline| and |\hdashline| (the latter is % a command of \pkg{arydshln}). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9.5cm] % \begin{pNiceMatrix} % 1 & 2 & 3 & 4 & 5 \\ % ~emphase#\hdottedline@ % 6 & 7 & 8 & 9 & 10 \\ % 11 & 12 & 13 & 14 & 15 % \end{pNiceMatrix} % \end{BVerbatim} % $\begin{pNiceMatrix} % 1 & 2 & 3 & 4 & 5 \\ % \hdottedline % 6 & 7 & 8 & 9 & 10 \\ % 11 & 12 & 13 & 14 & 15 % \end{pNiceMatrix}$ % % % \bigskip % In the environments with an explicit preamble (like |{NiceTabular}|, % |{NiceArray}|, etc.), it's possible to draw a vertical dotted line with the % specifier ``|:|''. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9.5cm] % \left(\begin{NiceArray}{cccc~emphase#:@c} % 1 & 2 & 3 & 4 & 5 \\ % 6 & 7 & 8 & 9 & 10 \\ % 11 & 12 & 13 & 14 & 15 % \end{NiceArray}\right) % \end{BVerbatim} % $\left(\begin{NiceArray}{cccc:c} % 1 & 2 & 3 & 4 & 5 \\ % 6 & 7 & 8 & 9 & 10 \\ % 11 & 12 & 13 & 14 & 15 % \end{NiceArray}\right)$ % % \bigskip % It's possible to change in \pkg{nicematrix} the letter used to specify a % vertical dotted line with the option |letter-for-dotted-lines| available in % |\NiceMatrixOptions|. Thus released, the letter ``|:|'' can be used otherwise % (for example by the package \pkg{arydshln}\footnote{However, one should remark % that the package \pkg{arydshln} is not fully compatible with % \pkg{nicematrix}.}). % % \bigskip % \emph{Remark}: In the package \pkg{array} (on which the package % \pkg{nicematrix} relies), horizontal and vertical rules make the array larger % or wider by a quantity equal to the width of the rule\footnote{In fact, with % \pkg{array}, this is true only for |\hline| and ``"|"'' but not for |\cline|: % cf p.~\pageref{remark-cline}}. In \pkg{nicematrix}, the dotted lines drawn by % |\hdottedline| and ``|:|'' do likewise. % % % %\section{The color of the rows and columns} % % \subsection{Use of colortbl} % % We recall that the package \pkg{colortbl} can be loaded directly with % |\usepackage{colortbl}| or by loading \pkg{xcolor} with the key |table|: % |\usepackage[table]{xcolor}|. % % \medskip % Since the package \pkg{nicematrix} is based on \pkg{array}, it's possible to % use \pkg{colortbl} with \pkg{nicematrix}. % % \medskip % However, there is two drawbacks: % \begin{itemize} % \item The package \pkg{colortbl} patches \pkg{array}, leading to some % incompatibilities (for instance with the command |\hdotsfor|). % % \item The package \pkg{colortbl} constructs the array row by row, alterning % colored rectangles, rules and contents of the cells. The resulting % \textsc{pdf} is difficult to interpret by some \textsc{pdf} viewers and may % lead to artefacts on the screen. % \begin{itemize} % \item Some rules seem to disappear. This is because many PDF viewers give % priority to graphical element drawn posteriorly (which is in the spirit of the % ``painting model'' of PostScript and PDF). Concerning this problem, MuPDF % (which is used, for instance, by SumatraPDF) gives better results than Adobe % Reader). % \item A thin white line may appear between two cells of the same color. This % phenomenon occurs when each cell is colored with its own instruction |fill| % (the PostScript operator |fill| noted |f| in PDF). This is the case with % \pkg{colortbl}: each cell is colored on its own, even when |\columncolor| or % |\rowcolor| is used. % % As for this phenomenon, Adobe Reader gives better results than MuPDF. % \end{itemize} % % The package \pkg{nicematrix} provides tools to avoid those problems. % \end{itemize} % % \subsection{The tools of nicematrix in the \textbackslash CodeBefore} % % \label{color-in-code-before} % % The package \pkg{nicematrix} provides some tools (independent of % \pkg{colortbl}) to draw the colored panels first, and, then, the content of % the cells and the rules. This strategy is more conform to the ``painting % model'' of the formats PostScript and \textsc{pdf} and is more suitable for % the \textsc{pdf} viewers. However, it requires several % compilations.\footnote{If you use Overleaf, Overleaf will do automatically the % right number of compilations.} % % \medskip % The extension \pkg{nicematrix} provides a key |code-before| for some code that % will be executed before the drawing of the tabular. % % \medskip % An alternative syntax is provided: it's possible to put the content of that % |code-before| between the keywords |\CodeBefore| and |\Body| at the beginning % of the environment. % % \begin{Verbatim} % \begin{pNiceArray}{~textsl#preamble@} % ~emphase#\CodeBefore@ % ~textsl#instructions of the code-before@ % ~emphase#\Body@ % ~textsl#contents of the environnement@ % \end{pNiceArray} % \end{Verbatim} % % New commands are available in that |\CodeBefore|: |\cellcolor|, % |\rectanglecolor|, |\rowcolor|, |\columncolor|, |\rowcolors|, % |\rowlistcolors|, |\chessboardcolors| and |arraycolor|.\footnote{Remark that, % in the |\CodeBefore|, PGF/Tikz nodes of the form ``\verb+(i-|j)+'' are % also available to indicate the position to the potential rules: % cf.~p.~\pageref{nodes-i}.} % \label{code-before} % % \medskip % All these commands accept an optional argument (between square brackets and % in first position) which is the color model for the specification of the % colors. % % \medskip % These commands don't color the cells which are in the ``corners'' if the key % |corners| is used. This key has been described p.~\pageref{corners}. % % \medskip % \begin{itemize} % \item The command |\cellcolor| takes its name from the command |\cellcolor| of % \pkg{colortbl}. % % This command takes in as mandatory arguments a color and a list of cells, each % of which with the format $i$-$j$ where $i$ is the number of the row and $j$ the % number of the colummn of the cell. % % % \medskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[boxwidth=10cm,baseline=c] % \begin{NiceTabular}{|c|c|c|} % \CodeBefore % ~emphase#\cellcolor[HTML]{FFFF88}{3-1,2-2,1-3}@ % \Body % \hline % a & b & c \\ \hline % e & f & g \\ \hline % h & i & j \\ \hline % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{|c|c|c|} % \CodeBefore % \cellcolor[HTML]{FFFF88}{3-1,2-2,1-3} % \Body % \hline % a & b & c \\ \hline % e & f & g \\ \hline % h & i & j \\ \hline % \end{NiceTabular} % \end{scope} % % \bigskip % \item The command |\rectanglecolor| takes three mandatory arguments. The first % is the color. The second is the upper-left cell of the rectangle and the third % is the lower-right cell of the rectangle. % % \medskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[boxwidth=10cm,baseline=c] % \begin{NiceTabular}{|c|c|c|} % \CodeBefore % ~emphase#\rectanglecolor{blue!15}{2-2}{3-3}@ % \Body % \hline % a & b & c \\ \hline % e & f & g \\ \hline % h & i & j \\ \hline % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{|c|c|c|} % \CodeBefore % \rectanglecolor{blue!15}{2-2}{3-3} % \Body % \hline % a & b & c \\ \hline % e & f & g \\ \hline % h & i & j \\ \hline % \end{NiceTabular} % \end{scope} % % \bigskip % \item The command |\arraycolor| takes in as mandatory argument a color and % color the whole tabular with that color (excepted the potential exterior rows % and columns: cf.~p.~\pageref{exterior}). It's only a particular case of % |\rectanglecolor|. % % % \bigskip % \item The command |\chessboardcolors| takes in as mandatory arguments two colors % and it colors the cells of the tabular in quincunx with these colors. % % \medskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % $\begin{pNiceMatrix}[r,margin] % \CodeBefore % ~emphase#\chessboardcolors{red!15}{blue!15}@ % \Body % 1 & -1 & 1 \\ % -1 & 1 & -1 \\ % 1 & -1 & 1 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix}[r,baseline=1, margin] % \CodeBefore % \chessboardcolors{red!15}{blue!15} % \Body % 1 & -1 & 1 \\ % -1 & 1 & -1 \\ % 1 & -1 & 1 % \end{pNiceMatrix}$ % \end{scope} % % \medskip % We have used the key |r| which aligns all the columns rightwards (cf. % p.~\pageref{key-R}). % % % \bigskip % \item The command |\rowcolor| takes its name from the command |\rowcolor| of % \pkg{colortbl}. Its first mandatory argument is the color and the second is a % comma-separated list of rows or interval of rows with the form $a$-$b$ (an % interval of the form $a$- represent all the rows from the row $a$ until the end). % % \medskip % \begin{scope} % \hfuzz = 10cm % \begin{BVerbatim}[boxwidth=9cm,baseline=c] % $\begin{NiceArray}{lll}[hvlines] % \CodeBefore % ~emphase#\rowcolor{red!15}{1,3-5,8-}@ % \Body % a_1 & b_1 & c_1 \\ % a_2 & b_2 & c_2 \\ % a_3 & b_3 & c_3 \\ % a_4 & b_4 & c_4 \\ % a_5 & b_5 & c_5 \\ % a_6 & b_6 & c_6 \\ % a_7 & b_7 & c_7 \\ % a_8 & b_8 & c_8 \\ % a_9 & b_9 & c_9 \\ % a_{10} & b_{10} & c_{10} \\ % \end{NiceArray}$ % \end{BVerbatim} % $\begin{NiceArray}{lll}[baseline=4,hvlines] % \CodeBefore % \rowcolor{red!15}{1,3-5,8-} % \Body % a_1 & b_1 & c_1 \\ % a_2 & b_2 & c_2 \\ % a_3 & b_3 & c_3 \\ % a_4 & b_4 & c_4 \\ % a_5 & b_5 & c_5 \\ % a_6 & b_6 & c_6 \\ % a_7 & b_7 & c_7 \\ % a_8 & b_8 & c_8 \\ % a_9 & b_9 & c_9 \\ % a_{10} & b_{10} & c_{10} \\ % \end{NiceArray}$ % \end{scope} % % % \bigskip % \item The command |\columncolor| takes its name from the command % |\columncolor| of \pkg{colortbl}. Its syntax is similar to the syntax of % |\rowcolor|. % % \bigskip % \item The command |\rowcolors| (with a \emph{s}) takes its name from the % command |\rowcolors| of \pkg{xcolor}\footnote{The command |\rowcolors| of % \pkg{xcolor} is available when \pkg{xcolor} is loaded with the option~|table|. % That option also loads the package \pkg{colortbl}.}. The \emph{s} emphasizes % the fact that there is \emph{two} colors. This command colors alternately the % rows of the tabular with the tow colors (provided in second and third % argument), beginning with the row whose number is given in first (mandatory) % argument. % % In fact, the first (mandatory) argument is, more generally, a comma separated % list of intervals describing the rows involved in the action of |\rowcolors| % (an interval of the form $i$|-| describes in fact the interval of all the rows % of the tabular, beginning with the row~$i$). % % % \bigskip % The last argument of |\rowcolors| is an optional list of pairs key-value (the % optional argument in the first position corresponds to the colorimetric % space). The available keys are |cols|, |restart| and |respect-blocks|. % \begin{itemize} % \item The key |cols| describes a set of columns. The command |\rowcolors| will % color only the cells of these columns. The value is a comma-separated list of % intervals of the form $i$-$j$ (where $i$ or $j$ may be replaced by |*|). % \item With the key |restart|, each interval of rows (specified by the first % mandatory argument) begins with the same color.\footnote{Otherwise, the color % of a given row relies only upon the parity of its absolute number.} % \item With the key |respect-blocks| the ``rows'' alternately colored may extend over % several rows if they have to incorporate blocks (created with the command % |\Block|: cf.~p.~\pageref{Block}). % \end{itemize} % % \medskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{NiceTabular}{clr}[hvlines] % \CodeBefore % ~emphase#\rowcolors[gray]{2}{0.8}{}[cols=2-3,restart]@ % \Body % \Block{1-*}{Results} \\ % John & 12 \\ % Stephen & 8 \\ % Sarah & 18 \\ % Ashley & 20 \\ % Henry & 14 \\ % Madison & 15 % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{clr}[hvlines,baseline=2] % \CodeBefore % \rowcolors[gray]{2}{0.8}{}[cols=2-3,restart] % \Body % \Block{1-*}{Results} \\ % \Block{2-1}{A}& John & 12 \\ % & Stephen & 8 \\ % \Block{4-1}{B}& Sarah & 18 \\ % & Ashley & 20 \\ % & Henry & 14 \\ % & Madison & 15 % \end{NiceTabular} % \end{scope} % % \vspace{1cm} % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{NiceTabular}{lr}[hvlines] % \CodeBefore % ~emphase#\rowcolors{1}{blue!10}{}[respect-blocks]@ % \Body % \Block{2-1}{John} & 12 \\ % & 13 \\ % Steph & 8 \\ % \Block{3-1}{Sarah} & 18 \\ % & 17 \\ % & 15 \\ % Ashley & 20 \\ % Henry & 14 \\ % \Block{2-1}{Madison} & 15 \\ % & 19 % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{lr}[hvlines,baseline=c] % \CodeBefore % \rowcolors{1}{blue!10}{}[respect-blocks] % \Body % \Block{2-1}{John} & 12 \\ % & 13 \\ % Steph & 8 \\ % \Block{3-1}{Sarah} & 18 \\ % & 17 \\ % & 15 \\ % Ashley & 20 \\ % Henry & 14 \\ % \Block{2-1}{Madison} & 15 \\ % & 19 % \end{NiceTabular} % \end{scope} % % % % % \bigskip % \item \colorbox{yellow!50}{\textbf{New 6.0}}\enskip The extension % \pkg{nicematrix} provides also a command |\rowlistcolors|. This command % generalises the command |\rowcolors|: instead of two successive arguments for % the colors, this command takes in an argument which is a (comma-separated) % list of colors. In that list, the symbol |=| represent a color identical to % the previous one. % \end{itemize} % % \smallskip % \begin{BVerbatim}[boxwidth=10cm,baseline=c] % \begin{NiceTabular}{c} % \CodeBefore % ~emphase#\rowlistcolors{1}{red!15,blue!15,green!15}@ % \Body % Peter \\ % James \\ % Abigail \\ % Elisabeth \\ % Claudius \\ % Jane \\ % Alexandra \\ % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{c} % \CodeBefore % \rowlistcolors{1}{red!15,blue!15,green!15} % \Body % Peter \\ % James \\ % Abigail \\ % Elisabeth \\ % Claudius \\ % Jane \\ % Alexandra \\ % \end{NiceTabular} % % % \medskip % We recall that all the color commands we have described don't color the cells % which are in the ``corners''. In the following example, we use the key % |corners| to require the determination of the corner \emph{north east} (NE). % %\medskip % \begin{scope} % \hfuzz=11cm % \begin{BVerbatim}[boxwidth=9cm,baseline=c] % \begin{NiceTabular}{cccccc}[~emphase#corners=NE@,margin,hvlines,first-row,first-col] % \CodeBefore % ~emphase#\rowlistcolors{1}{blue!15, }@ % \Body % & 0 & 1 & 2 & 3 & 4 & 5 & 6 \\ % 0 & 1 \\ % 1 & 1 & 1 \\ % 2 & 1 & 2 & 1 \\ % 3 & 1 & 3 & 3 & 1 \\ % 4 & 1 & 4 & 6 & 4 & 1 \\ % 5 & 1 & 5 & 10 & 10 & 5 & 1 \\ % 6 & 1 & 6 & 15 & 20 & 15 & 6 & 1 \\ % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{ccccccc}[corners=NE,margin,hvlines,first-row,first-col] % \CodeBefore % \rowlistcolors{1}{blue!15, } % \Body % & 0 & 1 & 2 & 3 & 4 & 5 & 6 \\ % 0 & 1 \\ % 1 & 1 & 1 \\ % 2 & 1 & 2 & 1 \\ % 3 & 1 & 3 & 3 & 1 \\ % 4 & 1 & 4 & 6 & 4 & 1 \\ % 5 & 1 & 5 & 10 & 10 & 5 & 1 \\ % 6 & 1 & 6 & 15 & 20 & 15 & 6 & 1 \\ % \end{NiceTabular} % \end{scope} % % % \bigskip % One should remark that all the previous commands are compatible with the % commands of \pkg{booktabs} (|\toprule|, |\midrule|, |\bottomrule|, etc). % However, \pkg{booktabs} is not loaded by \pkg{nicematrix}. % % \medskip % \begin{scope} % \hfuzz=10cm % \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] % \begin{NiceTabular}[c]{lSSSS} % \CodeBefore % \rowcolor{red!15}{1-2} % \rowcolors{3}{blue!15}{} % \Body % ~emphase#\toprule@ % \Block{2-1}{Product} & % \Block{1-3}{dimensions (cm)} & & & % \Block{2-1}{\rotate Price} \\ % ~emphase#\cmidrule(rl){2-4}@ % & L & l & h \\ % ~emphase#\midrule@ % small & 3 & 5.5 & 1 & 30 \\ % standard & 5.5 & 8 & 1.5 & 50.5 \\ % premium & 8.5 & 10.5 & 2 & 80 \\ % extra & 8.5 & 10 & 1.5 & 85.5 \\ % special & 12 & 12 & 0.5 & 70 \\ % ~emphase#\bottomrule@ % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}[c]{lSSSS} % \CodeBefore % \rowcolor{red!15}{1-2} % \rowcolors{3}{blue!15}{} % \Body % \toprule % \Block{2-1}{Product} & % \Block{1-3}{dimensions (cm)} & & & % \Block{2-1}{\rotate Price} \\ % \cmidrule(rl){2-4} % & L & l & h \\ % \midrule % small & 3 & 5.5 & 1 & 30 \\ % standard & 5.5 & 8 & 1.5 & 50.5 \\ % premium & 8.5 & 10.5 & 2 & 80 \\ % extra & 8.5 & 10 & 1.5 & 85.5 \\ % special & 12 & 12 & 0.5 & 70 \\ % \bottomrule % \end{NiceTabular} % \end{scope} % % \medskip % We have used the type of column |S| of \pkg{siunitx}. % % % \subsection{Color tools with the syntax of colortbl} % % It's possible to access the preceding tools with a syntax close to the syntax % of \pkg{colortbl}. For that, one must use the key |colortbl-like| in the % current environment.\footnote{Up to now, this key is \emph{not} available in |\NiceMatrixOptions|.} % % There are three commands available (they are inspired by \pkg{colortbl} but % are \emph{independent} of \pkg{colortbl}): % \begin{itemize} % \item |\cellcolor| which colorizes a cell; % \item |\rowcolor| which must be used in a cell and which colorizes the end of % the row; % \item |\columncolor| which must be used in the preamble of the environment % with the same syntax as the corresponding command of % \pkg{colortbl} (however, unlike the command |\columncolor| of \pkg{colortbl}, % this command |\columncolor| can appear within another command, itself used in the % preamble of the array). % \end{itemize} % % \medskip % \begin{Verbatim} % \NewDocumentCommand { \Blue } { } { ~emphase#\columncolor{blue!15}@ } % \begin{NiceTabular}[colortbl-like]{>{\Blue}c>{\Blue}cc} % \toprule % ~emphase#\rowcolor{red!15}@ % Last name & First name & Birth day \\ % \midrule % Achard & Jacques & 5 juin 1962 \\ % Lefebvre & Mathilde & 23 mai 1988 \\ % Vanesse & Stephany & 30 octobre 1994 \\ % Dupont & Chantal & 15 janvier 1998 \\ % \bottomrule % \end{NiceTabular} % \end{Verbatim} % % % \begin{center} % \NewDocumentCommand { \Blue } { } { \columncolor{blue!15} } % \begin{NiceTabular}[colortbl-like]{>{\Blue}c>{\Blue}cc} % \toprule % \rowcolor{red!15} % Last name & First name & Birth day \\ % \midrule % Achard & Jacques & 5 juin 1962 \\ % Lefebvre & Mathilde & 23 mai 1988 \\ % Vanesse & Stephany & 30 octobre 1994 \\ % Dupont & Chantal & 15 janvier 1998 \\ % \bottomrule % \end{NiceTabular} % \end{center} % % \section{The command \textbackslash RowStyle} % % \label{RowStyle} % % \colorbox{yellow!50}{\bfseries New 5.18}\enskip The command |\RowStyle| takes % in as argument some formatting intructions that will be applied to each cell % on the rest of the current row. % % \medskip % That command also takes in as optional argument (between square brackets) % a list of key-value pairs. % \begin{itemize} % \item The keys |cell-space-top-limit|, |cell-space-bottom-limit| and % |cell-space-limits| are available with the same meaning that the corresponding % global keys (cf. p.~\pageref{cell-space}). % \item \colorbox{yellow!50}{\bfseries New 6.1}\enskip The key |color| sets the % color of the text.\footnote{The key |color| uses the command % |\color| but inserts also an instruction |\leavevmode| before. This % instruction prevents a extra vertical space in the cells which belong to % columns of type |p|, |b|, |m| and |X| (which start in % vertical mode).} % \end{itemize} % % \medskip % \begin{BVerbatim}[boxwidth=11cm,baseline=c] % \begin{NiceTabular}{cccc}[colortbl-like] % \hline % ~emphase#\RowStyle[cell-space-limits=3pt]{\rotate}@ % first & second & third & fourth \\ % \rowcolor{blue!50}~emphase#\RowStyle[color=white]{\sffamily}@ % 1 & 2 & 3 & 4 \\ % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{cccc}[colortbl-like] % \hline % \RowStyle[cell-space-limits=3pt]{\rotate} % first & second & third & fourth \\ % \rowcolor{blue!50}\RowStyle[color=white]{\sffamily} % 1 & 2 & 3 & 4 \\ % \end{NiceTabular} % % \medskip % The command |\rotate| is described p.~\pageref{rotate}. % % \section{The width of the columns} % \label{width} % % \subsection{Basic tools} % % In the environments with an explicit preamble (like |{NiceTabular}|, % |{NiceArray}|, etc.), it's possible to fix the width of a given column with % the standard letters |w|, |W|, |p|, |b| and |m| of the package \pkg{array}. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % \begin{NiceTabular}{~emphase#Wc{2cm}@cc}[hvlines] % Paris & New York & Madrid \\ % Berlin & London & Roma \\ % Rio & Tokyo & Oslo % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{Wc{2cm}cc}[hvlines] % Paris & New York & Madrid \\ % Berlin & London & Roma \\ % Rio & Tokyo & Oslo % \end{NiceTabular} % % % \bigskip % In the environments of \pkg{nicematrix}, it's also possible to fix the \emph{minimal} % width of all the columns (excepted the potential exterior columns: cf. p.~\pageref{exterior}) directly % with the key |columns-width|. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $\begin{pNiceMatrix}[~emphase#columns-width = 1cm@] % 1 & 12 & -123 \\ % 12 & 0 & 0 \\ % 4 & 1 & 2 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix}[columns-width = 1cm] % 1 & 12 & -123 \\ % 12 & 0 & 0 \\ % 4 & 1 & 2 % \end{pNiceMatrix}$ % % \medskip % Note that the space inserted between two columns (equal to 2 |\tabcolsep| in % |{NiceTabular}| and to 2 |\arraycolsep| in the other environments) % is not suppressed (of course, it's possible to suppress this space by setting % |\tabcolsep| or |\arraycolsep| equal to $0$~pt before the environment). % % \bigskip % It's possible to give the special value |auto| to the option |columns-width|: % all the columns of the array will have a width equal to the widest cell of the % array.\footnote{The result is achieved with only one compilation (but PGF/Tikz % will have written informations in the |aux| file and a message requiring a % second compilation will appear).}\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $\begin{pNiceMatrix}[~emphase#columns-width = auto@] % 1 & 12 & -123 \\ % 12 & 0 & 0 \\ % 4 & 1 & 2 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix}[columns-width = auto] % 1 & 12 & -123 \\ % 12 & 0 & 0 \\ % 4 & 1 & 2 % \end{pNiceMatrix}$ % % \bigskip % Without surprise, it's possible to fix the minimal width of the columns of all % the arrays of a current scope with the command % |\NiceMatrixOptions|.\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] % ~emphase#\NiceMatrixOptions{columns-width=10mm}@ % $\begin{pNiceMatrix} % a & b \\ c & d % \end{pNiceMatrix} % = % \begin{pNiceMatrix} % 1 & 1245 \\ 345 & 2 % \end{pNiceMatrix}$ % \end{BVerbatim} % \begin{scope} % \NiceMatrixOptions{columns-width=10mm} % $\begin{pNiceMatrix} % a & b \\ % c & d % \end{pNiceMatrix} % = % \begin{pNiceMatrix} % 1 & 1245 \\ % 345 & 2 % \end{pNiceMatrix}$ % \end{scope} % % % \bigskip % But it's also possible to fix a zone where all the matrices will have their % columns of the same width, equal to the widest cell of all the matrices. This % construction uses the environment |{NiceMatrixBlock}| with the option % |auto-columns-width|\footnote{At this time, this is the only usage of the % environment |{NiceMatrixBlock}| but it may have other usages in the future.}. % The environment |{NiceMatrixBlock}| has no direct link with the command % |\Block| presented previously in this document (cf.~p.~\pageref{Block}). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] % ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@ % $\begin{array}{c} % \begin{bNiceMatrix} % 9 & 17 \\ -2 & 5 % \end{bNiceMatrix} \\ \\ % \begin{bNiceMatrix} % 1 & 1245345 \\ 345 & 2 % \end{bNiceMatrix} % \end{array}$ % ~emphase#\end{NiceMatrixBlock}@ % \end{BVerbatim} % \begin{NiceMatrixBlock}[auto-columns-width] % $\begin{array}{c} % \begin{bNiceMatrix} % 9 & 17 \\ -2 & 5 % \end{bNiceMatrix} \\ \\ % \begin{bNiceMatrix} % 1 & 1245345 \\ 345 & 2 % \end{bNiceMatrix} % \end{array}$ % \end{NiceMatrixBlock} % % \subsection{The columns X} % % \label{X-columns} % \colorbox{yellow!50}{\textbf{New 6.0}} % % The environment |{NiceTabular}| provides |X| columns similar to those provided % by the environment |{tabularx}| of the eponymous package. % % The required width of the tabular may be specified with the key |width|. The % initial value of this parameter is |\linewidth|. % % For sake of similarity with the environment |{tabularx}|, \pkg{nicematrix} % also provides an environment |{NiceTabularX}| with a first mandatory argument % which is the width of the tabular. % % As with the packages \pkg{tabu} and \pkg{tabularray}, the specifier |X| takes % in an optional argument (between square brackets) which is a list of keys. % \begin{itemize} % \item It's possible to give a weight for the column by providing an integer % directly as argument of the specifier |X|. For example, a column |X[2]| will % have a width double of the width of a column |X| (which has a weight equal to $1$). % \item It's possible to specify an horizontal alignment with one of the % letters |l|, |c| and |r| (which inserts respectively |\raggedright|, % |\centering| and |\raggedleft| followed by |\arraybackslash|). % \item It's possible to specify a vertical alignement with one of the keys % |t| (alias |p|), |m| and |b| (which construct respectively columns of type % |p|, |m| and |b|). The default value is |t|. % \end{itemize} % % \begin{Verbatim} % \begin{NiceTabular}~emphase#[width=9cm]{X[2,l]X[l]}@[hvlines] % a rather long text which fits on several lines % & a rather long text which fits on several lines \\ % a shorter text & a shorter text % \end{NiceTabular} % \end{Verbatim} % % \begin{center} % \begin{NiceTabular}[width=9cm]{X[2,l]X[l]}[hvlines] % a rather long text which fits on several lines % & a rather long text which fits on several lines \\ % a shorter text & a shorter text % \end{NiceTabular} % \end{center} % % \bigskip % \section{The exterior rows and columns} % % The options |first-row|, |last-row|, |first-col| and |last-col| allow the % composition of exterior rows and columns in the environments of % \pkg{nicematrix}. It's particularly interesting for the (methematical) % matrices. % \label{exterior} % % A potential ``first row'' (exterior) has the number $0$ (and not $1$). Idem % for the potential ``first column''. % % \begin{Verbatim} % $\begin{pNiceMatrix}[~emphase#first-row,last-row,first-col,last-col@,nullify-dots] % & C_1 & \Cdots & & C_4 & \\ % L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\ % \Vdots & a_{21} & a_{22} & a_{23} & a_{24} & \Vdots \\ % & a_{31} & a_{32} & a_{33} & a_{34} & \\ % L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\ % & C_1 & \Cdots & & C_4 & % \end{pNiceMatrix}$ % \end{Verbatim} % % \[\begin{pNiceMatrix}[first-row,last-row,first-col,last-col,nullify-dots] % & C_1 & \Cdots & & C_4 & \\ % L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\ % \Vdots & a_{21} & a_{22} & a_{23} & a_{24} & \Vdots \\ % & a_{31} & a_{32} & a_{33} & a_{34} & \\ % L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\ % & C_1 & \Cdots & & C_4 & % \end{pNiceMatrix}\] % % \medskip % The dotted lines have been drawn with the tools presented p.~\pageref{Cdots}. % % \bigskip % We have several remarks to do. % \begin{itemize}[beginpenalty=10000] % \item For the environments with an explicit preamble (i.e. |{NiceTabular}|, % |{NiceArray}| and its variants), no letter must be given in that preamble for % the potential first column and the potential last column: they will % automatically (and necessarily) be of type |r| for the first column and |l| % for the last one.\footnote{The users wishing exteriors columns with another % type of alignment should consider the command |\SubMatrix| available in the % |\CodeAfter| (cf.~p.~\pageref{sub-matrix}).} % \item One may wonder how \pkg{nicematrix} determines the number of rows and % columns which are needed for the composition of the ``last row'' and ``last % column''. % \begin{itemize} % \item For the environments with explicit preamble, like |{NiceTabular}| and % |{pNiceArray}|, the number of columns can obviously be computed from the % preamble. % % \item When the option |light-syntax| (cf. p. \pageref{light-syntax}) is used, % \pkg{nicematrix} has, in any case, to load the whole body of the environment % (and that's why it's not possible to put verbatim material in the array with % the option |light-syntax|). The analysis of this whole body gives the number % of rows (but not the number of columns). % % \item In the other cases, \pkg{nicematrix} compute the number of rows and % columns during the first compilation and write the result in the |aux| file % for the next run. % % \textsl{However, it's possible to provide the number of the last row and the % number of the last column as values of the options |last-row| and |last-col|, % tending to an acceleration of the whole compilation of the document.} That's % what we will do throughout the rest of the document. % \end{itemize} % \end{itemize} % % \bigskip % It's possible to control the appearance of these rows and columns with options % |code-for-first-row|, |code-for-last-row|, |code-for-first-col| and % |code-for-last-col|. These options specify tokens that will be inserted before % each cell of the corresponding row or column. % % % \begin{Verbatim} % \NiceMatrixOptions{~emphase#code-for-first-row@ = \color{red}, % ~emphase#code-for-first-col@ = \color{blue}, % ~emphase#code-for-last-row@ = \color{green}, % ~emphase#code-for-last-col@ = \color{magenta}} % $\begin{pNiceArray}{cc|cc}[first-row,last-row=5,first-col,last-col,nullify-dots] % & C_1 & \Cdots & & C_4 & \\ % L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\ % \Vdots & a_{21} & a_{22} & a_{23} & a_{24} & \Vdots \\ % \hline % & a_{31} & a_{32} & a_{33} & a_{34} & \\ % L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\ % & C_1 & \Cdots & & C_4 & % \end{pNiceArray}$ % \end{Verbatim} % % \begin{scope} % \NiceMatrixOptions{code-for-first-row = \color{red}, % code-for-first-col = \color{blue}, % code-for-last-row = \color{green}, % code-for-last-col = \color{magenta}} % \begin{displaymath} % \begin{pNiceArray}{cc|cc}[first-row,last-row=5,first-col,last-col,nullify-dots] % & C_1 & \multicolumn1c{\Cdots} & & C_4 & \\ % L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\ % \Vdots & a_{21} & a_{22} & a_{23} & a_{24} & \Vdots \\ % \hline % & a_{31} & a_{32} & a_{33} & a_{34} & \\ % L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\ % & C_1 & \multicolumn1c{\Cdots} & & C_4 & % \end{pNiceArray} % \end{displaymath} % \end{scope} % % % \emph{Remarks} % \begin{itemize}[beginpenalty=10000] % \item As shown in the previous example, the horizontal and vertical rules % don't extend in the exterior rows and columns. % % However, if one wishes to define new specifiers for columns in order to draw % vertical rules (for example thicker than the standard rules), he should % consider the command |\OnlyMainNiceMatrix| described on % page~\pageref{OnlyMainNiceMatrix}. % % \item A specification of color present in |code-for-first-row| also applies to % a dotted line drawn in that exterior ``first row'' (excepted if a value has % been given to |xdots/color|). Idem for the other exterior rows and columns. % % \item Logically, the potential option |columns-width| (described % p.~\pageref{width}) doesn't apply to the ``first column'' and ``last column''. % % \item For technical reasons, it's not possible to use the option of the % command |\\| after the ``first row'' or before the ``last row''. The placement % of the delimiters would be wrong. If you are looking for a workaround, % consider the command |\SubMatrix| in the |\CodeAfter| described % p.~\pageref{sub-matrix}. % \end{itemize} % % % % % % \section{The continuous dotted lines} % % \label{Cdots} % Inside the environments of the package \pkg{nicematrix}, new commands are % defined: |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, and |\Iddots|. These commands % are intended to be used in place of |\dots|, |\cdots|, |\vdots|, |\ddots| and % |\iddots|.\footnote{The command |\iddots|, defined in \pkg{nicematrix}, is a % variant of |\ddots| with dots going forward. If |mathdots| is loaded, the % version of |mathdots| is used. It corresponds to the command |\adots| of % \pkg{unicode-math}.} % \newcounter{fniddots} % \setcounter{fniddots}{\thefootnote} % % \smallskip % Each of them must be used alone in the cell of the array and it draws a dotted % line between the first non-empty cells\footnote{The precise definition of a % ``non-empty cell'' is given below (cf. p.~\pageref{empty-cells}).} on both % sides of the current cell. Of course, for |\Ldots| and |\Cdots|, it's an % horizontal line; for |\Vdots|, it's a vertical line and for |\Ddots| and % |\Iddots| diagonal ones. It's possible to change the color of these lines % with the option |color|.\footnote{It's also possible to change the color of % all these dotted lines with the option |xdots/color| (\textsl{xdots} to % remind that it works for |\Cdots|, |\Ldots|, |\Vdots|, etc.): cf. p. % \pageref{customisation}.}\par\nobreak % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix} % a_1 & \Cdots & & & a_1 \\ % \Vdots & a_2 & \Cdots & & a_2 \\ % & \Vdots & \Ddots[color=red] \\ % \\ % a_1 & a_2 & & & a_n % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix} % a_1 & \Cdots & & & a_1 \\ % \Vdots & a_2 & \Cdots & & a_2 \\ % & \Vdots & \Ddots[color=red] \\ % \\ % a_1 & a_2 & & & a_n % \end{bNiceMatrix}$ % % \interitem % In order to represent the null matrix, one can use the following % codage:\par\nobreak % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix} % 0 & \Cdots & 0 \\ % \Vdots & & \Vdots \\ % 0 & \Cdots & 0 % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix} % 0 & \Cdots & 0 \\ % \Vdots & & \Vdots \\ % 0 & \Cdots & 0 % \end{bNiceMatrix}$ % % \bigskip % However, one may want a larger matrix. Usually, in such a case, the users of % LaTeX add a new row and a new column. It's possible to use the same method % with \pkg{nicematrix}:\par\nobreak % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix} % 0 & \Cdots & \Cdots & 0 \\ % \Vdots & & & \Vdots \\ % \Vdots & & & \Vdots \\ % 0 & \Cdots & \Cdots & 0 % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix} % 0 & \Cdots & \Cdots & 0 \\ % \Vdots & & & \Vdots \\ % \Vdots & & & \Vdots \\ % 0 & \Cdots & \Cdots & 0 % \end{bNiceMatrix}$ % % \bigskip % In the first column of this exemple, there are two instructions |\Vdots| but, % of course, only one dotted line is drawn. % % \bigskip % In fact, in this example, it would be possible to draw the same matrix more % easily with the following code:\par\nobreak % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix} % 0 & \Cdots & & 0 \\ % \Vdots & & & \\ % & & & \Vdots \\ % 0 & & \Cdots & 0 % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix} % 0 & \Cdots & & 0 \\ % \Vdots & & & \\ % & & & \Vdots \\ % 0 & & \Cdots & 0 % \end{bNiceMatrix}$ % % \bigskip % There are also other means to change the size of the matrix. Someone might % want to use the optional argument of the command~|\\| for the vertical % dimension and a command~|\hspace*| in a cell for the horizontal % dimension.\footnote{In \pkg{nicematrix}, one should use |\hspace*| and not % |\hspace| for such an usage because \pkg{nicematrix} loads \pkg{array}. One % may also remark that it's possible to fix the width of a column by using the % environment |{NiceArray}| (or one of its variants) with a column of type~|w| % or~|W|: see p.~\pageref{width}} % % However, a command~|\hspace*| might interfer with the construction of the % dotted lines. That's why the package \pkg{nicematrix} provides a % command~|\Hspace| which is a variant of |\hspace| transparent for the dotted % lines of \pkg{nicematrix}.\par\nobreak % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix} % 0 & \Cdots & ~emphase#\Hspace*{1cm}@ & 0 \\ % \Vdots & & & \Vdots \\~emphase#[1cm]@ % 0 & \Cdots & & 0 % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix} % 0 & \Cdots & \Hspace*{1cm} & 0 \\ % \Vdots & & & \Vdots \\[1cm] % 0 & \Cdots & & 0 % \end{bNiceMatrix}$ % % \subsection{The option nullify-dots} % % % Consider the following matrix composed classicaly with the environment % |{pmatrix}| of \pkg{amsmath}.\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $A = \begin{pmatrix} % h & i & j & k & l & m \\ % x & & & & & x % \end{pmatrix}$ % \end{BVerbatim} % $A = \begin{pmatrix} % h & i & j & k & l & m \\ % x & & & & & x % \end{pmatrix}$ % % % \bigskip % If we add |\ldots| instructions in the second row, the geometry of the % matrix is modified.\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $B = \begin{pmatrix} % h & i & j & k & l & m \\ % x & \ldots & \ldots & \ldots & \ldots & x % \end{pmatrix}$ % \end{BVerbatim} % $B = \begin{pmatrix} % h & i & j & k & l & m \\ % x & \ldots & \ldots & \ldots & \ldots & x % \end{pmatrix}$ % % \bigskip % By default, with \pkg{nicematrix}, if we replace |{pmatrix}| by % |{pNiceMatrix}| and |\ldots| by |\Ldots|, the geometry of the matrix is not % changed.\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $C = \begin{pNiceMatrix} % h & i & j & k & l & m \\ % x & \Ldots & \Ldots & \Ldots & \Ldots & x % \end{pNiceMatrix}$ % \end{BVerbatim} % $C = \begin{pNiceMatrix} % h & i & j & k & l & m \\ % x & \Ldots & \Ldots & \Ldots & \Ldots & x % \end{pNiceMatrix}$ % % \bigskip % However, one may prefer the geometry of the first matrix $A$ and would like to % have such a geometry with a dotted line in the second row. It's possible by % using the option |nullify-dots| (and only one instruction |\Ldots| is % necessary).\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $D = \begin{pNiceMatrix}[~emphase#nullify-dots@] % h & i & j & k & l & m \\ % x & \Ldots & & & & x % \end{pNiceMatrix}$ % \end{BVerbatim} % $D = \begin{pNiceMatrix}[nullify-dots] % h & i & j & k & l & m \\ % x & \Ldots & & & & x % \end{pNiceMatrix}$ % % \medskip % The option |nullify-dots| smashes the instructions |\Ldots| (and the variants) % horizontally but also vertically. % % % % \subsection{The commands \textbackslash Hdotsfor and \textbackslash Vdotsfor} % % Some people commonly use the command |\hdotsfor| of \pkg{amsmath} in order to % draw horizontal dotted lines in a matrix. In the environments of % \pkg{nicematrix}, one should use instead |\Hdotsfor| in order to draw dotted % lines similar to the other dotted lines drawn by the package \pkg{nicematrix}. % % As with the other commands of \pkg{nicematrix} (like |\Cdots|, |\Ldots|, % |\Vdots|, etc.), the dotted line drawn with |\Hdotsfor| extends until the % contents of the cells on both sides. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=7cm] % $\begin{pNiceMatrix} % 1 & 2 & 3 & 4 & 5 \\ % 1 & ~emphase#\Hdotsfor{3}@ & 5 \\ % 1 & 2 & 3 & 4 & 5 \\ % 1 & 2 & 3 & 4 & 5 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix} % 1 & 2 & 3 & 4 & 5 \\ % 1 & \Hdotsfor{3} & 5 \\ % 1 & 2 & 3 & 4 & 5 \\ % 1 & 2 & 3 & 4 & 5 % \end{pNiceMatrix}$ % % \bigskip % However, if these cells are empty, the dotted line extends only in the cells % specified by the argument of |\Hdotsfor| (by design). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=7cm] % $\begin{pNiceMatrix} % 1 & 2 & 3 & 4 & 5 \\ % & ~emphase#\Hdotsfor{3}@ \\ % 1 & 2 & 3 & 4 & 5 \\ % 1 & 2 & 3 & 4 & 5 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix} % 1 & 2 & 3 & 4 & 5 \\ % & \Hdotsfor{3} \\ % 1 & 2 & 3 & 4 & 5 \\ % 1 & 2 & 3 & 4 & 5 % \end{pNiceMatrix}$ % % \medskip % Remark: Unlike the command |\hdotsfor| of \pkg{amsmath}, the command % |\Hdotsfor| may be used even when the package \pkg{colortbl}\footnote{We % recall that when \pkg{xcolor} is loaded with the option |table|, the % package \pkg{colortbl} is loaded.} is loaded (but you might have problem if % you use |\rowcolor| on the same row as |\Hdotsfor|). % % \bigskip % The package \pkg{nicematrix} also provides a command |\Vdotsfor| similar to % |\Hdotsfor| but for the vertical dotted lines. % \bigskip % The following example uses both |\Hdotsfor| and |\Vdotsfor|: % % \begin{Verbatim}[formatcom=\small\color{gray}] % \begin{bNiceMatrix} % C[a_1,a_1] & \Cdots & C[a_1,a_n] % & \hspace*{20mm} & C[a_1,a_1^{(p)}] & \Cdots & C[a_1,a_n^{(p)}] \\ % \Vdots & \Ddots & \Vdots % & ~emphase#\Hdotsfor{1}@ & \Vdots & \Ddots & \Vdots \\ % C[a_n,a_1] & \Cdots & C[a_n,a_n] % & & C[a_n,a_1^{(p)}] & \Cdots & C[a_n,a_n^{(p)}] \\ % \rule{0pt}{15mm}\NotEmpty & ~emphase#\Vdotsfor{1}@ & & \Ddots & & ~emphase#\Vdotsfor{1}@ \\ % C[a_1^{(p)},a_1] & \Cdots & C[a_1^{(p)},a_n] % & & C[a_1^{(p)},a_1^{(p)}] & \Cdots & C[a_1^{(p)},a_n^{(p)}] \\ % \Vdots & \Ddots & \Vdots % & ~emphase#\Hdotsfor{1}@ & \Vdots & \Ddots & \Vdots \\ % C[a_n^{(p)},a_1] & \Cdots & C[a_n^{(p)},a_n] % & & C[a_n^{(p)},a_1^{(p)}] & \Cdots & C[a_n^{(p)},a_n^{(p)}] % \end{bNiceMatrix} % \end{Verbatim} % % % \[\begin{bNiceMatrix} % C[a_1,a_1] & \Cdots & C[a_1,a_n] & \hspace*{20mm} & C[a_1,a_1^{(p)}] & \Cdots & C[a_1,a_n^{(p)}] \\ % \Vdots & \Ddots & \Vdots & \Hdotsfor{1} & \Vdots & \Ddots & \Vdots \\ % C[a_n,a_1] & \Cdots & C[a_n,a_n] & & C[a_n,a_1^{(p)}] & \Cdots & C[a_n,a_n^{(p)}] \\ % \rule{0pt}{15mm}\NotEmpty & \Vdotsfor{1} & & \Ddots & & \Vdotsfor{1} \\ % C[a_1^{(p)},a_1] & \Cdots & C[a_1^{(p)},a_n] & & C[a_1^{(p)},a_1^{(p)}] & \Cdots & C[a_1^{(p)},a_n^{(p)}] \\ % \Vdots & \Ddots & \Vdots & \Hdotsfor{1} & \Vdots & \Ddots & \Vdots \\ % C[a_n^{(p)},a_1] & \Cdots & C[a_n^{(p)},a_n] & & C[a_n^{(p)},a_1^{(p)}] & \Cdots & C[a_n^{(p)},a_n^{(p)}] % \end{bNiceMatrix}\] % % % % % \subsection{How to generate the continuous dotted lines transparently} % % Imagine you have a document with a great number of mathematical matrices with % ellipsis. You may wish to use the dotted lines of \pkg{nicematrix} without % having to modify the code of each matrix. It's possible with the keys. % |renew-dots| and |renew-matrix|.\footnote{The options |renew-dots|, % |renew-matrix| can be fixed with the command % |\NiceMatrixOptions| like the other options. However, they can also be fixed % as options of the command |\usepackage|. There is also a key |transparent| % which is an alias for the conjonction of |renew-dots| and |renew-matrix| but it % must be considered as obsolete.} % % \smallskip % % \begin{itemize} % \item The option |renew-dots|\par\nobreak % % With this option, the commands |\ldots|, |\cdots|, |\vdots|, |\ddots|, % |\iddots|\footnotemark[\thefniddots] and |\hdotsfor| are redefined within the % environments provided by \pkg{nicematrix} and behave like |\Ldots|, |\Cdots|, % |\Vdots|, |\Ddots|, |\Iddots| and |\Hdotsfor|; the command |\dots| % (``automatic dots'' of |amsmath|) is also redefined to behave like |\Ldots|. % % \item The option |renew-matrix|\par\nobreak % % With this option, the environment |{matrix}| is redefined and behave like % |{NiceMatrix}|, and so on for the five variants. % \end{itemize} % % \bigskip % Therefore, with the keys |renew-dots| and |renew-matrix|, a classical code % gives directly the ouput of \pkg{nicematrix}.\par\nobreak % % \bigskip % \begin{scope} % \NiceMatrixOptions{renew-dots,renew-matrix} % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % ~emphase#\NiceMatrixOptions{renew-dots,renew-matrix}@ % \begin{pmatrix} % 1 & \cdots & \cdots & 1 \\ % 0 & \ddots & & \vdots \\ % \vdots & \ddots & \ddots & \vdots \\ % 0 & \cdots & 0 & 1 % \end{pmatrix} % \end{BVerbatim} % $\begin{pmatrix} % 1 & \cdots & \cdots & 1 \\ % 0 & \ddots & & \vdots \\ % \vdots & \ddots & \ddots & \vdots \\ % 0 & \cdots & 0 & 1 % \end{pmatrix}$ % \end{scope} % % \subsection{The labels of the dotted lines} % % The commands |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, |\Iddots| and |\Hdotsfor| % (and the command |\line| in the |\CodeAfter| which is described % p.~\pageref{line-in-code-after}) accept two optional arguments specified % by the tokens |_| and |^| for labels positionned below and above the line. The % arguments are composed in math mode with |\scriptstyle|. % % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $\begin{bNiceMatrix} % 1 & \hspace*{1cm} & 0 \\[8mm] % & ~emphase#\Ddots^{n \text{ times}}@ & \\ % 0 & & 1 % \end{bNiceMatrix}$ % \end{BVerbatim} % $\begin{bNiceMatrix} % 1 & \hspace*{1cm} & 0 \\[8mm] % & \Ddots^{n \text{ times}} & \\ % 0 & & 1 % \end{bNiceMatrix}$ % % \subsection{Customisation of the dotted lines} % % \label{customisation} % The dotted lines drawn by |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, |\Iddots| % and |\Hdotsfor| (and by the command |\line| in the |\CodeAfter| which is described % p.~\pageref{line-in-code-after}) may be customized by three options (specified % between square brackets after the command): % \begin{itemize} % \item |color|; % \item |shorten|; % \item |line-style|. % \end{itemize} % % These options may also be fixed with |\NiceMatrixOptions|, as options of % |\CodeAfter| or at the level of a given environment but, in those cases, they % must be prefixed by |xdots|, and, thus have for names: % \begin{itemize} % \item |xdots/color|; % \item |xdots/shorten|; % \item |xdots/line-style|. % \end{itemize} % % For the clarity of the explanations, we will use those names. % % \bigskip % \textbf{The option xdots/color}\par\nobreak % % \smallskip % The option |xdots/color| fixes the color or the dotted line. However, one should % remark that the dotted lines drawn in the exterior rows and columns have a % special treatment: cf. p.~\pageref{exterior}. % % \bigskip % \textbf{The option xdots/shorten}\par\nobreak % % \smallskip % The option |xdots/shorten| fixes the margin of both extremities of the line. % The name is derived from the options ``|shorten >|'' and ``|shorten <|'' of % Tikz but one should notice that \pkg{nicematrix} only provides % |xdots/shorten|. The initial value of this parameter is 0.3~em (it is % recommanded to use a unit of length dependent of the current font). % % \bigskip % \textbf{The option xdots/line-style}\par\nobreak % % \smallskip % It should be pointed that, by default, the lines drawn by Tikz with the % parameter |dotted| are composed of square dots (and not rounded % ones).\footnote{The first reason of this behaviour is that the \textsc{pdf} % format includes a description for dashed lines. The lines specified with this % descriptor are displayed very efficiently by the \textsc{pdf} readers. It's % easy, starting from these dashed lines, % to create a line composed by square dots whereas a line of rounded dots needs % a specification of each dot in the \textsc{pdf} file.} % % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % \tikz \draw [dotted] (0,0) -- (5,0) ; % \end{BVerbatim} % \tikz \draw [dotted] (0,0) -- (5,0) ; % % \medskip % In order to provide lines with rounded dots in the style of those provided by % |\ldots| (at least with the \emph{Computer Modern} fonts), the package % \pkg{nicematrix} embeds its own system to draw a dotted line (and this system % uses \textsc{pgf} and not Tikz). This style is called |standard| and that's % the initial value of the parameter |xdots/line-style|. % % However (when Tikz is loaded) it's possible to use for |xdots/line-style| any style % provided by Tikz, that is to say any sequence of options provided by Tikz for % the Tizk pathes (with the exception of ``|color|'', ``|shorten >|'' and % ``|shorten <|''). % % \medskip % Here is for example a tridiagonal matrix with the style |loosely dotted|:\par\nobreak % % \medskip % \begin{BVerbatim}[baseline=c] % $\begin{pNiceMatrix}[nullify-dots,~emphase#xdots/line-style=loosely dotted@] % a & b & 0 & & \Cdots & 0 \\ % b & a & b & \Ddots & & \Vdots \\ % 0 & b & a & \Ddots & & \\ % & \Ddots & \Ddots & \Ddots & & 0 \\ % \Vdots & & & & & b \\ % 0 & \Cdots & & 0 & b & a % \end{pNiceMatrix}$ % \end{BVerbatim} % % % \[\begin{pNiceMatrix}[nullify-dots,xdots/line-style=loosely dotted] % a & b & 0 & & \Cdots & 0 \\ % b & a & b & \Ddots & & \Vdots \\ % 0 & b & a & \Ddots & & \\ % & \Ddots & \Ddots & \Ddots & & 0 \\ % \Vdots & & & & & b \\ % 0 & \Cdots & & 0 & b & a % \end{pNiceMatrix}\] % % % \subsection{The dotted lines and the rules} % % \label{dotted-and-rules} % % The dotted lines determine virtual blocks which have the same behaviour % regarding the rules (the rules specified by the specifier \verb+|+ in the % preamble, by the command |\Hline| and by the keys |hlines|, |vlines|, % |hvlines| and |hvlines-except-borders| are not drawn within the % blocks).\footnote{On the other side, the command |\line| in the % |\CodeAfter| (cf.~p.~\pageref{line-in-code-after}) does \emph{not} create % block.} % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] % $\begin{bNiceMatrix}[margin,~emphase#hvlines@] % \Block{3-3}<\LARGE>{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % 0 & \Cdots& 0 & 0 % \end{bNiceMatrix}$ % \end{BVerbatim} % $\begin{bNiceMatrix}[margin,hvlines] % \Block{3-3}<\LARGE>{A} & & & 0 \\ % & \hspace*{1cm} & & \Vdots \\ % & & & 0 \\ % 0 & \Cdots& 0 & 0 % \end{bNiceMatrix}$ % % % % \section{The \textbackslash CodeAfter} % % \label{code-after} % The option |code-after| may be used to give some code that will be executed % \emph{after} the construction of the matrix.\footnote{There is also a key % |code-before| described p.~\pageref{code-before}.} % % \medskip % For the legibility of the code, an alternative syntax is provided: it's % possible to give the instructions of the |code-after| at the end of the % environment, after the keyword |\CodeAfter|. Although |\CodeAfter| is a % keyword, it takes in an optional argument (between square brackets). The keys % accepted form a subset of the keys of the command |\WithArrowsOptions|. % % % \medskip % The experienced users may, for instance, use the PGF/Tikz nodes created by % \pkg{nicematrix} in the |\CodeAfter|. These nodes are described further % beginning on p.~\pageref{PGF-nodes}. % % \medskip % Moreover, two special commands are available in the |\CodeAfter|: |line| and % |\SubMatrix|. % % \subsection{The command \textbackslash line in the \textbackslash CodeAfter} % % \label{line-in-code-after} % The command |\line| draws directly dotted lines between nodes. It takes in two % arguments for the two cells to link, both of the form $i$-$j$ where is the % number of the row and $j$ is the number of the column. The options available % for the customisation of the dotted lines created by |\Cdots|, |\Vdots|, etc. % are also available for this command (cf. p.~\pageref{customisation}). % % \bigskip % This command may be used, for example, to draw a dotted line between two % adjacent cells. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % \NiceMatrixOptions{xdots/shorten = 0.6 em} % \begin{pNiceMatrix} % I & 0 & \Cdots &0 \\ % 0 & I & \Ddots &\Vdots\\ % \Vdots &\Ddots & I &0 \\ % 0 &\Cdots & 0 &I % ~emphase#\CodeAfter \line{2-2}{3-3}@ % \end{pNiceMatrix} % \end{BVerbatim} % \begin{scope} % \NiceMatrixOptions{xdots/shorten = 0.6 em} % $\begin{pNiceMatrix} % I & 0 & \Cdots &0 \\ % 0 & I & \Ddots &\Vdots\\ % \Vdots &\Ddots & I &0 \\ % 0 &\Cdots & 0 &I % \CodeAfter \line{2-2}{3-3} % \end{pNiceMatrix}$ % \end{scope} % % \bigskip % It can also be used to draw a diagonal line not parallel to the other diagonal % lines (by default, the dotted lines drawn by |\Ddots| are ``parallelized'': % cf.~p.~\pageref{parallelization}). % % \medskip % \begin{BVerbatim} % \begin{bNiceMatrix} % 1 & \Cdots & & 1 & 2 & \Cdots & 2 \\ % 0 & \Ddots & & \Vdots & \Vdots & \hspace*{2.5cm} & \Vdots \\ % \Vdots & \Ddots & & & & & \\ % 0 & \Cdots & 0 & 1 & 2 & \Cdots & 2 % ~emphase#\CodeAfter \line[shorten=6pt]{1-5}{4-7}@ % \end{bNiceMatrix} % \end{BVerbatim} % \[\begin{bNiceMatrix} % 1 & \Cdots & & 1 & 2 & \Cdots & 2 \\ % 0 & \Ddots & & \Vdots & \Vdots & \hspace*{2.5cm} & \Vdots \\ % \Vdots & \Ddots & & & & & \\ % 0 & \Cdots & 0 & 1 & 2 & \Cdots & 2 % \CodeAfter \line[shorten=6pt]{1-5}{4-7} % \end{bNiceMatrix}\] % % % % \subsection{The command \textbackslash SubMatrix in the \textbackslash CodeAfter} % % \label{sub-matrix} % % The command |\SubMatrix| provides a way to put delimiters on a portion % of the array considered as a submatrix. The command |\SubMatrix| takes in five % arguments: % \begin{itemize} % \item the first argument is the left delimiter, which may be any extensible delimiter % provided by LaTeX : |(|, |[|, |\{|, |\langle|, |\lgroup|, |\lfloor|, etc. but also % the null delimiter |.|; % \item the second argument is the upper-left corner of the submatrix with the % syntax $i$|-|$j$ where $i$ the number of row and $j$ the number of column; % \item the third argument is the lower-right corner with the same syntax; % \item the fourth argument is the right delimiter; % \item the last argument, which is optional, is a list of key-value % pairs.\footnote{There is no optional argument between square brackets in first % position because a square bracket just after |\SubMatrix| must be interpreted % as the first (mandatory) argument of the command |\SubMatrix|: that bracket is % the left delimiter of the sub-matrix to construct (eg.: % |\SubMatrix[{2-2}{4-7}]|).} % \end{itemize} % % One should remark that the command |\SubMatrix| draws the delimiters after the % construction of the array: no space is inserted by the command |\SubMatrix| % itself. That's why, in the following example, we have used the key |margin| % and you have added by hand some space between the third and fourth column with % |@{\hspace{1.5em}}| in the preamble of the array. % % \medskip % \begin{scope} % \hfuzz=15cm % \fvset{commandchars=\~\#\+}% % \begin{BVerbatim}[boxwidth=11cm,baseline=c] % \[\begin{NiceArray}{ccc~emphase#@{\hspace{1.5em}}+c}[cell-space-limits=2pt,~emphase#margin+] % 1 & 1 & 1 & x \\ % \dfrac{1}{4} & \dfrac{1}{2} & \dfrac{1}{4} & y \\ % 1 & 2 & 3 & z % \CodeAfter % ~emphase#\SubMatrix({1-1}{3-3})+ % ~emphase#\SubMatrix({1-4}{3-4})+ % \end{NiceArray}\] % \end{BVerbatim} % \end{scope} % $\begin{NiceArray}{ccc@{\hspace{1.5em}}c}[cell-space-limits=2pt,margin] % 1 & 1 & 1 & x \\ % \dfrac{1}{4} & \dfrac{1}{2} & \dfrac{1}{4} & y \\ % 1 & 2 & 3 & z % \CodeAfter % \SubMatrix({1-1}{3-3}) % \SubMatrix({1-4}{3-4}) % \end{NiceArray}$ % % \bigskip % \colorbox{yellow!50}{\bfseries New 5.18}\enskip In fact, the command % |\SubMatrix| also takes in two optional arguments specified by the % traditional symbols |^| and |_| for material in superscript and subscript. % % \medskip % \begin{scope} % \hfuzz=15cm % \begin{BVerbatim}[boxwidth=11cm,baseline=c] % $\begin{bNiceMatrix}[right-margin=1em] % 1 & 1 & 1 \\ % 1 & a & b \\ % 1 & c & d % \CodeAfter % ~emphase#\SubMatrix[{2-2}{3-3}]^{T}@ % \end{bNiceMatrix}$ % \end{BVerbatim} % $\begin{bNiceMatrix}[right-margin=1em] % 1 & 1 & 1 \\ % 1 & a & b \\ % 1 & c & d % \CodeAfter % \SubMatrix[{2-2}{3-3}]^{T} % \end{bNiceMatrix}$ % \end{scope} % % % \bigskip % The options of the command |\SubMatrix| are as follows: % \begin{itemize} % \item |left-xshift| and |right-xshift| shift horizontally the delimiters (there % exists also the key |xshift| which fixes both parameters); % \item |extra-height| adds a quantity to the total height of the delimiters % (height |\ht| + depth |\dp|); % \item |delimiters/color| fixes the color of the delimiters (also % available in |\NiceMatrixOptions|, in the environments with delimiters and as % option of the keyword |\CodeAfter|); % \item |slim| is a boolean key: when that key is in force, the horizontal % position of the delimiters is computed by using only the contents of the cells % of the submatrix whereas, in the general case, the position is computed by % taking into account the cells of the whole columns implied in the submatrix % (see example below). ; % \item |vlines| contents a list of numbers of vertical rules that will be drawn in % the sub-matrix (if this key is used without value, all the vertical rules of % the sub-matrix are drawn); % \item |hlines| is similar to |vlines| but for the horizontal rules; % \item |hvlines|, which must be used without value, draws all the vertical and % horizontal rules. % \end{itemize} % One should remark that these keys add their rules after the construction of % the main matrix: no space is added between the rows and the columns of the % array for theses rules. % % \bigskip % All these keys are also available in |\NiceMatrixOptions|, at the level of the % environments of \pkg{nicematrix} or as option of the command |\CodeAfter| with % the prefix |sub-matrix| which means that their names are therefore % |sub-matrix/left-xshift|, |sub-matrix/right-xshift|, |sub-matrix/xshift|, etc. % % \bigskip % \begin{scope} % \hfuzz=12cm % \fvset{commandchars=\~\#\!}% % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % $\begin{NiceArray}{cc@{\hspace{5mm}}l}[cell-space-limits=2pt] % & & \frac12 \\ % & & \frac14 \\[1mm] % a & b & \frac12a+\frac14b \\ % c & d & \frac12c+\frac14d \\ % \CodeAfter % \SubMatrix({1-3}{2-3}) % \SubMatrix({3-1}{4-2}) % \SubMatrix({3-3}{4-3}) % \end{NiceArray}$ % \end{BVerbatim} % \end{scope} % $\begin{NiceArray}{cc@{\hspace{5mm}}l}[cell-space-limits=2pt] % & & \frac12 \\ % & & \frac14 \\[1mm] % a & b & \frac12a+\frac14b \\ % c & d & \frac12c+\frac14d \\ % \CodeAfter % \SubMatrix({1-3}{2-3}) % \SubMatrix({3-1}{4-2}) % \SubMatrix({3-3}{4-3}) % \end{NiceArray}$ % % \medskip % Here is the same example with the key |slim| used for one of the submatrices. % % \medskip % \begin{scope} % \hfuzz=12cm % \fvset{commandchars=\~\#\!}% % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % $\begin{NiceArray}{cc@{\hspace{5mm}}l}[cell-space-limits=2pt] % & & \frac12 \\ % & & \frac14 \\[1mm] % a & b & \frac12a+\frac14b \\ % c & d & \frac12c+\frac14d \\ % \CodeAfter % \SubMatrix({1-3}{2-3})[~emphase#slim!] % \SubMatrix({3-1}{4-2}) % \SubMatrix({3-3}{4-3}) % \end{NiceArray}$ % \end{BVerbatim} % \end{scope} % $\begin{NiceArray}{cc@{\hspace{5mm}}l}[cell-space-limits=2pt] % & & \frac12 \\ % & & \frac14 \\[1mm] % a & b & \frac12a+\frac14b \\ % c & d & \frac12c+\frac14d \\ % \CodeAfter % \SubMatrix({1-3}{2-3})[slim] % \SubMatrix({3-1}{4-2}) % \SubMatrix({3-3}{4-3}) % \end{NiceArray}$ % % % \bigskip % There is also a key |name| which gives a name to the submatrix created by % |\SubMatrix|. That name is used to create PGF/Tikz nodes: cf % p.~\pageref{node-sub-matrix}. % % % \bigskip % It's also possible to specify some delimiters\footnote{Those delimiters are % |(|, |[|, |\{| and the closing ones. Of course, it's also % possible to put \verb+|+ and \verb+||+ in the preamble of the environement.} % by placing them in the preamble of the environment (for the environments with % a preamble: |{NiceArray}|, |{pNiceArray}|, etc.). This syntax is inspired by % the extension \pkg{blkarray}. % % When there are two successive delimiters (necessarily a closing one following by % an opening one for another submatrix), a space equal to |\enskip| is % automatically inserted. % % \medskip % \begin{BVerbatim} % $\begin{pNiceArray}{~emphase#(c)(c)(c)@} % a_{11} & a_{12} & a_{13} \\ % a_{21} & \displaystyle \int_0^1\dfrac{1}{x^2+1}\,dx & a_{23} \\ % a_{31} & a_{32} & a_{33} % \end{pNiceArray}$ % \end{BVerbatim} % % \[\begin{pNiceArray}{(c)(c)(c)} % a_{11} & a_{12} & a_{13} \\ % a_{21} & \displaystyle \int_0^1\dfrac{1}{x^2+1}\,dx & a_{23} \\ % a_{31} & a_{32} & a_{33} % \end{pNiceArray}\] % % \section{The notes in the tabulars} % % \label{s:notes} % % \subsection{The footnotes} % % \smallskip % The package \pkg{nicematrix} allows, by using \pkg{footnote} or % \pkg{footnotehyper}, the extraction of the notes inserted by |\footnote| in % the environments of \pkg{nicematrix} and their composition in the footpage % with the other notes of the document. % % \smallskip % % \smallskip % If \pkg{nicematrix} is loaded with the option |footnote| (with % |\usepackage[footnote]{nicematrix}| or with |\PassOptionsToPackage|), the % package \pkg{footnote} is loaded (if it is not yet loaded) and it is used to % extract the footnotes. % % \smallskip % If \pkg{nicematrix} is loaded with the option |footnotehyper|, the package % \pkg{footnotehyper} is loaded (if it is not yet loaded) ant it is used to % extract footnotes. % % \smallskip % Caution: The packages \pkg{footnote} and \pkg{footnotehyper} are incompatible. % The package \pkg{footnotehyper} is the successor of the package \pkg{footnote} % and should be used preferently. The package \pkg{footnote} has some drawbacks, % in particular: it must be loaded after the package \pkg{xcolor} and it is not % perfectly compatible with \pkg{hyperref}. % % % \subsection{The notes of tabular} % % The package \pkg{nicematrix} also provides a command |\tabularnote| which gives % the ability to specify notes that will be composed at the end of the array % with a width of line equal to the width of the array (excepted the potential % exterior columns). With no surprise, that command is available only in the % environments without delimiters, that is to say |{NiceTabular}|, |{NiceArray}| % and |{NiceMatrix}|. % % In fact, this command is available only if the extension \pkg{enumitem} has % been loaded (before or after \pkg{nicematrix}). Indeed, the notes are composed % at the end of the array with a type of list provided by the package % \pkg{enumitem}. % % \begin{scope} % \fvset{commandchars=\~\#\!} % \begin{Verbatim} % \begin{NiceTabular}{@{}llr@{}} % \toprule \RowStyle{\bfseries} % Last name & First name & Birth day \\ % \midrule % Achard\tabularnote{~emphase#Achard is an old family of the Poitou.!} % & Jacques & 5 juin 1962 \\ % Lefebvre\tabularnote{~emphase#The name Lefebvre is an alteration of the name Lefebure.!} % & Mathilde & 23 mai 1988 \\ % Vanesse & Stephany & 30 octobre 1994 \\ % Dupont & Chantal & 15 janvier 1998 \\ % \bottomrule % \end{NiceTabular} % \end{Verbatim} % \end{scope} % % \begin{center} % \begin{NiceTabular}{@{}llr@{}} % \toprule \RowStyle{\bfseries} % Last name & First name & Birth day \\ % \midrule % Achard\tabularnote{Achard is an old family of the Poitou.} % & Jacques & June 5, 2005 \\ % Lefebvre\tabularnote{The name Lefebvre is an alteration of the name Lefebure.} % & Mathilde & January 23, 1975 \\ % Vanesse & Stephany & October 30, 1994 \\ % Dupont & Chantal & January 15, 1998 \\ % \bottomrule % \end{NiceTabular} % \end{center} % % % \bigskip % \begin{itemize} % \item If you have several successive commands |\tabularnote{...}| \emph{with no % space at all between them}, the labels of the corresponding notes are composed % together, separated by commas (this is similar to the option |multiple| of % \pkg{footmisc} for the footnotes). % % \item If a command |\tabularnote{...}| is exactly at the end of a cell (with % no space at all after), the label of the note is composed in an overlapping % position (towards the right). This structure may provide a better alignment of % the cells of a given column. % % \item If the key |notes/para| is used, the notes are composed at the end of % the array in a single paragraph (as with the key |para| of \pkg{threeparttable}). % % \item There is a key |tabularnote| which provides a way to insert some text in % the zone of the notes before the numbered tabular notes. % % \item If the package \pkg{booktabs} has been loaded (before or after % \pkg{nicematrix}), the key |notes/bottomrule| draws a |\bottomrule| of % \pkg{booktabs} \emph{after} the notes. % % \item The command |\tabularnote| may be used \emph{before} % the environment of \pkg{nicematrix}. Thus, it's possible to use it on the % title inserted by |\caption| in an environment |{table}| of LaTeX. % % \item It's possible to create a reference to a tabular note created by |\tabularnote| % (with the usual command |\label| used after the |\tabularnote|). % \end{itemize} % % % For an illustration of some of those remarks, see table % \ref{t:tabularnote}, p.~\pageref{t:tabularnote}. This table has been composed % with the following code. % % \begin{center} % \fvset{commandchars=\~\#\!} % \begin{Verbatim}[formatcom=\small\color{gray}] % \begin{table} % \setlength{\belowcaptionskip}{1ex} % \centering % \caption{Use of \texttt{\textbackslash tabularnote}~emphase#\tabularnote{It's possible! % ~emphase#to put a note in the caption.}}! % \label{t:tabularnote} % \begin{NiceTabular}{@{}llc@{} % [~emphase#notes/bottomrule!, tabularnote = Some text before the notes.] % \toprule % Last name & First name & Length of life \\ % \midrule % Churchill & Wiston & 91\\ % Nightingale~emphase#\tabularnote{Considered as the first nurse of! % ~emphase#history.}\tabularnote{Nicknamed ``the Lady with the Lamp''.}! % & Florence & 90 \\ % Schoelcher & Victor & 89~emphase#\tabularnote{The label of the note is overlapping.}!\\ % Touchet & Marie & 89 \\ % Wallis & John & 87 \\ % \bottomrule % \end{NiceTabular} % \end{table} % \end{Verbatim} % \end{center} % % % \begin{table}[hb] % \setlength{\belowcaptionskip}{1ex} % \centering % \caption{Use of \texttt{\textbackslash tabularnote}\tabularnote{It's possible % to put a note in the caption.}} % \label{t:tabularnote} % \begin{NiceTabular}{@{}llc@{}}[notes/bottomrule, % tabularnote = Some text before the notes.] % \toprule % Last name & First name & Length of life \\ % \midrule % Churchill & Wiston & 91\\ % Nightingale\tabularnote{Considered as the first nurse of % history.}\tabularnote{Nicknamed ``the Lady with the Lamp''.} % & Florence & 90 \\ % Schoelcher & Victor & 89\tabularnote{The label of the note is overlapping.}\\ % Touchet & Marie & 89 \\ % Wallis & John & 87 \\ % \bottomrule % \end{NiceTabular} % \end{table} % % %\subsection{Customisation of the tabular notes} % % % The tabular notes can be customized with a set of keys available in % |\NiceMatrixOptions|. The name of these keys is prefixed by |notes|. % \begin{itemize} % \item |notes/para| % \item |notes/bottomrule| % \item |notes/style| % \item |notes/label-in-tabular| % \item |notes/label-in-list| % \item |notes/enumitem-keys| % \item |notes/enumitem-keys-para| % \item |notes/code-before| % \end{itemize} % For sake of commodity, it is also possible to set these keys in % |\NiceMatrixOptions| via a key |notes| which takes in as value a list of % pairs \textsl{key=value} where the name of the keys need no longer be % prefixed by |notes|: % \begin{center} % \begin{BVerbatim}[formatcom = \small \color{gray}] % \NiceMatrixOptions % { % notes = % { % bottomrule , % style = ... , % label-in-tabular = ... , % enumitem-keys = % { % labelsep = ... , % align = ... , % ... % } % } % } % \end{BVerbatim} % \end{center} % % % \bigskip % We detail these keys. % % \begin{itemize}[itemsep=\medskipamount] % \item The key |notes/para| requires the composition of the notes (at the end of % the tabular) in a single paragraph. % % Initial value: |false| % % That key is also available within a given environment. % % \item The key |notes/bottomrule| adds a |\bottomrule| of \pkg{booktabs} % \emph{after} the notes. Of course, that rule is drawn only if there is really % notes in the tabular. The package \pkg{booktabs} must have been loaded (before % or after the package \pkg{nicematrix}). If it is not, an error is raised. % % Initial value: |false| % % That key is also available within a given environment. % % \item The key |notes/style| is a command whose argument is specified by |#1| % and which gives the style of numerotation of the notes. That style will be % used by |\ref| when referencing a tabular note marked with a command |\label|. % The labels formatted by that style are used, separated by commas, when the user % puts several consecutive commands |\tabularnote|. The marker |#1| is meant to % be the name of a LaTeX counter. % % Initial value: |\textit{\alph{#1}}| % % Another possible value should be a mere |\arabic{#1}| % % \item The key |notes/label-in-tabular| is a command whose argument is % specified by |#1| which is used when formatting the label of a note in the % tabular. Internally, this number of note has already been formatted by % |notes/style| before sent to that command. % % Initial value: |\textsuperscript{#1}| % % In French, it's a tradition of putting a small space before the label of note. % That tuning could be acheived by the following code: % % % \begin{Verbatim} % \NiceMatrixOptions{notes/label-in-tabular = \,\textsuperscript{~#1}} % \end{Verbatim} % % % \item The key |notes/label-in-list| is a command whose argument is specified % by |#1| which is used when formatting the label in the list of notes at the % end of the tabular. Internally, this number of note has already been formatted by % |notes/style| before sent to that command. % % Initial value: |\textsuperscript{#1}| % % In French, the labels of notes are not composed in upper position when % composing the notes. Such behaviour could be acheived by: % \begin{Verbatim} % \NiceMatrixOptions{notes/label-in-list = ~#1.\nobreak\hspace{0.25em}} % \end{Verbatim} % The command |\nobreak| is for the event that the option |para| is used. % % % \item The notes are composed at the end of the tabular by using internally a % style of list of \pkg{enumitem}. % % The key |notes/enumitem-keys| specifies a list of pairs % \textsl{key=value} (following the specifications of \pkg{enumitem}) to % customize that type of list. % % Initial value:\quad |noitemsep , leftmargin = * , align = left , labelsep = 0pt| % % This initial value contains the specification |align = left| which requires a % composition of the label leftwards in the box affected to that label. % With that tuning, the notes are composed flush left, which is pleasant when % composing tabulars in the spirit of \pkg{booktabs} (see for example the % table \ref{t:tabularnote}, p.~\pageref{t:tabularnote}). % % % \item The key |notes/enumitem-keys-para| is similar to the previous one but % corresponds to the type of list used when the option |para| is in force. Of % course, when the option |para| is used, a list of type |inline| (as called by % \pkg{enumitem}) is used and the pairs \textsl{key=value} should correspond to % such a list of type |inline|. % % Initial value:\quad |afterlabel = \nobreak, itemjoin = \quad| % % % \item The key |notes/code-before| is a token list inserted by \pkg{nicematrix} % just before the composition of the notes at the end of the tabular. % % Initial value: \textsl{empty} % % For example, if one wishes to compose all the notes in gray and |\footnotesize|, % he should use that key: % \begin{Verbatim} % \NiceMatrixOptions{notes/code-before = \footnotesize \color{gray}} % \end{Verbatim} % It's also possible to add |\raggedright| or |\RaggedRight| in that key (|\RaggedRight| % is a command of \pkg{ragged2e}). % \end{itemize} % % % % \bigskip % For an example of customisation of the tabular notes, see p.~\pageref{ex:notes}. % % % \subsection{Use of \{NiceTabular\} with threeparttable} % % % If you wish to use the environment |{NiceTabular}|, |{NiceTabular*}| % |{NiceTabularX}|in an environment |{threeparttable}| of the eponymous package, % you have to patch the environment |{threeparttable}| with the following code % (with a version of LaTeX at least 2020/10/01). % \begin{Verbatim}[commandchars=\~\#\!] % \makeatletter % \AddToHook{env/threeparttable/begin} % {\TPT@hookin{NiceTabular}\TPT@hookin{NiceTabular*}\TPT@hookin{NiceTabularX}} % \makeatother % \end{Verbatim} % % % % \section{Other features} % % \subsection{Use of the column type S of siunitx} % % If the package \pkg{siunitx} is loaded (before or after \pkg{nicematrix}), % it's possible to use the |S| column type of \pkg{siunitx} in the environments % of \pkg{nicematrix}. The implementation doesn't use explicitly any private % macro of \pkg{siunitx}. % % % \medskip % \begin{BVerbatim}[baseline = c, boxwidth = 10.5cm] % $\begin{pNiceArray}{~emphase#S@cWc{1cm}c}[nullify-dots,first-row] % {C_1} & \Cdots & & C_n \\ % 2.3 & 0 & \Cdots & 0 \\ % 12.4 & \Vdots & & \Vdots \\ % 1.45 \\ % 7.2 & 0 & \Cdots & 0 % \end{pNiceArray}$ % \end{BVerbatim} % $\begin{pNiceArray}{ScWc{1cm}c}[nullify-dots,first-row] % {C_1} & \Cdots & & C_n \\ % 2.3 & 0 & \Cdots & 0 \\ % 12.4 & \Vdots & & \Vdots \\ % 1.45 \\ % 7.2 & 0 & \Cdots & 0 % \end{pNiceArray}$ % % \medskip % On the other hand, the |d| columns of the package \pkg{dcolumn} are not % supported by \pkg{nicematrix}. % % % \subsection{Alignment option in \{NiceMatrix\}} % % \label{key-R} % % The environments without preamble (|{NiceMatrix}|, |{pNiceMatrix}|, % |{bNiceMatrix}|, etc.) provide two options |l| and |r| which generate all the % columns aligned leftwards (or rightwards). % % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $\begin{bNiceMatrix}[r] % \cos x & - \sin x \\ % \sin x & \cos x % \end{bNiceMatrix}$ % \end{BVerbatim} % $\begin{bNiceMatrix}[r] % \cos x & - \sin x \\ % \sin x & \cos x % \end{bNiceMatrix}$ % % % \subsection{The command \textbackslash rotate} % % \label{rotate} % % The package \pkg{nicematrix} provides a command |\rotate|. When used in the % beginning of a cell, this command composes the contents of the cell after a % rotation of 90° in the direct sens. % % In the following command, we use that command in the % |code-for-first-row|.\footnote{It can also be used in |\RowStyle| % (cf.~p.~\pageref{RowStyle}.} % %\bigskip % %\begin{BVerbatim}[baseline=c,boxwidth=12cm] % \NiceMatrixOptions% % {code-for-first-row = \scriptstyle ~emphase#\rotate@ \text{image of }, % code-for-last-col = \scriptstyle } % $A = \begin{pNiceMatrix}[first-row,last-col=4] % e_1 & e_2 & e_3 \\ % 1 & 2 & 3 & e_1 \\ % 4 & 5 & 6 & e_2 \\ % 7 & 8 & 9 & e_3 % \end{pNiceMatrix}$ % \end{BVerbatim} % \begin{varwidth}{10cm} % \NiceMatrixOptions% % {code-for-first-row = \scriptstyle\rotate \text{image of }, % code-for-last-col = \scriptstyle } % $ A = \begin{pNiceMatrix}[first-row,last-col=4] % e_1 & e_2 & e_3 \\ % 1 & 2 & 3 & e_1 \\ % 4 & 5 & 6 & e_2 \\ % 7 & 8 & 9 & e_3 % \end{pNiceMatrix}$ % \end{varwidth} % % \bigskip % If the command |\rotate| is used in the ``last row'' (exterior to the matrix), % the corresponding elements are aligned upwards as shown below. % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=12cm] % \NiceMatrixOptions% % {code-for-last-row = \scriptstyle ~emphase#\rotate@ , % code-for-last-col = \scriptstyle } % $A = \begin{pNiceMatrix}[last-row=4,last-col=4] % 1 & 2 & 3 & e_1 \\ % 4 & 5 & 6 & e_2 \\ % 7 & 8 & 9 & e_3 \\ % \text{image of } e_1 & e_2 & e_3 % \end{pNiceMatrix}$ % \end{BVerbatim} % \begin{varwidth}{10cm} % \NiceMatrixOptions% % {code-for-last-row = \scriptstyle\rotate , % code-for-last-col = \scriptstyle }% % $A = \begin{pNiceMatrix}[last-row=4,last-col=4] % 1 & 2 & 3 & e_1 \\ % 4 & 5 & 6 & e_2 \\ % 7 & 8 & 9 & e_3 \\ % \text{image of } e_1 & e_2 & e_3 % \end{pNiceMatrix}$ % \end{varwidth} % % % % \subsection{The option small} % % \label{small} % % With the option |small|, the environments of the package \pkg{nicematrix} % are composed in a way similar to the environment |{smallmatrix}| of the % package \pkg{amsmath} (and the environments |{psmallmatrix}|, % |{bsmallmatrix}|, etc. of the package \pkg{mathtools}). % % \bigskip % \begin{Verbatim} % $\begin{bNiceArray}{cccc|c}[~emphase#small@, % last-col, % code-for-last-col = \scriptscriptstyle, % columns-width = 3mm ] % 1 & -2 & 3 & 4 & 5 \\ % 0 & 3 & 2 & 1 & 2 & L_2 \gets 2 L_1 - L_2 \\ % 0 & 1 & 1 & 2 & 3 & L_3 \gets L_1 + L_3 % \end{bNiceArray}$ % \end{Verbatim} % % % \[\begin{bNiceArray}{cccc|c}[small, last-col, % code-for-last-col = \scriptscriptstyle, % columns-width=3mm] % 1 & -2 & 3 & 4 & 5 \\ % 0 & 3 & 2 & 1 & 2 & L_2 \gets 2 L_1 - L_2 \\ % 0 & 1 & 1 & 2 & 3 & L_3 \gets L_1 + L_3 % \end{bNiceArray}\] % % % % \bigskip % One should note that the environment |{NiceMatrix}| with the option |small| is % not composed \emph{exactly} as the environment |{smallmatrix}|. Indeed, all % the environments of \pkg{nicematrix} are constructed upon |{array}| (of the % package \pkg{array}) whereas the environment |{smallmatrix}| is constructed % directly with an |\halign| of TeX. % % \medskip % In fact, the option |small| corresponds to the following tuning: % \begin{itemize} % \item the cells of the array are composed with |\scriptstyle|; % \item |\arraystretch| is set to $0.47$; % \item |\arraycolsep| is set to $1.45$~pt; % \item the characteristics of the dotted lines are also modified. % \end{itemize} % % \subsection{The counters iRow and jCol} % % In the cells of the array, it's possible to use the LaTeX counters |iRow| and % |jCol| which represent the number of the current row and the number of the % current column\footnote{We recall that the exterior ``first row'' (if it % exists) has the number~$0$ and that the exterior ``first column'' (if it % exists) has also the number~$0$.}. Of course, the user must not change the % value of these counters which are used internally by \pkg{nicematrix}. % % In the |\CodeBefore| (cf. p. \pageref{code-before}) and in the |\CodeAfter| % (cf. p. \pageref{code-after}), |iRow| represents the total number of rows % (excepted the potential exterior rows) and |jCol| represents the total number % of columns (excepted the potential exterior columns). % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] % $\begin{pNiceMatrix}% don't forget the % % [first-row, % first-col, % code-for-first-row = \mathbf{~emphase#\alph{jCol}@} , % code-for-first-col = \mathbf{~emphase#\arabic{iRow}@} ] % & & & & \\ % & 1 & 2 & 3 & 4 \\ % & 5 & 6 & 7 & 8 \\ % & 9 & 10 & 11 & 12 % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix}[first-row, % first-col, % code-for-first-row = \mathbf{\alph{jCol}} , % code-for-first-col = \mathbf{\arabic{iRow}} ] % & & & & \\ % & 1 & 2 & 3 & 4 \\ % & 5 & 6 & 7 & 8 \\ % & 9 & 10 & 11 & 12 % \end{pNiceMatrix}$ % % \medskip % If LaTeX counters called |iRow| and |jCol| are defined in the document by % packages other than \pkg{nicematrix} (or by the final user), they are shadowed % in the environments of \pkg{nicematrix}. % % \bigskip % The package \pkg{nicematrix} also provides commands in order to compose % automatically matrices from a general pattern. These commands are % |\AutoNiceMatrix|, |\pAutoNiceMatrix|, |\bAutoNiceMatrix|, |\vAutoNiceMatrix|, % |\VAutoNiceMatrix| and |\BAutoNiceMatrix|. % % These commands take in two mandatory arguments. The first is the format of the % matrix, with the syntax $n$-$p$ where $n$ is the number of rows and $p$ the % number of columns. The second argument is the pattern (it's a list of tokens % which are inserted in each cell of the constructed matrix). % % \medskip % \begin{Verbatim} % $C = ~emphase#\pAutoNiceMatrix@{3-3}{C_{\arabic{iRow},\arabic{jCol}}}$ % \end{Verbatim} % % % \[C = \pAutoNiceMatrix{3-3}{C_{\arabic{iRow},\arabic{jCol}}}\] % % % \subsection{The option light-syntax} % % \label{light-syntax} % The option |light-syntax| (inpired by the package \pkg{spalign}) allows the % user to compose the arrays with a lighter syntax, which gives a better % legibility of the TeX source. % % When this option is used, one should use the semicolon for the end of a row % and spaces or tabulations to separate the columns. However, as usual in the % TeX world, the spaces after a control sequence are discarded and the elements % between curly braces are considered as a whole. % % % \medskip % \begin{scope} % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % $\begin{bNiceMatrix}[~emphase#light-syntax@,first-row,first-col] % {} a b ; % a 2\cos a {\cos a + \cos b} ; % b \cos a+\cos b { 2 \cos b } % \end{bNiceMatrix}$ % \end{BVerbatim} % \end{scope} % $\begin{bNiceMatrix}[light-syntax,first-row,first-col] % {} a b ; % a 2\cos a {\cos a + \cos b} ; % b \cos a+\cos b { 2 \cos b } % \end{bNiceMatrix}$ % % \medskip % It's possible to change the character used to mark the end of rows with the % option |end-of-row|. As said before, the initial value is a semicolon. % % \medskip % When the option |light-syntax| is used, it is not possible to put verbatim % material (for example with the command |\verb|) in the cells of the % array.\footnote{The reason is that, when the option |light-syntax| is used, % the whole content of the environment is loaded as a TeX argument to be % analyzed. The environment doesn't behave in that case as a standard % environment of LaTeX which only put TeX commands before and after the content.} % % % \subsection{Color of the delimiters} % % For the environements with delimiters (|{pNiceArray}|, |{pNiceMatrix}|, etc.), % it's possible to change the color of the delimiters with the key % |delimiters/color|. % % \medskip % \begin{BVerbatim}[boxwidth=12cm,baseline=c] % $\begin{bNiceMatrix}[delimiters/color=red] % 1 & 2 \\ % 3 & 4 % \end{bNiceMatrix}$ % \end{BVerbatim} % $\begin{bNiceMatrix}[delimiters/color=red] % 1 & 2 \\ % 3 & 4 % \end{bNiceMatrix}$ % % \medskip % This colour alos applies to the delimiters drawn by the command |\SubMatrix| % (cf.~p.~\pageref{sub-matrix}). % % \subsection{The environment \{NiceArrayWithDelims\}} % % In fact, the environment |{pNiceArray}| and its variants are based upon a % more general environment, called |{NiceArrayWithDelims}|. The first two % mandatory arguments of this environment are the left and right delimiters used % in the construction of the matrix. It's possible to use % |{NiceArrayWithDelims}| if we want to use atypical or asymetrical delimiters. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % $\begin{~emphase#NiceArrayWithDelims@} % {\downarrow}{\uparrow}{ccc}[margin] % 1 & 2 & 3 \\ % 4 & 5 & 6 \\ % 7 & 8 & 9 % \end{~emphase#NiceArrayWithDelims@}$ % \end{BVerbatim} % $\begin{NiceArrayWithDelims} % {\downarrow}{\uparrow}{ccc}[margin] % 1 & 2 & 3 \\ % 4 & 5 & 6 \\ % 7 & 8 & 9 % \end{NiceArrayWithDelims}$ % % % % \section{Use of Tikz with nicematrix} % % \label{name}\label{PGF-nodes} % % \subsection{The nodes corresponding to the contents of the cells} % % The package \pkg{nicematrix} creates a PGF/Tikz node for each (non-empty) cell % of the considered array. These nodes are used to draw the dotted lines between % the cells of the matrix (inter alia). % % % \smallskip % \textbf{Caution} : By default, no node is created in a empty cell. % % \smallskip % However, it's possible to impose the creation of a node with the command % |\NotEmpty|. \footnote{One should note that, with that command, the cell is % considered as non-empty, which has consequencies for the continuous dotted % lines (cf. p.~\pageref{Cdots}) and the computation of the ``corners'' % (cf.~p.~\pageref{corners}).} % % \medskip % The nodes of a document must have distinct names. That's why the names of the % nodes created by \pkg{nicematrix} contains the number of the current % environment. Indeed, the environments of \pkg{nicematrix} are numbered by a % internal global counter. % % \smallskip % In the environment with the number $n$, the node of the row $i$ and % column~$j$ has for name |nm-|$n$|-|$i$|-|$j$. % % \smallskip % The command |\NiceMatrixLastEnv| provides the number of the last environment % of \pkg{nicematrix} (for LaTeX, it's a ``fully expandable'' command and not a % counter). % % \smallskip % However, it's advisable to use instead the key |name|. This key gives a name % to the current environment. When the environment has a name, the nodes are % accessible with the name ``\textsl{name}-$i$-$j$'' where \textsl{name} is the % name given to the array and $i$ and $j$ the numbers of row and column. It's % possible to use these nodes with \textsc{pgf} but the final user will % probably prefer to use Tikz (which is a convenient layer upon \textsc{pgf}). % However, one should remind that \pkg{nicematrix} doesn't load Tikz by default. % In the following examples, we assume that Tikz has been loaded. % % \bigskip % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % $\begin{pNiceMatrix}[name=~emphase#mymatrix@] % 1 & 2 & 3 \\ % 4 & 5 & 6 \\ % 7 & 8 & 9 % \end{pNiceMatrix}$ % \tikz[remember picture,overlay] % \draw ~emphase#(mymatrix-2-2)@ circle (2mm) ; % \end{BVerbatim} % $\begin{pNiceMatrix}[name=mymatrix] % 1 & 2 & 3 \\ % 4 & 5 & 6 \\ % 7 & 8 & 9 % \end{pNiceMatrix}$ % \tikz[remember picture,overlay] % \draw (mymatrix-2-2) circle (2mm) ; % % \medskip % Don't forget the options |remember picture| and |overlay|. % % \bigskip % In the |\CodeAfter|, the things are easier : one must refer to the nodes with % the form $i$-$j$ (we don't have to indicate the environment which is of % course the current environment). % % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % $\begin{pNiceMatrix} % 1 & 2 & 3 \\ % 4 & 5 & 6 \\ % 7 & 8 & 9 % \CodeAfter % \tikz \draw ~emphase#(2-2)@ circle (2mm) ; % \end{pNiceMatrix}$ % \end{BVerbatim} % $\begin{pNiceMatrix} % 1 & 2 & 3 \\ % 4 & 5 & 6 \\ % 7 & 8 & 9 % \CodeAfter % \tikz \draw (2-2) circle (2mm) ; % \end{pNiceMatrix}$ % % % \bigskip % In the following example, we have underlined all the nodes of the matrix (we % explain below the technic used : cf. p. \pageref{highlight}). % % % \[\begin{pNiceMatrix} % \CodeBefore [create-cell-nodes] % \begin{tikzpicture}% % [every node/.style = { inner sep = 0 pt , fill = red!15 }] % \node [fit = (1-1)] {} ; % \node [fit = (1-3)] {} ; % \node [fit = (2-2)] {} ; % \node [fit = (3-1)] {} ; % \node [fit = (3-3)] {} ; % \node [fit = (1-2)] {} ; % \node [fit = (2-1)] {} ; % \node [fit = (2-3)] {} ; % \node [fit = (3-2)] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c \\ % a & a & a + b \\ % a & a & a % \end{pNiceMatrix}\] % % % \subsection{The ``medium nodes'' and the ``large nodes''} % % In fact, the package \pkg{nicematrix} can create ``extra nodes'': the ``medium % nodes'' and the ``large nodes''. The first ones % are created with the option |create-medium-nodes| and the second ones with the % option |create-large-nodes|.\footnote{There is also an option % |create-extra-nodes| which is an alias for the conjonction of % |create-medium-nodes| and |create-large-nodes|.} % % \medskip % These nodes are not used by \pkg{nicematrix} by default, and that's why they % are not created by default. % % \medskip % The names of the ``medium nodes'' are constructed by adding the suffix % ``|-medium|'' to the names of the ``normal nodes''. In the following example, % we have underlined the ``medium nodes''. We consider that this example is % self-explanatory. % \[\begin{pNiceMatrix}[create-medium-nodes] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % [every node/.style = {fill = red!15, inner sep = 0 pt}, % name suffix = -medium] % \node [fit = (1-1)] {} ; % \node [fit = (1-2)] {} ; % \node [fit = (1-3)] {} ; % \node [fit = (2-1)] {} ; % \node [fit = (2-2)] {} ; % \node [fit = (2-3)] {} ; % \node [fit = (3-1)] {} ; % \node [fit = (3-2)] {} ; % \node [fit = (3-3)] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c \\ % a & a & a + b \\ % a & a & a % \end{pNiceMatrix}\] % % % \medskip % The names of the ``large nodes'' are constructed by adding the suffix % ``|-large|'' to the names of the ``normal nodes''. In the following example, % we have underlined the ``large nodes''. We consider that this example is % self-explanatory.\footnote{There is no ``large nodes'' created in the exterior % rows and columns (for these rows and columns, cf. p.~\pageref{exterior}).} % \[\begin{pNiceMatrix}[create-large-nodes] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % [every node/.style = { inner sep = 0 pt} , % name suffix = -large] % \node [fit = (1-1),fill = red!15] {} ; % \node [fit = (1-3),fill = red!15] {} ; % \node [fit = (2-2),fill = red!15] {} ; % \node [fit = (3-1),fill = red!15] {} ; % \node [fit = (3-3),fill = red!15] {} ; % \node [fit = (1-2),fill = blue!15] {} ; % \node [fit = (2-1),fill = blue!15] {} ; % \node [fit = (2-3),fill = blue!15] {} ; % \node [fit = (3-2),fill = blue!15] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c \\ % a & a & a + b \\ % a & a & a % \end{pNiceMatrix}\] % % % % \medskip % The ``large nodes'' of the first column and last column may appear too small % for some usage. That's why it's possible to use the options |left-margin| and % |right-margin| to add space on both sides of the array and also space in the % ``large nodes'' of the first column and last column. In the following example, % we have used the options |left-margin| and |right-margin|.\footnote{The % options |left-margin| and |right-margin| take dimensions as values but, if no % value is given, the default value is used, which is |\arraycolsep| (by % default: 5~pt). There is also an option |margin| to fix both |left-margin| and % |right-margin| to the same value.} % \[\begin{pNiceMatrix}[create-large-nodes,left-margin,right-margin] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % [every node/.style = {inner sep = 0 pt}, % name suffix = -large] % \node [fit = (1-1),fill = red!15] {} ; % \node [fit = (1-3),fill = red!15] {} ; % \node [fit = (2-2),fill = red!15] {} ; % \node [fit = (3-1),fill = red!15] {} ; % \node [fit = (3-3),fill = red!15] {} ; % \node [fit = (1-2),fill = blue!15] {} ; % \node [fit = (2-1),fill = blue!15] {} ; % \node [fit = (2-3),fill = blue!15] {} ; % \node [fit = (3-2),fill = blue!15] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c \\ % a & a & a + b \\ % a & a & a % \end{pNiceMatrix}\] % % % \medskip % It's also possible to add more space on both side of the array with the % options |extra-left-margin| and |extra-right-margin|. These margins are not % incorporated in the ``large nodes''. It's possible to fix both values with the % option |extra-margin| and, in the following example, we use |extra-margin| % with the value $3$~pt. % \[\begin{pNiceMatrix}[create-large-nodes,left-margin,right-margin,extra-right-margin=3pt,extra-left-margin=3pt] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % [every node/.style = {inner sep = 0 pt}, % name suffix = -large] % \node [fit = (1-1),fill = red!15] {} ; % \node [fit = (1-3),fill = red!15] {} ; % \node [fit = (2-2),fill = red!15] {} ; % \node [fit = (3-1),fill = red!15] {} ; % \node [fit = (3-3),fill = red!15] {} ; % \node [fit = (1-2),fill = blue!15] {} ; % \node [fit = (2-1),fill = blue!15] {} ; % \node [fit = (2-3),fill = blue!15] {} ; % \node [fit = (3-2),fill = blue!15] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c \\ % a & a & a + b \\ % a & a & a % \end{pNiceMatrix}\] % % % % \bigskip % \textbf{Be careful} : These nodes are reconstructed from the contents of the % contents cells of the array. Usually, they do not correspond to the cells % delimited by the rules (if we consider that these rules are drawn). % % \bigskip % \begin{minipage}[c]{7.6cm} % Here is an array composed with the following code: % % \medskip % \begin{BVerbatim} % \large % \begin{NiceTabular}{wl{2cm}ll}[hvlines] % fraise & amande & abricot \\ % prune & pêche & poire \\[1ex] % noix & noisette & brugnon % \end{NiceTabular} % \end{BVerbatim} % \end{minipage} % \hspace{0.9cm} % \begin{scope} % \large % \begin{NiceTabular}[c]{wl{2cm}ll}[hvlines] % fraise & amande & abricot \\ % prune & pêche & poire \\[1ex] % noix & noisette & brugnon % \end{NiceTabular} % \end{scope} % % \vspace{1cm} % \begin{minipage}[c]{7cm} % Here, we have colored all the cells of the array with |\chessboardcolors|. % \end{minipage} % \hspace{1.5cm} % \begin{scope} % \large % \begin{NiceTabular}[c]{wl{2cm}ll}[hvlines,code-before = \chessboardcolors{red!15}{blue!15}] % fraise & amande & abricot \\ % prune & pêche & poire \\[1ex] % noix & noisette & brugnon % \end{NiceTabular} % \end{scope} % % % \vspace{1cm} % \begin{minipage}[c]{7cm} % Here are the ``large nodes'' of this array (without use of |margin| % nor |extra-margin|). % \end{minipage} % \hspace{1.5cm} % \begin{scope} % \large % \begin{NiceTabular}[c]{w{l}{2cm}ll}[hvlines,create-large-nodes] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % [every node/.style = {inner sep = 0 pt}, % name suffix = -large] % \node [fit = (1-1),fill = red!15] {} ; % \node [fit = (1-3),fill = red!15] {} ; % \node [fit = (2-2),fill = red!15] {} ; % \node [fit = (3-1),fill = red!15] {} ; % \node [fit = (3-3),fill = red!15] {} ; % \node [fit = (1-2),fill = blue!15] {} ; % \node [fit = (2-1),fill = blue!15] {} ; % \node [fit = (2-3),fill = blue!15] {} ; % \node [fit = (3-2),fill = blue!15] {} ; % \end{tikzpicture} % \Body % fraise & amande & abricot \\ % prune & pêche & poire \\[1ex] % noix & noisette & brugnon % \end{NiceTabular} % \end{scope} % % % \vspace{1cm} % The nodes we have described are not available by default in the |\CodeBefore| % (described p.~\pageref{code-before}).\par\nobreak % % It's possible to have these nodes available in the |\CodeBefore| by using the % key |create-cell-nodes| of the keyword |\CodeBefore| (in that case, the nodes % are created first before the construction of the array by using informations % written on the |aux| file and created a second time during the contruction of % the array itself). % % \subsection{The nodes which indicate the position of the rules} % % \label{nodes-i} % The package \pkg{nicematrix} creates a PGF/Tikz node merely called $i$ (with % the classical prefix) at the intersection of the horizontal rule of number~$i$ % and the vertical rule of number~$i$ (more specifically the potential position % of those rules because maybe there are not actually drawn). The last node has % also an alias called |last|. There is also a node called $i$|.5| midway % between the node $i$ and the node $i+1$. % % These nodes are available in the |\CodeBefore| and the |\CodeAfter|. % % \begin{center} % \begin{NiceTabular}{ccc}[hvlines,rules/width=1pt,rules/color=gray] % & tulipe & lys \\ % arum & & violette mauve \\ % muguet & dahlia % \CodeAfter % \tiny % \begin{tikzpicture} % \foreach \i in {1,1.5,2,2.5,3,3.5,4} % { % \fill [red] (\i) circle (0.5mm) ; % \node [red,above right] at (\i) {\i} ; % } % \end{tikzpicture} % \end{NiceTabular} % \end{center} % % \bigskip % If we use Tikz (we remind that \pkg{nicematrix} does not load Tikz by default, % by only \textsc{pgf}, which is a sub-layer of Tikz), we can access, in the % |\CodeAfter| but also in the |\CodeBefore|, to the intersection of the % (potential) horizontal rule~$i$ and the (potential) vertical rule~$j$ with the % syntax |(|$i$\verb+-|+$j$|)|. % % \medskip % \begin{Verbatim} % \begin{NiceMatrix} % \CodeBefore % ~emphase#\tikz \draw [fill=red!15] (7-|4) |- (8-|5) |- (9-|6) |- cycle ;@ % \Body % 1 \\ % 1 & 1 \\ % 1 & 2 & 1 \\ % 1 & 3 & 3 & 1 \\ % 1 & 4 & 6 & 4 & 1 \\ % 1 & 5 & 10 & 10 & 5 & 1 \\ % 1 & 6 & 15 & 20 & 15 & 6 & 1 \\ % 1 & 7 & 21 & 35 & 35 & 21 & 7 & 1 \\ % 1 & 8 & 28 & 56 & 70 & 56 & 28 & 8 & 1 % \end{NiceMatrix} % \end{Verbatim} % % % \[\begin{NiceMatrix} % \CodeBefore % \tikz \draw [fill=red!15] (7-|4) |- (8-|5) |- (9-|6) |- cycle ; % \Body % 1 \\ % 1 & 1 \\ % 1 & 2 & 1 \\ % 1 & 3 & 3 & 1 \\ % 1 & 4 & 6 & 4 & 1 \\ % 1 & 5 & 10 & 10 & 5 & 1 \\ % 1 & 6 & 15 & 20 & 15 & 6 & 1 \\ % 1 & 7 & 21 & 35 & 35 & 21 & 7 & 1 \\ % 1 & 8 & 28 & 56 & 70 & 56 & 28 & 8 & 1 % \end{NiceMatrix}\] % % % \bigskip % The nodes of the form $i$|.5| may be used, for example to cross a row of a % matrix (if Tikz is loaded). % % \smallskip % \begin{BVerbatim}[boxwidth=11cm,baseline=c] % $\begin{pNiceArray}{ccc|c} % 2 & 1 & 3 & 0 \\ % 3 & 3 & 1 & 0 \\ % 3 & 3 & 1 & 0 % \CodeAfter % \tikz \draw [red] (~emphase#3.5@-|1) -- (~emphase#3.5@-|last) ; % \end{pNiceArray}$ % \end{BVerbatim} % $\begin{pNiceArray}{ccc|c} % 2 & 1 & 3 & 0 \\ % 3 & 3 & 1 & 0 \\ % 3 & 3 & 1 & 0 % \CodeAfter % \tikz \draw [red] (3.5-|1) -- (3.5-|last) ; % \end{pNiceArray}$ % % \subsection{The nodes corresponding to the command \textbackslash SubMatrix} % % \label{node-sub-matrix} % % The command |\SubMatrix| available in the |\CodeAfter| has been described % p.~\pageref{sub-matrix}. % % \smallskip % If a command |\SubMatrix| has been used with the key |name| with an expression % such as |name=|\textsl{\ttfamily MyName} three PGF/Tikz nodes are created % with the names \textsl{\ttfamily MyName}|-left|, \textsl{\ttfamily MyName} and % \textsl{\ttfamily MyName}|-right|. % % \smallskip % The nodes \textsl{\ttfamily MyName}|-left| and \textsl{\ttfamily % MyName}|-right| correspond to the delimiters left and right and the node % \textsl{\ttfamily MyName} correspond to the submatrix itself. % % \medskip % In the following example, we have highlighted these nodes (the submatrix itself has % been created with |\SubMatrix\{{2-2}{3-3}\}|). % % \[\begin{pNiceMatrix} % 121 & 23 & 345 & 345\\ % 45 & 346 & 863 & 444\\ % 3462 & 38458 & 34 & 294 \\ % 34 & 7 & 78 & 309 \\ % \CodeAfter % \SubMatrix\{{2-2}{3-3}\}[name=A] % \begin{tikzpicture} % [every node/.style = {blend mode = multiply, % inner sep = 0 pt}] % \node [fit = (A),fill = red!15] {} ; % \node [fit = (A-left),fill = blue!15] {} ; % \node [fit = (A-right),fill = blue!15] {} ; % \end{tikzpicture} % \end{pNiceMatrix}\] % % \section{API for the developpers} % % The package \pkg{nicematrix} provides two variables which are internal but % public\footnote{According to the LaTeX3 conventions, % each variable with name beginning with |\g_nicematrix| ou |\l_nicematrix| is % public and each variable with name beginning with |\g__nicematrix| or % |\l__nicematrix| is private.}: % \begin{itemize} % \item |\g_nicematrix_code_before_tl| ; % \item |\g_nicematrix_code_after_tl|. % \end{itemize} % % % \medskip % These variables contain the code of what we have called the ``|code-before|'' % (usually specified at the beginning of the environment with the syntax using % the keywords |\CodeBefore| and |\Body|) and the ``|code-after|'' (usually % specified at the end of the environment after the keyword |\CodeAfter|). The % developper can use them to add code from a cell of the array (the affectation % must be global, allowing to exit the cell, which is a TeX group). % % \medskip % One should remark that the use of |\g_nicematrix_code_before_tl| needs one % compilation more (because the instructions are written on the |aux| file to be % used during the next run). % % \bigskip % \emph{Example} : We want to write a command |\crossbox| to draw a cross in the % current cell. This command will take in an optional argument between square % brackets for a list of pairs \textsl{key}-\textsl{value} which will be given to % Tikz before the drawing. % % It's possible to program such command |\crossbox| as follows, explicitely % using the public variable |\g_nicematrix_code_after_tl|. % % \begin{scope} % \fvset{commandchars=\§\¤\μ} % \begin{Verbatim} % \ExplSyntaxOn % \cs_new_protected:Nn \__pantigny_crossbox:nnn % { % \tikz \draw [ #3 ] % ( #1 -| \int_eval:n { #2 + 1 } ) -- ( \int_eval:n { #1 + 1 } -| #2 ) % ( #1 -| #2 ) -- ( \int_eval:n { #1 + 1 } -| \int_eval:n { #2 + 1 } ) ; % } % % \NewDocumentCommand \crossbox { ! O { } } % { % \tl_gput_right:Nx §emphase¤\g_nicematrix_code_after_tlμ % { % \__pantigny_crossbox:nnn % { \int_use:c { c@iRow } } % { \int_use:c { c@jCol } } % { \exp_not:n { #1 } } % } % } % \ExplSyntaxOff % \end{Verbatim} % \end{scope} % % % \ExplSyntaxOn % \cs_new_protected:Nn \__pantigny_crossbox:nnn % { % \tikz \draw [ #3 ] % ( #1 -| \int_eval:n { #2 + 1 } ) -- ( \int_eval:n { #1 + 1 } -| #2 ) % ( #1 -| #2 ) -- ( \int_eval:n { #1 + 1 } -| \int_eval:n { #2 + 1 } ) ; % } % % % \NewDocumentCommand \crossbox { ! O { } } % { % \tl_gput_right:Nx \g_nicematrix_code_after_tl % { % \__pantigny_crossbox:nnn % { \int_use:c { c@iRow } } % { \int_use:c { c@jCol } } % { \exp_not:n { #1 } } % } % } % \ExplSyntaxOff % % \bigskip % Here is an example of utilisation: % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=9cm] % \begin{NiceTabular}{ccc}[hvlines] % merlan & requin & cabillaud \\ % baleine & ~emphase#\crossbox[red]@ & morue \\ % mante & raie & poule % \end{NiceTabular} % \end{BVerbatim} % \begin{NiceTabular}{ccc}[hvlines] % merlan & requin & cabillaud \\ % baleine & \crossbox[red] & morue \\ % mante & raie & poule % \end{NiceTabular} % % % % \section{Technical remarks} % % \subsection{Definition of new column types} % % \label{OnlyMainNiceMatrix} % % The package \pkg{nicematrix} provides the command |\OnlyMainNiceMatrix| % which is meant to be used in definitions of new column types. Its argument is % evaluated if and only if we are in the main part of the array, that is to say % not in a potential exterior row. % % For example, one may wish to define a new column type |?| in order to draw a % (black) heavy rule of width 1~pt. The following definition will do the % job\footnote{The command |\vrule| is a TeX (and not LaTeX) command.}: % % \begin{Verbatim} % \newcolumntype{?}{!{\OnlyMainNiceMatrix{\vrule width 1 pt}}} % \end{Verbatim} % % The heavy vertical rule won't extend in the exterior rows.\footnote{Of course, % such rule is defined by the classical technics of \pkg{nicematrix} and, for % this reason, won't cross the double rules of |\hline\hline|.} % \medskip % \begin{scope} % \newcolumntype{?}{!{\OnlyMainNiceMatrix{\vrule width 1 pt}}} % % \begin{BVerbatim}[baseline = c, boxwidth = 10.5cm] % $\begin{pNiceArray}{cc?cc}[first-row,last-row=3] % C_1 & C_2 & C_3 & C_4 \\ % a & b & c & d \\ % e & f & g & h \\ % C_1 & C_2 & C_3 & C_4 % \end{pNiceArray}$ % \end{BVerbatim} % $\begin{pNiceArray}{cc?cc}[first-row,last-row=3] % C_1 & C_2 & C_3 & C_4 \\ % a & b & c & d \\ % e & f & g & h \\ % C_1 & C_2 & C_3 & C_4 % \end{pNiceArray}$ % \end{scope} % % \medskip % This specifier |?| may be used in the standard environments |{tabular}| and % |{array}| (of the package \pkg{array}) and, in this case, the command % |\OnlyMainNiceMatrix| is no-op. % % % % \subsection{Diagonal lines} % % \label{parallelization} % By default, all the diagonal lines\footnote{We speak of the lines created by % |\Ddots| and not the lines created by a command |\line| in the |\CodeAfter|.} of a % same array are ``parallelized''. That means that the first diagonal line is % drawn and, then, the other lines are drawn parallel to the first one (by % rotation around the left-most extremity of the line). That's why the position % of the instructions |\Ddots| in the array can have a marked effect on the % final result. % % \medskip % In the following examples, the first |\Ddots| instruction is written in color: % % % \medskip % \begin{scope} % \begin{minipage}{9.5cm} % Example with parallelization (default): % \begin{Verbatim} % $A = \begin{pNiceMatrix} % 1 & \Cdots & & 1 \\ % a+b & ~emphase#\Ddots@~ & & \Vdots \\ % \Vdots & \Ddots & & \\ % a+b & \Cdots & a+b & 1 % \end{pNiceMatrix}$ % \end{Verbatim} % \end{minipage} % $A = \begin{pNiceMatrix} % 1 & \Cdots & & 1 \\ % a+b & \Ddots & & \Vdots \\ % \Vdots & \Ddots & & \\ % a+b & \Cdots & a+b & 1 % \end{pNiceMatrix}$ % % \bigskip % \NiceMatrixOptions{parallelize-diags=true}% % \begin{minipage}{9.5cm} % % \begin{Verbatim} % $A = \begin{pNiceMatrix} % 1 & \Cdots & & 1 \\ % a+b & & & \Vdots \\ % \Vdots & ~emphase#\Ddots@~ & \Ddots & \\ % a+b & \Cdots & a+b & 1 % \end{pNiceMatrix}$ % \end{Verbatim} % \end{minipage} % $A = \begin{pNiceMatrix} % 1 & \Cdots & & 1 \\ % a+b & & & \Vdots \\ % \Vdots & \Ddots & \Ddots & \\ % a+b & \Cdots & a+b & 1 % \end{pNiceMatrix}$ % % \bigskip % It's possible to turn off the parallelization with the option % |parallelize-diags| set to |false|: \par\nobreak % % \medskip % \NiceMatrixOptions{parallelize-diags=false}% % \begin{minipage}{9.5cm} % The same example without parallelization: % \end{minipage} % $A = \begin{pNiceMatrix} % 1 & \Cdots & & 1 \\ % a+b & \Ddots & & \Vdots \\ % \Vdots & \Ddots & & \\ % a+b & \Cdots & a+b & 1 % \end{pNiceMatrix}$ % % \end{scope} % % It's possible to specify the instruction |\Ddots| which will be drawn first % (and which will be used to draw the other diagonal dotted lines when the % parallelization is in force) with the key |draw-first|: |\Ddots[draw-first]|. % % \subsection{The ``empty'' cells} % % \label{empty-cells} % An instruction like |\Ldots|, |\Cdots|, etc. tries to determine the first % non-empty cell on both sides. However, an ``empty cell'' is not necessarily a % cell with no TeX content (that is to say a cell with no token between the two % ampersands~|&|). The precise rules are as follow. % % \begin{itemize} % \item An implicit cell is empty. For example, in the following matrix: % % \begin{Verbatim} % \begin{pmatrix} % a & b \\ % c \\ % \end{pmatrix} % \end{Verbatim} % % the last cell (second row and second column) is empty. % % \medskip % \item Each cell whose TeX ouput has a width equal to zero is empty. % % \medskip % \item A cell containing the command |\NotEmpty| is not empty (and a PGF/Tikz % node) is created in that cell. % % \medskip % \item A cell with a command |\Hspace| (or |\Hspace*|) is empty. This command % |\Hspace| is a command defined by the package \pkg{nicematrix} with the same % meaning as |\hspace| except that the cell where it is used is considered as % empty. This command can be used to fix the width of some columns of the matrix % without interfering with \pkg{nicematrix}. % % \medskip % \item A cell of a column of type |p|, |m| or |t| is always considered as not % emtpy. \emph{Caution} : One should not rely upon that point because it may % change if a future version of \pkg{nicematrix}. % % \end{itemize} % % % \subsection{The option exterior-arraycolsep} % % The environment |{array}| inserts an horizontal space equal to |\arraycolsep| % before and after each column. In particular, there is a space equal to % |\arraycolsep| before and after the array. This feature of the environment % |{array}| was probably not a good idea\footnote{In the documentation of % |{amsmath}|, we can read: {\itshape The extra space of |\arraycolsep| that % \pkg{array} adds on each side is a waste so we remove it [in |{matrix}|] % (perhaps we should instead remove it from array in general, but that's a % harder task).}}. The environment |{matrix}| of % \pkg{amsmath} and its variants (|{pmatrix}|, |{vmatrix}|, etc.) of % \pkg{amsmath} prefer to delete these spaces with explicit instructions % |\hskip -\arraycolsep|\footnote{And not by inserting |@{}| on both sides of the % preamble of the array. As a consequence, the length of the |\hline| is not % modified and may appear too long, in particular when using square brackets.}. % The package \pkg{nicematrix} does the same in all its environments, % |{NiceArray}| included. However, if the user wants the environment % |{NiceArray}| behaving by default like the environment |{array}| of % \pkg{array} (for example, when adapting an existing document) it's possible to % control this behaviour with the option |exterior-arraycolsep|, set by the % command |\NiceMatrixOptions|. With this option, exterior spaces of length % |\arraycolsep| will be inserted in the environments |{NiceArray}| (the other % environments of \pkg{nicematrix} are not affected). % % % % \subsection{Incompatibilities} % % The package \pkg{nicematrix} is not fully compatible with the package % \pkg{arydshln} (because this package redefines many internal of \pkg{array}). % % Anyway, in order to use \pkg{arydshln}, one must first free the letter ``|:|'' % by giving a new letter for the vertical dotted rules of \pkg{nicematrix}: % % \begin{Verbatim} % \NiceMatrixOptions{letter-for-dotted-lines=;} % \end{Verbatim} % % \bigskip % Up to now, the package \pkg{nicematrix} is not compatible with % \cls{aastex63}. If you want to use \pkg{nicematrix} with \cls{aastex63}, send % me an email and I will try to solve the incompatibilies. % % % \bigskip % The package \pkg{nicematrix} is not compatible with the class \cls{ieeeaccess} % (because that class is not compatible with PGF/Tikz). % % \section{Examples} % % \subsection{Utilisation of the key ``tikz'' of the command \textbackslash Block} %\label{tikz-key-examples} % % % \begin{Verbatim} % \ttfamily \small % \begin{NiceTabular}{X[m]X[m]X[m]}[hvlines,cell-space-limits=3pt] % \Block[~emphase#tikz={pattern=grid,pattern color=lightgray}@]{} % {pattern = grid,\\ pattern color = lightgray} % & \Block[~emphase#tikz={pattern = north west lines,pattern color=blue}@]{} % {pattern = north west lines,\\ pattern color = blue} % & \Block[~emphase#tikz={outer color = red!50, inner color=white }@]{2-1} % {outer color = red!50,\\ inner color = white} \\ % \Block[~emphase#tikz={pattern = sixpointed stars, pattern color = blue!15}@]{} % {pattern = sixpointed stars,\\ pattern color = blue!15} % & \Block[~emphase#tikz={left color = blue!50}@]{} % {left color = blue!50} \\ % \end{NiceTabular} % \end{Verbatim} % % \begin{center} % \ttfamily \small % \begin{NiceTabular}{X[m]X[m]X[m]}[hvlines,cell-space-limits=3pt] % \Block[tikz={pattern=grid,pattern color=lightgray}]{} % {pattern = grid,\\ pattern color = lightgray} % & \Block[tikz={pattern = north west lines,pattern color=blue}]{} % {pattern = north west lines,\\ pattern color = blue} % & \Block[tikz={outer color = red!50, inner color=white }]{2-1} % {outer color = red!50,\\ inner color = white} \\ % \Block[tikz={pattern = sixpointed stars, pattern color = blue!15}]{} % {pattern = sixpointed stars,\\ pattern color = blue!15} % & \Block[tikz={left color = blue!50}]{} % {left color = blue!50} \\ % \end{NiceTabular} % \end{center} % % % \subsection{Notes in the tabulars} % % \label{ex:notes} % % The tools provided by \pkg{nicematrix} for the composition of the tabular % notes have been presented in the section \ref{s:notes} p.~\pageref{s:notes}. % % \medskip % Let's consider that we wish to number the notes of a tabular with % stars.\footnote{Of course, it's realistic only when there is very few notes in % the tabular.} % % \medskip % First, we write a command |\stars| similar the well-known commands % |\arabic|, |\alph|, |\Alph|, etc. which produces a number of stars equal to % its argument \footnote{In fact: the value of its argument.} % \begin{Verbatim} % \ExplSyntaxOn % \NewDocumentCommand ~emphase#\stars@ { m } % { \prg_replicate:nn { \value { ~#1 } } { $ \star $ } } % \ExplSyntaxOff % \end{Verbatim} % % % Of course, we change the style of the labels with the key |notes/style|. % However, it would be interesting to change also some parameters in the type of % list used to compose the notes at the end of the tabular. % First, we required a composition flush right for the labels with the setting % |align=right|. % Moreover, we want the labels to be composed on a width equal to the width of % the widest label. The widest label is, of course, the label with the greatest % number of stars. We know that number: it is equal to |\value{tabularnote}| % (because |tabularnote| is the LaTeX counter used by |\tabularnote| and, % therefore, at the end of the tabular, its value is equal to the total number % of tabular notes). We use the key |widest*| of \pkg{enumitem} in order to % require a width equal to that value: |widest*=\value{tabularnote}|. % \begin{Verbatim} % \NiceMatrixOptions % { % notes = % { % ~emphase#style = \stars{~#1} , @ % ~emphase#enumitem-keys = @ % ~emphase# { @ % ~emphase# widest* = \value{tabularnote} ,@ % ~emphase# align = right @ % ~emphase# } @ % } % } % \end{Verbatim} % % % % \begin{scope} % \ExplSyntaxOn % \NewDocumentCommand \stars { m } % { \prg_replicate:nn { \value { #1 } } { $ \star $ } } % \NiceMatrixOptions % { % notes = % { % style = \stars{#1} , % enumitem-keys = % { % widest* = \value{tabularnote} , % align = right % } % } % } % \ExplSyntaxOff % \begin{Verbatim} % \begin{NiceTabular}{~@{}llr~@{}} % \toprule \RowStyle{\bfseries} % Last name & First name & Birth day \\ % \midrule % Achard\tabularnote{~emphase#Achard is an old family of the Poitou.@} % & Jacques & 5 juin 1962 \\ % Lefebvre\tabularnote{~emphase#The name Lefebvre is an alteration of the name Lefebure.@} % & Mathilde & 23 mai 1988 \\ % Vanesse & Stephany & 30 octobre 1994 \\ % Dupont & Chantal & 15 janvier 1998 \\ % \bottomrule % \end{NiceTabular} % \end{Verbatim} % % \begin{center} % \begin{NiceTabular}{@{}llr@{}} % \toprule \RowStyle{\bfseries} % Last name & First name & Birth day \\ % \midrule % Achard\tabularnote{Achard is an old family of the Poitou.} % & Jacques & June 5, 2005 \\ % Lefebvre\tabularnote{The name Lefebvre is an alteration of the name Lefebure.} % & Mathilde & January 23, 1975 \\ % Vanesse & Stephany & October 30, 1994 \\ % Dupont & Chantal & January 15, 1998 \\ % \bottomrule % \end{NiceTabular} % \end{center} % \end{scope} % % % % \subsection{Dotted lines} % % An example with the resultant of two polynoms:\par\nobreak % % \bigskip % \begin{BVerbatim} % \setlength{\extrarowheight}{1mm} % \[\begin{vNiceArray}{cccc:ccc}[columns-width=6mm] % a_0 & && &b_0 & & \\ % a_1 &\Ddots&& &b_1 &\Ddots& \\ % \Vdots&\Ddots&& &\Vdots &\Ddots&b_0 \\ % a_p & &&a_0 & & &b_1 \\ % &\Ddots&&a_1 &b_q & &\Vdots\\ % & &&\Vdots & &\Ddots& \\ % & &&a_p & & &b_q % \end{vNiceArray}\] % \end{BVerbatim} % % \bigskip % % \begin{scope} % \setlength{\extrarowheight}{1mm} % \[\begin{vNiceArray}{cccc:ccc}[columns-width=6mm] % a_0 & && &b_0 & & \\ % a_1 &\Ddots&& &b_1 &\Ddots& \\ % \Vdots&\Ddots&& &\Vdots &\Ddots&b_0 \\ % a_p & &&a_0 & & &b_1 \\ % &\Ddots&&a_1 &b_q & &\Vdots\\ % & &&\Vdots & &\Ddots& \\ % & &&a_p & & &b_q % \end{vNiceArray}\] % \end{scope} % % \vspace{2cm} % An example for a linear system:\par\nobreak % % \begin{Verbatim} % $\begin{pNiceArray}{*6c|c}[nullify-dots,last-col,code-for-last-col=\scriptstyle] % 1 & 1 & 1 &\Cdots & & 1 & 0 & \\ % 0 & 1 & 0 &\Cdots & & 0 & & L_2 \gets L_2-L_1 \\ % 0 & 0 & 1 &\Ddots & & \Vdots & & L_3 \gets L_3-L_1 \\ % & & &\Ddots & & & \Vdots & \Vdots \\ % \Vdots & & &\Ddots & & 0 & \\ % 0 & & &\Cdots & 0 & 1 & 0 & L_n \gets L_n-L_1 % \end{pNiceArray}$ % \end{Verbatim} % % % \[\begin{pNiceArray}{*6c|c}[nullify-dots,last-col,code-for-last-col=\scriptstyle] % 1 & 1 & 1 &\Cdots & & 1 & 0 & \\ % 0 & 1 & 0 &\Cdots & & 0 & & L_2 \gets L_2-L_1 \\ % 0 & 0 & 1 &\Ddots & & \Vdots & & L_3 \gets L_3-L_1 \\ % & & &\Ddots & & & \Vdots & \Vdots \\ % \Vdots & & &\Ddots & & 0 & \\ % 0 & & &\Cdots & 0 & 1 & 0 & L_n \gets L_n-L_1 % \end{pNiceArray}\] % % % % \subsection{Dotted lines which are no longer dotted} % % The option |line-style| controls the style of the lines drawn by |\Ldots|, % |\Cdots|, etc. Thus, it's possible with these commands to draw lines which are % not longer dotted. % % % \begin{Verbatim}[formatcom=\small\color{gray}] % \NiceMatrixOptions{code-for-first-row = \scriptstyle,code-for-first-col = \scriptstyle } % \setcounter{MaxMatrixCols}{12} % \newcommand{\blue}{\color{blue}} % \[\begin{pNiceMatrix}[last-row,last-col,nullify-dots,xdots/line-style={dashed,blue}] % 1& & & \Vdots & & & & \Vdots \\ % & \Ddots[line-style=standard] \\ % & & 1 \\ % \Cdots[color=blue,line-style=dashed]& & & \blue 0 & % \Cdots & & & \blue 1 & & & \Cdots & \blue \leftarrow i \\ % & & & & 1 \\ % & & &\Vdots & & \Ddots[line-style=standard] & & \Vdots \\ % & & & & & & 1 \\ % \Cdots & & & \blue 1 & \Cdots & & \Cdots & \blue 0 & & & \Cdots & \blue \leftarrow j \\ % & & & & & & & & 1 \\ % & & & & & & & & & \Ddots[line-style=standard] \\ % & & & \Vdots & & & & \Vdots & & & 1 \\ % & & & \blue \overset{\uparrow}{i} & & & & \blue \overset{\uparrow}{j} \\ % \end{pNiceMatrix}\] % \end{Verbatim} % % % \begin{scope} % \NiceMatrixOptions{code-for-first-row = \scriptstyle,code-for-first-col = \scriptstyle } % \setcounter{MaxMatrixCols}{12} % \newcommand{\blue}{\color{blue}} % \[\begin{pNiceMatrix}[last-row,last-col,nullify-dots,xdots/line-style={dashed,blue}] % 1& & & \Vdots & & & & \Vdots \\ % & \Ddots[line-style=standard] \\ % & & 1 \\ % \Cdots[color=blue,line-style=dashed]& & & \blue 0 & % \Cdots & & & \blue 1 & & & \Cdots & \blue \leftarrow i \\ % & & & & 1 \\ % & & &\Vdots & & \Ddots[line-style=standard] & & \Vdots \\ % & & & & & & 1 \\ % \Cdots & & & \blue 1 & \Cdots & & \Cdots & \blue 0 & & & \Cdots & \blue \leftarrow j \\ % & & & & & & & & 1 \\ % & & & & & & & & & \Ddots[line-style=standard] \\ % & & & \Vdots & & & & \Vdots & & & 1 \\ % & & & \blue \overset{\uparrow}{i} & & & & \blue \overset{\uparrow}{j} \\ % \end{pNiceMatrix}\] % \end{scope} % % \interitem % In fact, it's even possible to draw solid lines with the commands |\Cdots|, % |\Vdots|, etc. % % \begin{Verbatim} % \NiceMatrixOptions % {nullify-dots,code-for-first-col = \color{blue},code-for-first-col=\color{blue}} % $\begin{pNiceMatrix}[first-row,first-col] % & & \Ldots[line-style={solid,<->},shorten=0pt]^{n \text{ columns}} \\ % & 1 & 1 & 1 & \Ldots & 1 \\ % & 1 & 1 & 1 & & 1 \\ % \Vdots[line-style={solid,<->}]_{n \text{ rows}} & 1 & 1 & 1 & & 1 \\ % & 1 & 1 & 1 & & 1 \\ % & 1 & 1 & 1 & \Ldots & 1 % \end{pNiceMatrix}$ % \end{Verbatim} % % % \begin{scope} % \NiceMatrixOptions % {nullify-dots,code-for-first-col = \color{blue},code-for-first-row=\color{blue}} % \[\begin{pNiceMatrix}[first-row,first-col] % & & \Ldots[line-style={solid,<->},shorten=0pt]^{n \text{ columns}} \\ % & 1 & 1 & 1 & \Ldots & 1 \\ % & 1 & 1 & 1 & & 1 \\ % \Vdots[line-style={solid,<->}]_{n \text{ rows}} & 1 & 1 & 1 & & 1 \\ % & 1 & 1 & 1 & & 1 \\ % & 1 & 1 & 1 & \Ldots & 1 % \end{pNiceMatrix}\] % \end{scope} % % % \subsection{Stacks of matrices} % % We often need to compose mathematical matrices on top on each other (for % example for the resolution of linear systems). % % \medskip % In order to have the columns aligned one above the other, it's possible to % fix a width for all the columns. That's what is done in the following example % with the environment |{NiceMatrixBlock}| and its option |auto-columns-width|. % % \begin{Verbatim}[formatcom=\small\color{gray}] % ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@ % \NiceMatrixOptions % { % light-syntax, % last-col, code-for-last-col = \color{blue} \scriptstyle, % } % \setlength{\extrarowheight}{1mm} % % $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 3 -18 12 1 4 ; % -3 -46 29 -2 -15 ; % 9 10 -5 4 7 % \end{pNiceArray}$ % % \smallskip % $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 ; % 0 64 -41 1 19 { L_2 \gets L_1-4L_2 } ; % 0 -192 123 -3 -57 { L_3 \gets L_1+4L_3 } ; % 0 -64 41 -1 -19 { L_4 \gets 3L_1-4L_4 } ; % \end{pNiceArray}$ % % \smallskip % $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 ; % 0 64 -41 1 19 ; % 0 0 0 0 0 { L_3 \gets 3 L_2 + L_3 } % \end{pNiceArray}$ % % \smallskip % $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 0 64 -41 1 19 ; % \end{pNiceArray}$ % % ~emphase#\end{NiceMatrixBlock}@ % \end{Verbatim} % % \bigskip % \begin{NiceMatrixBlock}[auto-columns-width] % \NiceMatrixOptions % { % light-syntax, % last-col, code-for-last-col = \color{blue} \scriptstyle , % } % \setlength{\extrarowheight}{1mm} % % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 3 -18 12 1 4 ; % -3 -46 29 -2 -15 ; % 9 10 -5 4 7 % \end{pNiceArray}$ % % \smallskip % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 ; % 0 64 -41 1 19 { L_2 \gets L_1-4L_2 } ; % 0 -192 123 -3 -57 { L_3 \gets L_1+4L_3 } ; % 0 -64 41 -1 -19 { L_4 \gets 3L_1-4L_4 } ; % \end{pNiceArray}$ % % \smallskip % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 ; % 0 64 -41 1 19 ; % 0 0 0 0 0 { L_3 \gets 3 L_2 + L_3 } % \end{pNiceArray}$\par\nobreak % % \smallskip % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 0 64 -41 1 19 ; % \end{pNiceArray}$ % \end{NiceMatrixBlock} % % \bigskip % However, one can see that the last matrix is not perfectly aligned with % others. That's why, in LaTeX, the parenthesis have not exactly the same width % (smaller parenthesis are a bit slimer). % % \medskip % In order the solve that problem, it's possible to require the delimiters to be % composed with the maximal width, thanks to the boolean key % |delimiters/max-width|. % % \begin{Verbatim}[formatcom=\small\color{gray}] % ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@ % \NiceMatrixOptions % { % ~emphase#delimiters/max-width@, % light-syntax, % last-col, code-for-last-col = \color{blue}\scriptstyle, % } % \setlength{\extrarowheight}{1mm} % % $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 3 -18 12 1 4 ; % -3 -46 29 -2 -15 ; % 9 10 -5 4 7 % \end{pNiceArray}$ % % ... % ~emphase#\end{NiceMatrixBlock}@ % \end{Verbatim} % % \bigskip % \begin{NiceMatrixBlock}[auto-columns-width] % \NiceMatrixOptions % { % delimiters/max-width, % light-syntax, % last-col, code-for-last-col = \color{blue}\scriptstyle, % } % \setlength{\extrarowheight}{1mm} % % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 3 -18 12 1 4 ; % -3 -46 29 -2 -15 ; % 9 10 -5 4 7 % \end{pNiceArray}$ % % \smallskip % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 ; % 0 64 -41 1 19 { L_2 \gets L_1-4L_2 } ; % 0 -192 123 -3 -57 { L_3 \gets L_1+4L_3 } ; % 0 -64 41 -1 -19 { L_4 \gets 3L_1-4L_4 } ; % \end{pNiceArray}$ % % \smallskip % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 ; % 0 64 -41 1 19 ; % 0 0 0 0 0 { L_3 \gets 3 L_2 + L_3 } % \end{pNiceArray}$\par\nobreak % % \smallskip % \quad $\begin{pNiceArray}{rrrr|r} % 12 -8 7 5 3 {} ; % 0 64 -41 1 19 ; % \end{pNiceArray}$ % % \end{NiceMatrixBlock} % % % \interitem % If you wish an alignment of the different matrices without the same width % for all the columns, you can construct a unique array and place the % parenthesis with commands |\SubMatrix| in the |\CodeAfter|. Of course, that % array can't be broken by a page break. % % \medskip % \begin{Verbatim} % \setlength{\extrarowheight}{1mm} % \[\begin{NiceMatrix}[ r, last-col=6, code-for-last-col = \scriptstyle \color{blue} ] % 12 & -8 & 7 & 5 & 3 \\ % 3 & -18 & 12 & 1 & 4 \\ % -3 & -46 & 29 &-2 &-15 \\ % 9 & 10 &-5 &4 & 7 \\[1mm] % 12 & -8 & 7 &5 & 3 \\ % 0 & 64 &-41 & 1 & 19 & L_2 \gets L_1-4L_2 \\ % 0 & -192 &123 &-3 &-57 & L_3 \gets L_1+4L_3 \\ % 0 & -64 & 41 &-1 &-19 & L_4 \gets 3L_1-4L_4 \\[1mm] % 12 & -8 &7 &5 & 3 \\ % 0 & 64 &-41 &1 &19 \\ % 0 & 0 &0 &0 & 0 & L_3 \gets 3L_2+L_3 \\[1mm] % 12 & -8 &7 &5 & 3 \\ % 0 & 64 &-41 & 1 & 19 \\ % ~emphase#\CodeAfter [sub-matrix/vlines=4]@ % ~emphase# \SubMatrix({1-1}{4-5})@ % ~emphase# \SubMatrix({5-1}{8-5})@ % ~emphase# \SubMatrix({9-1}{11-5})@ % ~emphase# \SubMatrix({12-1}{13-5})@ % \end{NiceMatrix}\] % \end{Verbatim} % % \medskip % \begin{scope} % \setlength{\extrarowheight}{1mm} % \[\begin{NiceMatrix}[ r, last-col=6, code-for-last-col = \scriptstyle \color{blue} ] % 12 & -8 & 7 & 5 & 3 \\ % 3 & -18 & 12 & 1 & 4 \\ % -3 & -46 & 29 &-2 &-15 \\ % 9 & 10 &-5 &4 & 7 \\[1mm] % 12 & -8 & 7 &5 & 3 \\ % 0 & 64 &-41 & 1 & 19 & L_2 \gets L_1-4L_2 \\ % 0 & -192 &123 &-3 &-57 & L_3 \gets L_1+4L_3 \\ % 0 & -64 & 41 &-1 &-19 & L_4 \gets 3L_1-4L_4 \\[1mm] % 12 & -8 &7 &5 & 3 \\ % 0 & 64 &-41 &1 &19 \\ % 0 & 0 &0 &0 & 0 & L_3 \gets 3L_2+L_3 \\[1mm] % 12 & -8 &7 &5 & 3 \\ % 0 & 64 &-41 & 1 & 19 \\ % \CodeAfter [sub-matrix/vlines=4] % \SubMatrix({1-1}{4-5}) % \SubMatrix({5-1}{8-5}) % \SubMatrix({9-1}{11-5}) % \SubMatrix({12-1}{13-5}) % \end{NiceMatrix}\] % \end{scope} % % % % \subsection{How to highlight cells of a matrix} % % % \label{highlight} % % \medskip % In order to highlight a cell of a matrix, it's possible to ``draw'' that cell % with the key |draw| of the command |\Block| (this is one of the uses of a % mono-cell block\footnote{We recall that, if the first mandatory argument of % the command |\Block| is left empty, that means that the block is a mono-cell block}). % % \label{example-CodeAfter} % % % \begin{Verbatim} % $\begin{pNiceArray}{>{\strut}cccc}[margin,rules/color=blue] % ~emphase#\Block[draw]{}{a_{11}}@ & a_{12} & a_{13} & a_{14} \\ % a_{21} & \Block[draw]{}{a_{22}} & a_{23} & a_{24} \\ % a_{31} & a_{32} & \Block[draw]{}{a_{33}} & a_{34} \\ % a_{41} & a_{42} & a_{43} & \Block[draw]{}{a_{44}} \\ % \end{pNiceArray}$ % \end{Verbatim} % \[\begin{pNiceArray}{>{\strut}cccc}[margin,rules/color=blue] % \Block[draw]{}{a_{11}} & a_{12} & a_{13} & a_{14} \\ % a_{21} & \Block[draw]{}{a_{22}} & a_{23} & a_{24} \\ % a_{31} & a_{32} & \Block[draw]{}{a_{33}} & a_{34} \\ % a_{41} & a_{42} & a_{43} & \Block[draw]{}{a_{44}} \\ % \end{pNiceArray}\] % % We should remark that the rules we have drawn are drawn \emph{after} the % construction of the array and thus, they don't spread the cells of the array. % We recall that, on the other side, the commands |\hline| and |\Hline|, the % specifier ``"|"'' and the options |hlines|, |vlines|, |hvlines| and % |hvlines-except-borders| spread the cells.\footnote{For the command |\cline|, % see the remark p.~\pageref{remark-cline}.} % % % \vspace{1cm} % It's possible to color a row with |\rowcolor| in the |code-before| (or with % |\rowcolor| in the first cell of the row if the key |colortbl-like| is % used−even when \pkg{colortbl} is not loaded). % % \medskip % \begin{Verbatim} % \begin{pNiceArray}{>{\strut}cccc}[margin, extra-margin=2pt,colortbl-like] % ~emphase#\rowcolor{red!15}@A_{11} & A_{12} & A_{13} & A_{14} \\ % A_{21} & ~emphase#\rowcolor{red!15}@A_{22} & A_{23} & A_{24} \\ % A_{31} & A_{32} & ~emphase#\rowcolor{red!15}@A_{33} & A_{34} \\ % A_{41} & A_{42} & A_{43} & ~emphase#\rowcolor{red!15}@A_{44} % \end{pNiceArray} % \end{Verbatim} % % % % \[\begin{pNiceArray}{>{\strut}cccc}[margin, extra-margin=2pt,colortbl-like] % \rowcolor{red!15}A_{11} & A_{12} & A_{13} & A_{14} \\ % A_{21} & \rowcolor{red!15}A_{22} & A_{23} & A_{24} \\ % A_{31} & A_{32} & \rowcolor{red!15}A_{33} & A_{34} \\ % A_{41} & A_{42} & A_{43} & \rowcolor{red!15}A_{44} % \end{pNiceArray}\] % % \bigskip % However, it's not possible to do a fine tuning. That's why we describe now a % method to highlight a row of the matrix. We create a rectangular Tikz node % which encompasses the nodes of the second row with the Tikz library \pkg{fit}. % This Tikz node is filled after the construction of the matrix. In order to see % the text \emph{under} this node, we have to use transparency with the % |blend mode| equal to |multiply|. % % \medskip % \textbf{Caution} : Some \textsc{pdf} readers are not able to show % transparency.\footnote{In Overleaf, the ``built-in'' \textsc{pdf} viewer does % not show transparency. You can switch to the ``native'' viewer in that case.} % % % \medskip % That example and the following ones require Tikz (by default, \pkg{nicematrix} % only loads \textsc{pgf}, which is a sub-layer of Tikz) and the Tikz library % |fit|. The following lines in the preamble of your document do the job: % \begin{verbatim} % \usepackage{tikz} % \usetikzlibrary{fit} % \end{verbatim} % % \medskip % We create a rectangular Tikz node which encompasses the nodes of the second % row by using the tools of the Tikz library \pkg{fit}. Those nodes are not % available by default in the |\CodeBefore| (for efficiency). We have to require % their creation with the key |create-cell-nodes| of the keyword |\CodeBefore|. % % \tikzset{highlight/.style={rectangle, % fill=red!15, % rounded corners = 0.5 mm, % inner sep=1pt, % fit = #1}} % % \medskip % \begin{Verbatim} % \tikzset{highlight/.style={rectangle, % fill=red!15, % rounded corners = 0.5 mm, % inner sep=1pt, % fit=~#1}} % % $\begin{bNiceMatrix} % ~emphase#\CodeBefore [create-cell-nodes] @ % ~emphase# \tikz \node [highlight = (2-1) (2-3)] {} ; @ % ~emphase# \Body @ % 0 & \Cdots & 0 \\ % 1 & \Cdots & 1 \\ % 0 & \Cdots & 0 \\ % \end{bNiceMatrix}$ % \end{Verbatim} % \[\begin{bNiceMatrix} % \CodeBefore [create-cell-nodes] % \tikz \node [highlight = (2-1) (2-3)] {} ; % \Body % 0 & \Cdots & 0 \\ % 1 & \Cdots & 1 \\ % 0 & \Cdots & 0 \\ % \end{bNiceMatrix}\] % % % \vspace{1cm} % We consider now the following matrix. If we want to highlight each row of % this matrix, we can use the previous technique three times. % % \begin{Verbatim} % \[\begin{pNiceArray}{ccc}[last-col] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % ~emphase# \node [highlight = (1-1) (1-3)] {} ;@ % ~emphase# \node [highlight = (2-1) (2-3)] {} ;@ % ~emphase# \node [highlight = (3-1) (3-3)] {} ;@ % \end{tikzpicture} % \Body % a & a + b & a + b + c & L_1 \\ % a & a & a + b & L_2 \\ % a & a & a & L_3 % \end{pNiceArray}\] % \end{Verbatim} % % % \[\begin{pNiceArray}{ccc}[last-col] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} % \node [highlight = (1-1) (1-3)] {} ; % \node [highlight = (2-1) (2-3)] {} ; % \node [highlight = (3-1) (3-3)] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c & L_1 \\ % a & a & a + b & L_2 \\ % a & a & a & L_3 % \end{pNiceArray}\] % % \medskip % The result may seem disappointing. We can improve it by using the ``medium % nodes'' instead of the ``normal nodes''. % % \begin{Verbatim} % \[\begin{pNiceArray}{ccc}[last-col,create-medium-nodes] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} ~emphase#[name suffix = -medium]@ % \node [highlight = (1-1) (1-3)] {} ; % \node [highlight = (2-1) (2-3)] {} ; % \node [highlight = (3-1) (3-3)] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c & L_1 \\ % a & a & a + b & L_2 \\ % a & a & a & L_3 % \end{pNiceArray}\] % \end{Verbatim} % % %\[\begin{pNiceArray}{ccc}[last-col,create-medium-nodes] % \CodeBefore [create-cell-nodes] % \begin{tikzpicture} [name suffix = -medium] % \node [highlight = (1-1) (1-3)] {} ; % \node [highlight = (2-1) (2-3)] {} ; % \node [highlight = (3-1) (3-3)] {} ; % \end{tikzpicture} % \Body % a & a + b & a + b + c & L_1 \\ % a & a & a + b & L_2 \\ % a & a & a & L_3 % \end{pNiceArray}\] % % % \subsection{Utilisation of \textbackslash SubMatrix in the \textbackslash CodeBefore} % % In the following example, we illustrate the mathematical product of two % matrices. % % The whole figure is an environment |{NiceArray}| and the three pairs of % parenthesis have been added with |\SubMatrix| in the |\CodeBefore|. % % \tikzset{highlight/.style={rectangle, % fill=red!15, % rounded corners = 0.5 mm, % inner sep=1pt, % fit=#1}}% % \[\begin{NiceArray}{*{6}{c}@{\hspace{6mm}}*{5}{c}}[nullify-dots] % \CodeBefore [create-cell-nodes] % \SubMatrix({2-7}{6-11}) % \SubMatrix({7-2}{11-6}) % \SubMatrix({7-7}{11-11}) % \begin{tikzpicture} % \node [highlight = (9-2) (9-6)] { } ; % \node [highlight = (2-9) (6-9)] { } ; % \end{tikzpicture} % \Body % & & & & & & & & \color{blue}\scriptstyle C_j \\ % & & & & & & b_{11} & \Cdots & b_{1j} & \Cdots & b_{1n} \\ % & & & & & & \Vdots & & \Vdots & & \Vdots \\ % & & & & & & & & b_{kj} \\ % & & & & & & & & \Vdots \\ % & & & & & & b_{n1} & \Cdots & b_{nj} & \Cdots & b_{nn} \\[3mm] % & a_{11} & \Cdots & & & a_{1n} \\ % & \Vdots & & & & \Vdots & & & \Vdots \\ % \color{blue}\scriptstyle L_i % & a_{i1} & \Cdots & a_{ik} & \Cdots & a_{in} & \Cdots & & c_{ij} \\ % & \Vdots & & & & \Vdots \\ % & a_{n1} & \Cdots & & & a_{nn} \\ % \CodeAfter % \tikz \draw [gray,shorten > = 1mm, shorten < = 1mm] (9-4.north) to [bend left] (4-9.west) ; % \end{NiceArray}\] % % % \vspace{1cm} % \begin{Verbatim} % \tikzset{highlight/.style={rectangle, % fill=red!15, % rounded corners = 0.5 mm, % inner sep=1pt, % fit=~#1}} % \end{Verbatim} % % \begin{Verbatim}[formatcom = \small\color{gray}] % \[\begin{NiceArray}{*{6}{c}~LetterAt{\hspace{6mm}}*{5}{c}}[nullify-dots] % \CodeBefore [create-cell-nodes] % \SubMatrix({2-7}{6-11}) % \SubMatrix({7-2}{11-6}) % \SubMatrix({7-7}{11-11}) % \begin{tikzpicture} % \node [highlight = (9-2) (9-6)] { } ; % \node [highlight = (2-9) (6-9)] { } ; % \end{tikzpicture} % \Body % & & & & & & & & \color{blue}\scriptstyle C_j \\ % & & & & & & b_{11} & \Cdots & b_{1j} & \Cdots & b_{1n} \\ % & & & & & & \Vdots & & \Vdots & & \Vdots \\ % & & & & & & & & b_{kj} \\ % & & & & & & & & \Vdots \\ % & & & & & & b_{n1} & \Cdots & b_{nj} & \Cdots & b_{nn} \\[3mm] % & a_{11} & \Cdots & & & a_{1n} \\ % & \Vdots & & & & \Vdots & & & \Vdots \\ % \color{blue}\scriptstyle L_i % & a_{i1} & \Cdots & a_{ik} & \Cdots & a_{in} & \Cdots & & c_{ij} \\ % & \Vdots & & & & \Vdots \\ % & a_{n1} & \Cdots & & & a_{nn} \\ % \CodeAfter % \tikz \draw [gray,shorten > = 1mm, shorten < = 1mm] (9-4.north) to [bend left] (4-9.west) ; % \end{NiceArray}\] % \end{Verbatim} % % %\section{Implementation} % % By default, the package \pkg{nicematrix} doesn't patch any existing code. % % \smallskip % However, when the option |renew-dots| is used, the commands |\cdots|, % |\ldots|, |\dots|, |\vdots|, |\ddots| and |\iddots| are redefined in the % environments provided by \pkg{nicematrix} as explained previously. In the same % way, if the option |renew-matrix| is used, the environment |{matrix}| of % \pkg{amsmath} is redefined. % % \smallskip % On the other hand, the environment |{array}| is never redefined. % % \smallskip % Of course, the package \pkg{nicematrix} uses the features of the package % \pkg{array}. It tries to be independent of its implementation. Unfortunately, % it was not possible to be strictly independent. For example, the package % \pkg{nicematrix} relies upon the fact that the package |{array}| uses % |\ialign| to begin the |\halign|. % % % \bigskip % \subsection*{Declaration of the package and packages loaded} % % % The prefix |nicematrix| has been registred for this package. % % See: |http://mirrors.ctan.org/macros/latex/contrib/l3kernel/l3prefixes.pdf| % %<@@=nicematrix> % % \bigskip % First, we load \pkg{pgfcore} and the module \pkg{shapes}. We do so because % it's not possible to use |\usepgfmodule| in |\ExplSyntaxOn|. % \begin{macrocode} \RequirePackage{pgfcore} \usepgfmodule{shapes} % \end{macrocode} % % % We give the traditional declaration of a package written with the L3 % programming layer. % \begin{macrocode} \RequirePackage{l3keys2e} \ProvidesExplPackage {nicematrix} {\myfiledate} {\myfileversion} {Enhanced arrays with the help of PGF/TikZ} % \end{macrocode} % % % \bigskip % The command for the treatment of the options of |\usepackage| is at the end of % this package for technical reasons. % % \bigskip % We load some packages. The package \pkg{xparse} is still loaded for use on Overleaf. % \begin{macrocode} \RequirePackage { xparse } \RequirePackage { array } \RequirePackage { amsmath } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_error:n { \msg_error:nn { nicematrix } } \cs_new_protected:Npn \@@_error:nn { \msg_error:nnn { nicematrix } } \cs_new_protected:Npn \@@_error:nnn { \msg_error:nnnn { nicematrix } } \cs_new_protected:Npn \@@_fatal:n { \msg_fatal:nn { nicematrix } } \cs_new_protected:Npn \@@_fatal:nn { \msg_fatal:nnn { nicematrix } } \cs_new_protected:Npn \@@_msg_new:nn { \msg_new:nnn { nicematrix } } \cs_new_protected:Npn \@@_msg_new:nnn { \msg_new:nnnn { nicematrix } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_msg_redirect_name:nn { \msg_redirect_name:nnn { nicematrix } } % \end{macrocode} % % % \bigskip % \subsection*{Technical definitions} % % % \medskip % \begin{macrocode} \bool_new:N \c_@@_in_preamble_bool \bool_set_true:N \c_@@_in_preamble_bool \AtBeginDocument { \bool_set_false:N \c_@@_in_preamble_bool } % \end{macrocode} % % \begin{macrocode} \bool_new:N \c_@@_arydshln_loaded_bool \bool_new:N \c_@@_booktabs_loaded_bool \bool_new:N \c_@@_enumitem_loaded_bool \bool_new:N \c_@@_tikz_loaded_bool \AtBeginDocument { \@ifpackageloaded { arydshln } { \bool_set_true:N \c_@@_arydshln_loaded_bool } { } \@ifpackageloaded { booktabs } { \bool_set_true:N \c_@@_booktabs_loaded_bool } { } \@ifpackageloaded { enumitem } { \bool_set_true:N \c_@@_enumitem_loaded_bool } { } \@ifpackageloaded { tikz } { % \end{macrocode} % In some constructions, we will have to use a |{pgfpicture}| which \emph{must} % be replaced by a |{tikzpicture}| if Tikz is loaded. However, this switch % between |{pgfpicture}| and |{tikzpicture}| can't be done dynamically with a % conditional because, when the Tikz library |external| is loaded by the user, % the pair |\tikzpicture|-|\endtikpicture| (or % |\begin{tikzpicture}-\end{tikzpicture}|) must be statically ``visible'' (even % when externalization is not activated). % % That's why we create |\c_@@_pgfortikzpicture_tl| and % |\c_@@_endpgfortikzpicture_tl| which will be used to construct in a % |\AtBeginDocument| the correct version of some commands. % \begin{macrocode} \bool_set_true:N \c_@@_tikz_loaded_bool \tl_const:Nn \c_@@_pgfortikzpicture_tl { \exp_not:N \tikzpicture } \tl_const:Nn \c_@@_endpgfortikzpicture_tl { \exp_not:N \endtikzpicture } } { \tl_const:Nn \c_@@_pgfortikzpicture_tl { \exp_not:N \pgfpicture } \tl_const:Nn \c_@@_endpgfortikzpicture_tl { \exp_not:N \endpgfpicture } } } % \end{macrocode} % % We test whether the current class is \cls{revtex4-1} (deprecated) or % \cls{revtex4-2} because these classes redefines |\array| (of \pkg{array}) in a % way incompatible with our programmation. At the date January 2021, the current % version \cls{revtex4-2} is 4.2e (compatible with \pkg{booktabs}). % % \begin{macrocode} \bool_new:N \c_@@_revtex_bool \@ifclassloaded { revtex4-1 } { \bool_set_true:N \c_@@_revtex_bool } { } \@ifclassloaded { revtex4-2 } { \bool_set_true:N \c_@@_revtex_bool } { } % \end{macrocode} % Maybe one of the previous classes will be loaded inside another class... We % try to detect that situation. % \begin{macrocode} \cs_if_exist:NT \rvtx@ifformat@geq { \bool_set_true:N \c_@@_revtex_bool } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_generate_variant:Nn \tl_if_single_token_p:n { V } % \end{macrocode} % % \bigskip % The following regex will be used to modify the preamble of the array when the % key |colortbl-like| is used. % \begin{macrocode} \regex_const:Nn \c_@@_columncolor_regex { \c { columncolor } } % \end{macrocode} % % \bigskip % If the final user uses \pkg{nicematrix}, PGF/Tikz will write instruction % |\pgfsyspdfmark| in the |aux| file. If he changes its mind and no longer loads % \pkg{nicematrix}, an error may occur at the next compilation because of % remanent instructions |\pgfsyspdfmark| in the |aux| file. With the following % code, we try to avoid that situation. % \begin{macrocode} \cs_new_protected:Npn \@@_provide_pgfsyspdfmark: { \iow_now:Nn \@mainaux { \ExplSyntaxOn \cs_if_free:NT \pgfsyspdfmark { \cs_set_eq:NN \pgfsyspdfmark \@gobblethree } \ExplSyntaxOff } \cs_gset_eq:NN \@@_provide_pgfsyspdfmark: \prg_do_nothing: } % \end{macrocode} % % % \bigskip % We define a command |\iddots| similar to |\ddots| ($\ddots$) but with dots % going forward ($\iddots$). We use |\ProvideDocumentCommand| and so, if the % command |\iddots| has already been defined (for example by the package % \pkg{mathdots}), we don't define it again. % % \begin{macrocode} \ProvideDocumentCommand \iddots { } { \mathinner { \tex_mkern:D 1 mu \box_move_up:nn { 1 pt } { \hbox:n { . } } \tex_mkern:D 2 mu \box_move_up:nn { 4 pt } { \hbox:n { . } } \tex_mkern:D 2 mu \box_move_up:nn { 7 pt } { \vbox:n { \kern 7 pt \hbox:n { . } } } \tex_mkern:D 1 mu } } % \end{macrocode} % % This definition is a variant of the standard definition of |\ddots|. % % % \bigskip % In the |aux| file, we will have the references of the PGF/Tikz nodes created % by \pkg{nicematrix}. However, when \pkg{booktabs} is used, some nodes (more % precisely, some |row| nodes) will be defined twice because their position will % be modified. In order to avoid an error message in this case, we will redefine % |\pgfutil@check@rerun| in the |aux| file. % \begin{macrocode} \AtBeginDocument { \@ifpackageloaded { booktabs } { \iow_now:Nn \@mainaux \nicematrix@redefine@check@rerun } { } } \cs_set_protected:Npn \nicematrix@redefine@check@rerun { \cs_set_eq:NN \@@_old_pgfutil@check@rerun \pgfutil@check@rerun % \end{macrocode} % The new version of |\pgfutil@check@rerun| will not check the PGF nodes whose % names start with |nm-| (which is the prefix for the nodes created by % \pkg{nicematrix}). % \begin{macrocode} \cs_set_protected:Npn \pgfutil@check@rerun ##1 ##2 { \str_if_eq:eeF { nm- } { \tl_range:nnn { ##1 } 1 3 } { \@@_old_pgfutil@check@rerun { ##1 } { ##2 } } } } % \end{macrocode} % % \bigskip % We have to know whether \pkg{colortbl} is loaded in particular for the % redefinition of |\everycr|. % \begin{macrocode} \bool_new:N \c_@@_colortbl_loaded_bool \AtBeginDocument { \@ifpackageloaded { colortbl } { \bool_set_true:N \c_@@_colortbl_loaded_bool } { % \end{macrocode} % The command |\CT@arc@| is a command of \pkg{colortbl} which sets the color of % the rules in the array. We will use it to store the instruction of color for % the rules even if \pkg{colortbl} is not loaded. % \begin{macrocode} \cs_set_protected:Npn \CT@arc@ { } \cs_set:Npn \arrayrulecolor #1 # { \CT@arc { #1 } } \cs_set:Npn \CT@arc #1 #2 { \dim_compare:nNnT \baselineskip = \c_zero_dim \noalign { \cs_gset:Npn \CT@arc@ { \color #1 { #2 } } } } % \end{macrocode} % Idem for |\CT@drs@|. % \begin{macrocode} \cs_set:Npn \doublerulesepcolor #1 # { \CT@drs { #1 } } \cs_set:Npn\CT@drs #1 #2 { \dim_compare:nNnT \baselineskip = \c_zero_dim \noalign { \cs_gset:Npn \CT@drsc@ { \color #1 { #2 } } } } \cs_set:Npn \hline { \noalign { \ifnum 0 = `} \fi \cs_set_eq:NN \hskip \vskip \cs_set_eq:NN \vrule \hrule \cs_set_eq:NN \@width \@height { \CT@arc@ \vline } \futurelet \reserved@a \@xhline } } } % \end{macrocode} % % \bigskip % We will use |\AtBeginEnvironment|. For version of LaTeX posterior to % 2020-10-01, the command is available in the LaTeX kernel (\pkg{l3hooks}). For % older versions, we load \pkg{etoolbox}. % \begin{macrocode} \cs_if_exist:NF \AtBeginEnvironment { \RequirePackage { etoolbox } } % \end{macrocode} % The command |\AtBeginDocument| will be used to patch |{tabular}| in order to % come back to the original versions of |\multicolumn| in the |{tabular}| nested % in the environments of \pkg{nicematrix}. % % \bigskip % We have to redefine |\cline| for several reasons. The command |\@@_cline| will % be linked to |\cline| in the beginning of |{NiceArrayWithDelims}|. The % following commands must \emph{not} be protected. % \begin{macrocode} \cs_set:Npn \@@_standard_cline #1 { \@@_standard_cline:w #1 \q_stop } \cs_set:Npn \@@_standard_cline:w #1-#2 \q_stop { \int_compare:nNnT \l_@@_first_col_int = 0 { \omit & } \int_compare:nNnT { #1 } > 1 { \multispan { \@@_pred:n { #1 } } & } \multispan { \int_eval:n { #2 - #1 + 1 } } { \CT@arc@ \leaders \hrule \@height \arrayrulewidth \hfill % \end{macrocode} % The following |\skip_horizontal:N \c_zero_dim| is to prevent a potential % |\unskip| to delete the |\leaders|\footnote{See question 99041 on TeX % StackExchange.} % \begin{macrocode} \skip_horizontal:N \c_zero_dim } % \end{macrocode} % Our |\everycr| has been modified. In particular, the creation of the |row| % node is in the |\everycr| (maybe we should put it with the incrementation of % |\c@iRow|). Since the following |\cr| correspond to a ``false row'', we have % to nullify |\everycr|. % \begin{macrocode} \everycr { } \cr \noalign { \skip_vertical:N -\arrayrulewidth } } % \end{macrocode} % % \bigskip % The following version of |\cline| spreads the array of a quantity equal % to |\arrayrulewidth| as does |\hline|. It will be loaded excepted if the key % |standard-cline| has been used. % \begin{macrocode} \cs_set:Npn \@@_cline % \end{macrocode} % We have to act in a fully expandable way since there may be |\noalign| (in the % |\multispan|) to detect. That's why we use |\@@_cline_i:en|. % \begin{macrocode} { \@@_cline_i:en \l_@@_first_col_int } % \end{macrocode} % The command |\cline_i:nn| has two arguments. The first is the number of the % current column (it \emph{must} be used in that column). The second is a % standard argument of |\cline| of the form \textsl{i}-\textsl{j}. % \begin{macrocode} \cs_set:Npn \@@_cline_i:nn #1 #2 { \@@_cline_i:w #1-#2 \q_stop } \cs_set:Npn \@@_cline_i:w #1-#2-#3 \q_stop { % \end{macrocode} % Now, |#1| is the number of the current column and we have to draw a line from % the column |#2| to the column |#3| (both included). % \begin{macrocode} \int_compare:nNnT { #1 } < { #2 } { \multispan { \int_eval:n { #2 - #1 } } & } \multispan { \int_eval:n { #3 - #2 + 1 } } { \CT@arc@ \leaders \hrule \@height \arrayrulewidth \hfill \skip_horizontal:N \c_zero_dim } % \end{macrocode} % You look whether there is another |\cline| to draw (the final user may put % several |\cline|). % \begin{macrocode} \peek_meaning_remove_ignore_spaces:NTF \cline { & \@@_cline_i:en { \@@_succ:n { #3 } } } { \everycr { } \cr } } \cs_generate_variant:Nn \@@_cline_i:nn { e n } % \end{macrocode} % % \bigskip % The following commands are only for efficiency. They must \emph{not} be protected % because it will be used (for instance) in names of \textsc{pgf} nodes. % \begin{macrocode} \cs_new:Npn \@@_succ:n #1 { \the \numexpr #1 + 1 \relax } \cs_new:Npn \@@_pred:n #1 { \the \numexpr #1 - 1 \relax } % \end{macrocode} % % \bigskip % The following command is a small shortcut. % \begin{macrocode} \cs_new:Npn \@@_math_toggle_token: { \bool_if:NF \l_@@_NiceTabular_bool \c_math_toggle_token } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_set_CT@arc@: { \peek_meaning:NTF [ \@@_set_CT@arc@_i: \@@_set_CT@arc@_ii: } \cs_new_protected:Npn \@@_set_CT@arc@_i: [ #1 ] #2 \q_stop { \cs_set:Npn \CT@arc@ { \color [ #1 ] { #2 } } } \cs_new_protected:Npn \@@_set_CT@arc@_ii: #1 \q_stop { \cs_set:Npn \CT@arc@ { \color { #1 } } } % \end{macrocode} % % % \bigskip % \begin{macrocode} \cs_set_eq:NN \@@_old_pgfpointanchor \pgfpointanchor % \end{macrocode} % % \bigskip % \textbf{The column S of siunitx}\par\nobreak % % \medskip % We want to know whether the package \pkg{siunitx} is loaded and, if it is % loaded, we redefine the |S| columns of \pkg{siunitx}. % \begin{macrocode} \bool_new:N \c_@@_siunitx_loaded_bool \AtBeginDocument { \@ifpackageloaded { siunitx } { \bool_set_true:N \c_@@_siunitx_loaded_bool } { } } % \end{macrocode} % % % % \bigskip % The command |\@@_renew_NC@rewrite@S:| will be used in each environment of % \pkg{nicematrix} in order to ``rewrite'' the |S| column in each environment. % \begin{macrocode} \AtBeginDocument { \bool_if:nTF { ! \c_@@_siunitx_loaded_bool } { \cs_set_eq:NN \@@_renew_NC@rewrite@S: \prg_do_nothing: } { \cs_new_protected:Npn \@@_renew_NC@rewrite@S: { \renewcommand*{\NC@rewrite@S}[1][] { % \end{macrocode} % |\@temptokena| is a toks (not supported by \pkg{expl3}). % \begin{macrocode} \@temptokena \exp_after:wN { \tex_the:D \@temptokena \@@_S: [ ##1 ] } \NC@find } } } } % \end{macrocode} % % \medskip % The following code is used to define |\c_@@_table_collect_begin_tl| and % |\c_@@_table_print_tl| when the version of \pkg{siunitx} is prior to 3.0. The % command |\@@_adapt_S_column| is used in the environment |{NiceArrayWithDelims}|. % \begin{macrocode} \AtBeginDocument { \cs_set_eq:NN \@@_adapt_S_column: \prg_do_nothing: \bool_lazy_and:nnT { \c_@@_siunitx_loaded_bool } { ! \cs_if_exist_p:N \siunitx_cell_begin:w } { \cs_set_protected:Npn \@@_adapt_S_column: { \group_begin: \@temptokena = { } \cs_set_eq:NN \NC@find \prg_do_nothing: \NC@rewrite@S { } \tl_gset:NV \g_tmpa_tl \@temptokena \group_end: \tl_new:N \c_@@_table_collect_begin_tl \tl_set:Nx \l_tmpa_tl { \tl_item:Nn \g_tmpa_tl 2 } \tl_gset:Nx \c_@@_table_collect_begin_tl { \tl_item:Nn \l_tmpa_tl 1 } \tl_new:N \c_@@_table_print_tl \tl_gset:Nx \c_@@_table_print_tl { \tl_item:Nn \g_tmpa_tl { -1 } } \cs_gset_eq:NN \@@_adapt_S_column: \prg_do_nothing: } } } % \end{macrocode} % % % % \bigskip % \subsection*{Parameters} % % \bigskip % The following counter will count the environments |{NiceArray}|. The value of % this counter will be used to prefix the names of the Tikz nodes created in the % array. % \begin{macrocode} \int_new:N \g_@@_env_int % \end{macrocode} % % \bigskip % The following command is only a syntaxic shortcut. It must \emph{not} be % protected (it will be used in names of \textsc{pgf} nodes). % \begin{macrocode} \cs_new:Npn \@@_env: { nm - \int_use:N \g_@@_env_int } % \end{macrocode} % % \bigskip % The command |\NiceMatrixLastEnv| is not used by the package \pkg{nicematrix}. % It's only a facility given to the final user. It gives the number of the last % environment (in fact the number of the current environment but it's meant to % be used after the environment in order to refer to that environment --- and % its nodes --- without having to give it a name). This command \emph{must} be % expandable since it will be used in \pkg{pgf} nodes. % \begin{macrocode} \NewExpandableDocumentCommand \NiceMatrixLastEnv { } { \int_use:N \g_@@_env_int } % \end{macrocode} % % % \bigskip % The following command is only a syntaxic shortcut. The |q| in |qpoint| means % \emph{quick}. % \begin{macrocode} \cs_new_protected:Npn \@@_qpoint:n #1 { \pgfpointanchor { \@@_env: - #1 } { center } } % \end{macrocode} % % \bigskip % The following counter will count the environments |{NiceMatrixBlock}|. % \begin{macrocode} \int_new:N \g_@@_NiceMatrixBlock_int % \end{macrocode} % % \bigskip % The dimension |\l_@@_columns_width_dim| will be used when the options specify % that all the columns must have the same width (but, if the key |columns-width| % is used with the special value |auto|, the boolean % |l_@@_auto_columns_width_bool| also will be raised). % \begin{macrocode} \dim_new:N \l_@@_columns_width_dim % \end{macrocode} % % \bigskip % The dimension |\l_@@_col_width_dim| will be available in each cell which % belongs to a column of fixed width: |w{...}{...}|, |W{...}{...}|, |p{}|, % |m{}|, |b{}| but also |X| (when the actual width of that column is known, that % is to say after the first compilation). It's the width of that column. It will % be used by some commands |\Block|. A non positive value means that the column % has no fixed width (it's a column of type |c|, |r|, |l|, etc.). % \begin{macrocode} \dim_new:N \l_@@_col_width_dim \dim_set:Nn \l_@@_col_width_dim { -1 cm } % \end{macrocode} % % % \bigskip % The following counters will be used to count the numbers of rows and columns % of the array. % \begin{macrocode} \int_new:N \g_@@_row_total_int \int_new:N \g_@@_col_total_int % \end{macrocode} % % \bigskip % The following token list will contain the type of horizontal alignment of the % current cell as provided by the corresponding column. The possible values are % |r|, |l|, |c|. For exemple, a column |p[l]{3cm}| will provide the value |l| % for all the cells of the column. % \begin{macrocode} \str_new:N \l_@@_hpos_cell_str \str_set:Nn \l_@@_hpos_cell_str { c } % \end{macrocode} % % \bigskip % When there is a mono-column block (created by the command |\Block|), we want % to take into account the width of that block for the width of the column. % That's why we compute the width of that block in the |\g_@@_blocks_wd_dim| % and, after the construction of the box |\l_@@_cell_box|, we change the width % of that box to take into account the length |\g_@@_blocks_wd_dim|. % \begin{macrocode} \dim_new:N \g_@@_blocks_wd_dim % \end{macrocode} % % \bigskip % Idem pour the mono-row blocks. % \begin{macrocode} \dim_new:N \g_@@_blocks_ht_dim \dim_new:N \g_@@_blocks_dp_dim % \end{macrocode} % % \bigskip % The sequence |\g_@@_names_seq| will be the list of all the names of % environments used (via the option |name|) in the document: two environments % must not have the same name. However, it's possible to use the option % |allow-duplicate-names|. % \begin{macrocode} \seq_new:N \g_@@_names_seq % \end{macrocode} % % \bigskip % We want to know whether we are in an environment of \pkg{nicematrix} because we % will raise an error if the user tries to use nested environments. % \begin{macrocode} \bool_new:N \l_@@_in_env_bool % \end{macrocode} % % \bigskip % If the user uses |{NiceArray}| or |{NiceTabular}| the flag % |\l_@@_NiceArray_bool| will be raised. % \begin{macrocode} \bool_new:N \l_@@_NiceArray_bool % \end{macrocode} % In fact, if there is delimiters in the preamble of |{NiceArray}| (eg: % |[cccc]|), this boolean will be set to false. % % \bigskip % If the user uses |{NiceTabular}| or |{NiceTabular*}|, we will raise the % following flag. % \begin{macrocode} \bool_new:N \l_@@_NiceTabular_bool % \end{macrocode} % % \bigskip % If the user uses |{NiceTabular*}|, the width of the tabular (in the first % argument of the environment |{NiceTabular*}|) will be stored in the following % dimension. % \begin{macrocode} \dim_new:N \l_@@_tabular_width_dim % \end{macrocode} % % \bigskip % If the user uses an environment without preamble, we will raise the following % flag. % \begin{macrocode} \bool_new:N \l_@@_Matrix_bool % \end{macrocode} % % \bigskip % The following boolean will be raised when the command |\rotate| is used. % \begin{macrocode} \bool_new:N \g_@@_rotate_bool % \end{macrocode} % % \bigskip % In a cell, it will be possible to know whether we are in a cell of a column of % type |X| thanks to that flag. % \begin{macrocode} \bool_new:N \l_@@_X_column_bool % \end{macrocode} % % \bigskip % We will write in |\g_@@_aux_tl| all the instructions that we have to write on % the |aux| file for the current environment. The contain of that token list % will be written on the |aux| file at the end of the environment (in an % instruction |\tl_gset:cn { c_@@_ \int_use:N \g_@@_env_int _ tl }|). % \begin{macrocode} \tl_new:N \g_@@_aux_tl % \end{macrocode} % % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_test_if_math_mode: { \if_mode_math: \else: \@@_fatal:n { Outside~math~mode } \fi: } % \end{macrocode} % % \bigskip % The letter used for the vlines which will be drawn only in the sub-matrices. % |vlism| stands for \emph{vertical lines in sub-matrices}. % \begin{macrocode} \tl_new:N \l_@@_letter_vlism_tl % \end{macrocode} % % The list of the columns where vertical lines in sub-matrices (vlism) must be % drawn. Of course, the actual value of this sequence will be known after the % analyse of the preamble of the array. % \begin{macrocode} \seq_new:N \g_@@_cols_vlism_seq % \end{macrocode} % % \bigskip % The following colors will be used to memorize the color of the potential ``first % col'' and the potential ``first row''. % \begin{macrocode} \colorlet { nicematrix-last-col } { . } \colorlet { nicematrix-last-row } { . } % \end{macrocode} % \bigskip % The following string is the name of the current environment or the current % command of \pkg{nicematrix} (despite its name which contains \textsl{env}). % \begin{macrocode} \str_new:N \g_@@_name_env_str % \end{macrocode} % % \bigskip % The following string will contain the word \emph{command} or % \emph{environment} whether we are in a command of \pkg{nicematrix} or in an % environment of \pkg{nicematrix}. The default value is \emph{environment}. % \begin{macrocode} \tl_set:Nn \g_@@_com_or_env_str { environment } % \end{macrocode} % % \bigskip % The following command will be able to reconstruct the full name of the current % command or environment (despite its name which contains \textsl{env}). This % command must \emph{not} be protected since it will be used in error messages % and we have to use |\str_if_eq:VnTF| and not |\tl_if_eq:NnTF| because we need % to be fully expandable). % \begin{macrocode} \cs_new:Npn \@@_full_name_env: { \str_if_eq:VnTF \g_@@_com_or_env_str { command } { command \space \c_backslash_str \g_@@_name_env_str } { environment \space \{ \g_@@_name_env_str \} } } % \end{macrocode} % % \bigskip % The following token list corresponds to the option |code-after| (it's also % possible to set the value of that parameter with the keyword |\CodeAfter|). % \begin{macrocode} \tl_new:N \g_nicematrix_code_after_tl % \end{macrocode} % % \bigskip % For the key |code| of the command |\SubMatrix| (itself in the main % |\CodeAfter|), we will use the following token list. % \begin{macrocode} \tl_new:N \l_@@_code_tl % \end{macrocode} % % \bigskip % The following token list has a function similar to % |\g_nicematrix_code_after_tl| but it is used internally by \pkg{nicematrix}. % In fact, we have to distinguish between |\g_nicematrix_code_after_tl| and % |\g_@@_internal_code_after_tl| because we must take care of the order in which % instructions stored in that parameters are executed. % \begin{macrocode} \tl_new:N \g_@@_internal_code_after_tl % \end{macrocode} % % \bigskip % The counters |\l_@@_old_iRow_int| and |\l_@@_old_jCol_int| will be used to % save the values of the potential LaTeX counters |iRow| and |jCol|. These LaTeX % counters will be restored at the end of the environment. % \begin{macrocode} \int_new:N \l_@@_old_iRow_int \int_new:N \l_@@_old_jCol_int % \end{macrocode} % % The TeX counters |\c@iRow| and |\c@jCol| will be created in the beginning of % |{NiceArrayWithDelims}| (if they don't exist previously). % % \bigskip % The following token list corresponds to the key |rules/color| available % in the environments. % \begin{macrocode} \tl_new:N \l_@@_rules_color_tl % \end{macrocode} % % \bigskip % The sum of the weights of all the |X|-columns in the preamble. The weight of a % |X|-column is given as optional argument between square brackets. The default % value, of course, is $1$. % \begin{macrocode} \int_new:N \g_@@_total_X_weight_int % \end{macrocode} % % If there is at least one |X|-column in the preamble of the array, the % following flag will be raised via the |aux| file. The length % |l_@@_x_columns_dim| will be the width of |X|-columns of weight $1$ (the width % of a column of weigth $n$ will be that dimension multiplied by~$n$). That % value is computed after the construction of the array during the first % compilation in order to be used in the following run. % \begin{macrocode} \bool_new:N \l_@@_X_columns_aux_bool \dim_new:N \l_@@_X_columns_dim % \end{macrocode} % % \bigskip % This boolean will be used only to detect in an expandable way whether we are % at the beginning of the (potential) column zero, in order to raise an error if % |\Hdotsfor| is used in that column. % \begin{macrocode} \bool_new:N \g_@@_after_col_zero_bool % \end{macrocode} % % \bigskip % A kind of false row will be inserted at the end of the array for the % construction of the |col| nodes (and also to fix the width of the columns when % |columns-width| is used). When this special row will be created, we will raise % the flag |\g_@@_row_of_col_done_bool| in order to avoid some actions set in % the redefinition of |\everycr| when the last |\cr| of the |\halign| will occur % (after that row of |col| nodes). % \begin{macrocode} \bool_new:N \g_@@_row_of_col_done_bool % \end{macrocode} % % \bigskip % It's possible to use the command |\NotEmpty| to specify explicitely that a % cell must be considered as non empty by \pkg{nicematrix} (the Tikz nodes are % constructed only in the non empty cells). % \begin{macrocode} \bool_new:N \g_@@_not_empty_cell_bool % \end{macrocode} % % \bigskip % |\l_@@_code_before_tl| may contain two types of informations: % \begin{itemize} % \item A |code-before| written in the |aux| file by a previous run. When the % |aux| file is read, this |code-before| is stored in % |\g_@@_code_before_|\textsl{i}|_tl| (where \textsl{i} is the number of the % environment) and, at the beginning of the environment, it will be put in % |\l_@@_code_before_tl|. % \item The final user can explicitly add material in |\l_@@_code_before_tl| by % using the key |code-before| or the keyword |\CodeBefore| (with the keyword % |\Body|). % \end{itemize} % \begin{macrocode} \tl_new:N \l_@@_code_before_tl \bool_new:N \l_@@_code_before_bool % \end{macrocode} % % \bigskip % The following token list will contain ce code inserted in each cell of the % current row (this token list will be cleared at the beginning of each row). % \begin{macrocode} \tl_new:N \g_@@_row_style_tl % \end{macrocode} % % \bigskip % The following dimensions will be used when drawing the dotted lines. % \begin{macrocode} \dim_new:N \l_@@_x_initial_dim \dim_new:N \l_@@_y_initial_dim \dim_new:N \l_@@_x_final_dim \dim_new:N \l_@@_y_final_dim % \end{macrocode} % % \bigskip % The L3 programming layer provides scratch dimensions |\l_tmpa_dim| and % |\l_tmpb_dim|. We creates two more in the same spirit (if they don't exist % yet: that's why we use |\dim_zero_new:N|). % \begin{macrocode} \dim_zero_new:N \l_tmpc_dim \dim_zero_new:N \l_tmpd_dim % \end{macrocode} % % \bigskip % Some cells will be declared as ``empty'' (for example a cell with an % instruction |\Cdots|). % \begin{macrocode} \bool_new:N \g_@@_empty_cell_bool % \end{macrocode} % % % \bigskip % The following dimensions will be used internally to compute the width of the % potential ``first column'' and ``last column''. % \begin{macrocode} \dim_new:N \g_@@_width_last_col_dim \dim_new:N \g_@@_width_first_col_dim % \end{macrocode} % % \bigskip % The following sequence will contain the characteristics of the blocks of the % array, specified by the command |\Block|. Each block is represented by 6 % components surrounded by curly braces: % % |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}{|\textsl{options}|}{|\textsl{contents}|}|. % % The variable is global because it will be modified in the cells of the array. % \begin{macrocode} \seq_new:N \g_@@_blocks_seq % \end{macrocode} % We also manage a sequence of the \emph{positions} of the blocks. In that % sequence, each block is represented by only the four first components: % |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}|. A % block with the key |hvlines| won't appear in that sequence (otherwise, the % lines in that block would not be drawn!). % \begin{macrocode} \seq_new:N \g_@@_pos_of_blocks_seq % \end{macrocode} % In fact, this sequence will also contain the positions of the cells with a % |\diagbox|. The sequence |\g_@@_pos_of_blocks_seq| will be used when we will % draw the rules (which respect the blocks). % % \bigskip % We will also manage a sequence for the positions of the dotted lines. These % dotted lines are created in the array by |\Cdots|, |\Vdots|, |\Ddots|, etc. % However, their positions, that is to say, their extremities, will be % determined only after the construction of the array. In this sequence, each % item contains four components: % |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}|. % \begin{macrocode} \seq_new:N \g_@@_pos_of_xdots_seq % \end{macrocode} % The sequence |\g_@@_pos_of_xdots_seq| will be used when we will draw the rules % required by the key |hvlines| (these rules won't be drawn within the virtual % blocks corresponding to the dotted lines). % % \medskip % The final user may decide to ``stroke'' a block (using, for example, the key % |draw=red!15| when using the command |\Block|). In that case, the rules % specified, for instance, by |hvlines| must not be drawn around the block. % That's why we keep the information of all that stroken blocks in the following % sequence. % \begin{macrocode} \seq_new:N \g_@@_pos_of_stroken_blocks_seq % \end{macrocode} % % \medskip % If the user has used the key |corners| (or the key |hvlines-except-corners|, % even though that key is deprecated), all the cells which are in an (empty) % corner will be stored in the following sequence. % \begin{macrocode} \seq_new:N \l_@@_corners_cells_seq % \end{macrocode} % % \medskip % The list of the names of the potential |\SubMatrix| in the |\CodeAfter| of an % environment. Unfortunately, that list has to be global (we have to use it % inside the group for the options of a given |\SubMatrix|). % \begin{macrocode} \seq_new:N \g_@@_submatrix_names_seq % \end{macrocode} % % \medskip % The following flag will be raised if the key |width| has been raised. You use % it to raise an error when this key is used while no column |X| is used. % \begin{macrocode} \bool_new:N \l_@@_width_used_bool % \end{macrocode} % % \medskip % The sequence |\g_@@_multicolumn_cells_seq| will contain the list of the cells % of the array where a command |\multicolumn{|$n$|}{...}{...}| with $n>1$ is % issued. In |\g_@@_multicolumn_sizes_seq|, the ``sizes'' (that is to say the % values of $n$) correspondant will be stored. These lists will be used for the % creation of the ``medium nodes'' (if they are created). % \begin{macrocode} \seq_new:N \g_@@_multicolumn_cells_seq \seq_new:N \g_@@_multicolumn_sizes_seq % \end{macrocode} % % \medskip % The following counters will be used when searching the extremities of a dotted % line (we need these counters because of the potential ``open'' lines in the % |\SubMatrix|---the |\SubMatrix| in the |code-before|). % \begin{macrocode} \int_new:N \l_@@_row_min_int \int_new:N \l_@@_row_max_int \int_new:N \l_@@_col_min_int \int_new:N \l_@@_col_max_int % \end{macrocode} % % \medskip % The following sequence will be used when the command |\SubMatrix| is used in % the |code-before| (and not in the |\CodeAfter|). It will contain the position of % all the sub-matrices specified in the |code-before|. Each sub-matrix is % represented by an ``object'' of the forme |{|$i$|}{|$j$|}{|$k$|}{|$l$|}| % where $i$ and $j$ are the number of row and column of the upper-left cell and % $k$ and $l$ the number of row and column of the lower-right cell. % \begin{macrocode} \seq_new:N \g_@@_submatrix_seq % \end{macrocode} % % \medskip % We are able to determine the number of columns specified in the preamble (for % the environments with explicit preamble of course and without the potential % exterior columns). % \begin{macrocode} \int_new:N \g_@@_static_num_of_col_int % \end{macrocode} % % \medskip % The following parameters correspond to the keys |fill|, |draw|, |tikz|, |borders|, % and |rounded-corners| of the command |\Block|. % \begin{macrocode} \tl_new:N \l_@@_fill_tl \tl_new:N \l_@@_draw_tl \seq_new:N \l_@@_tikz_seq \clist_new:N \l_@@_borders_clist \dim_new:N \l_@@_rounded_corners_dim % \end{macrocode} % The last parameter has no direct link with the [empty] corners of the array % (which are computed and taken into account by \pkg{nicematrix} when the key % |corners| is used). % % \medskip % The following token list correspond to the key |color| of the command |\Block|. % \begin{macrocode} \tl_new:N \l_@@_color_tl % \end{macrocode} % % \medskip % Here is the dimension for the width of the rule when a block (created by % |\Block|) is stroked. % \begin{macrocode} \dim_new:N \l_@@_line_width_dim % \end{macrocode} % % \medskip % The parameters of the horizontal position of the label of a block. If the user % uses the key |c| or |C|, the value is |c|. If the user uses the key |l| or % |L|, the value is |l|. If the user uses the key |r| or |R|, the value is |r|. % If the user has used a capital letter, the boolean % |\l_@@_hpos_of_block_cap_bool| will be raised (in the second pass of the % analyze of the keys of the command |\Block|). % \begin{macrocode} \str_new:N \l_@@_hpos_block_str \str_set:Nn \l_@@_hpos_block_str { c } \bool_new:N \l_@@_hpos_of_block_cap_bool % \end{macrocode} % % \medskip % For the vertical position, the possible values are |c|, |t| and |b|. Of % course, it would be interesting to program a key |T| and a key |B|. % \begin{macrocode} \tl_new:N \l_@@_vpos_of_block_tl \tl_set:Nn \l_@@_vpos_of_block_tl { c } % \end{macrocode} % % % \medskip % Used when the key |draw-first| is used for |\Ddots| or |\Iddots|. % \begin{macrocode} \bool_new:N \l_@@_draw_first_bool % \end{macrocode} % % % \medskip % The following flag corresponds to the key |hvlines| of the command |\Block|. % \begin{macrocode} \bool_new:N \l_@@_hvlines_block_bool % \end{macrocode} % % % \medskip % The blocks which use the key |-| will store their content in a box. These % boxes are numbered with the following counter. % \begin{macrocode} \int_new:N \g_@@_block_box_int % \end{macrocode} % % \medskip % \begin{macrocode} \dim_new:N \l_@@_submatrix_extra_height_dim \dim_new:N \l_@@_submatrix_left_xshift_dim \dim_new:N \l_@@_submatrix_right_xshift_dim \clist_new:N \l_@@_hlines_clist \clist_new:N \l_@@_vlines_clist \clist_new:N \l_@@_submatrix_hlines_clist \clist_new:N \l_@@_submatrix_vlines_clist % \end{macrocode} % % % % \bigskip % \textbf{Variables for the exterior rows and columns}\par\nobreak % % \medskip % The keys for the exterior rows and columns are |first-row|, |first-col|, % |last-row| and |last-col|. However, internally, these keys are not coded in a % similar way. % % \bigskip % \begin{itemize} % \item \textbf{First row}\par\nobreak % The integer |\l_@@_first_row_int| is the number of the first row of the % array. The default value is $1$, but, if the option |first-row| is used, % the value will be~$0$. % \begin{macrocode} \int_new:N \l_@@_first_row_int \int_set:Nn \l_@@_first_row_int 1 % \end{macrocode} % % \medskip % \item \textbf{First column}\par\nobreak % The integer |\l_@@_first_col_int| is the number of the first column of the % array. The default value is $1$, but, if the option |first-col| is used, % the value will be~$0$. % \begin{macrocode} \int_new:N \l_@@_first_col_int \int_set:Nn \l_@@_first_col_int 1 % \end{macrocode} % % \medskip % \item \textbf{Last row}\par\nobreak % The counter |\l_@@_last_row_int| is the number of the potential ``last row'', % as specified by the key |last-row|. A value of $-2$ means that there is no % ``last row''. A value of $-1$ means that there is a ``last row'' but we don't % know the number of that row (the key |last-row| has been used without value % and the actual value has not still been read in the |aux| file). % \begin{macrocode} \int_new:N \l_@@_last_row_int \int_set:Nn \l_@@_last_row_int { -2 } % \end{macrocode} % % \smallskip % If, in an environment like |{pNiceArray}|, the option |last-row| is used % without value, we will globally raise the following flag. It will be used to % know if we have, after the construction of the array, to write in the |aux| % file the number of the ``last row''.\footnote{We can't use % |\l_@@_last_row_int| for this usage because, if \pkg{nicematrix} has read its % value from the |aux| file, the value of the counter won't be $-1$ any longer.} % \begin{macrocode} \bool_new:N \l_@@_last_row_without_value_bool % \end{macrocode} % % \smallskip % Idem for |\l_@@_last_col_without_value_bool| % \begin{macrocode} \bool_new:N \l_@@_last_col_without_value_bool % \end{macrocode} % % \medskip % \item \textbf{Last column}\par\nobreak % % For the potential ``last column'', we use an integer. A value of $-2$ means % that there is no last column. A value of $-1$ means that we are in an % environment without preamble (e.g. |{bNiceMatrix}|) and there is a last column % but we don't know its value because the user has used the option |last-col| % without value. A value of $0$ means that the option |last-col| has been used % in an environment with preamble (like |{pNiceArray}|): in this case, the key % was necessary without argument. % \begin{macrocode} \int_new:N \l_@@_last_col_int \int_set:Nn \l_@@_last_col_int { -2 } % \end{macrocode} % % However, we have also a boolean. Consider the following code: % \begin{center} % \begin{BVerbatim} % \begin{pNiceArray}{cc}[last-col] % 1 & 2 \\ % 3 & 4 % \end{pNiceArray} % \end{BVerbatim} % \end{center} % In such a code, the ``last column'' specified by the key |last-col| is not % used. We want to be able to detect such a situation and we create a boolean % for that job. % \begin{macrocode} \bool_new:N \g_@@_last_col_found_bool % \end{macrocode} % This boolean is set to |false| at the end of |\@@_pre_array_ii:|. % \end{itemize} % % \bigskip % \subsection*{The command \textbackslash tabularnote} % % \bigskip % The LaTeX counter |tabularnote| will be used to count the tabular notes during % the construction of the array (this counter won't be used during the % composition of the notes at the end of the array). You use a LaTeX counter % because we will use |\refstepcounter| in order to have the tabular notes % referenceable. % \begin{macrocode} \newcounter { tabularnote } % \end{macrocode} % % \bigskip % We will store in the following sequence the tabular notes of a given array. % \begin{macrocode} \seq_new:N \g_@@_tabularnotes_seq % \end{macrocode} % % \bigskip % However, before the actual tabular notes, it's possible to put a text % specified by the key |tabularnote| of the environment. The token list % |\l_@@_tabularnote_tl| corresponds to the value of that key. % \begin{macrocode} \tl_new:N \l_@@_tabularnote_tl % \end{macrocode} % % \bigskip % The following counter will be used to count the number of successive tabular % notes such as in % |\tabularnote{Note 1}\tabularnote{Note 2}\tabularnote{Note 3}|. % In the tabular, the labels of those nodes are composed as a comma % separated list (e.g. \textsuperscript{\textit{a},\textit{b},\textit{c}}). % \begin{macrocode} \int_new:N \l_@@_number_of_notes_int % \end{macrocode} % % \bigskip % The following function can be redefined by using the key |notes/style|. % \begin{macrocode} \cs_new:Npn \@@_notes_style:n #1 { \textit { \alph { #1 } } } % \end{macrocode} % % \bigskip % The following fonction can be redefined by using the key % |notes/label-in-tabular|. % \begin{macrocode} \cs_new:Npn \@@_notes_label_in_tabular:n #1 { \textsuperscript { #1 } } % \end{macrocode} % % \bigskip % The following function can be redefined by using the key |notes/label-in-list|. % \begin{macrocode} \cs_new:Npn \@@_notes_label_in_list:n #1 { \textsuperscript { #1 } } % \end{macrocode} % % \bigskip % We define |\thetabularnote| because it will be used by LaTeX if the user want % to reference a footnote which has been marked by a |\label|. The TeX group is % for the case where the user has put an instruction such as |\color{red}| in % |\@@_notes_style:n|. % \begin{macrocode} \cs_set:Npn \thetabularnote { { \@@_notes_style:n { tabularnote } } } % \end{macrocode} % % \bigskip % The tabular notes will be available for the final user only when % \pkg{enumitem} is loaded. Indeed, the tabular notes will be composed at the end % of the array with a list customized by \pkg{enumitem} (a list |tabularnotes| % in the general case and a list |tabularnotes*| if the key |para| is in force). % However, we can test whether \pkg{enumitem} has been loaded only at the % beginning of the document (we want to allow the user to load \pkg{enumitem} % after \pkg{nicematrix}). % \begin{macrocode} \AtBeginDocument { \bool_if:nTF { ! \c_@@_enumitem_loaded_bool } { \NewDocumentCommand \tabularnote { m } { \@@_error:n { enumitem~not~loaded } } } { % \end{macrocode} % The type of list |tabularnotes| will be used to format the tabular notes at % the end of the array in the general case and |tabularnotes*| will be used if % the key |para| is in force. % \begin{macrocode} \newlist { tabularnotes } { enumerate } { 1 } \setlist [ tabularnotes ] { topsep = 0pt , noitemsep , leftmargin = * , align = left , labelsep = 0pt , label = \@@_notes_label_in_list:n { \@@_notes_style:n { tabularnotesi } } , } \newlist { tabularnotes* } { enumerate* } { 1 } \setlist [ tabularnotes* ] { afterlabel = \nobreak , itemjoin = \quad , label = \@@_notes_label_in_list:n { \@@_notes_style:n { tabularnotes*i } } } % \end{macrocode} % % \medskip % The command |\tabularnote| is available in the whole document (and not only in % the environments of \pkg{nicematrix}) because we want it to be available in % the caption of a |{table}| (before the following |{NiceTabular}| or % |{NiceArray}|). That's also the reason why the variables |\c@tabularnote| and % |\g_@@_tabularnotes_seq| will be cleared at the end of the environment of % \pkg{nicematrix} (and not at the beginning). % % Unfortunately, if the package \pkg{caption} is loaded, the command |\caption| % evaluates its argument twice and since it is not aware (of course) of % |\tabularnote|, the command |\tabularnote| is, in fact, not usable in % |\caption| when \pkg{caption} is loaded.\footnote{We should try to find a % solution to that problem.} % \begin{macrocode} \NewDocumentCommand \tabularnote { m } { \bool_if:nTF { ! \l_@@_NiceArray_bool && \l_@@_in_env_bool } { \@@_error:n { tabularnote~forbidden } } { % \end{macrocode} % |\l_@@_number_of_notes_int| is used to count the number of successive tabular % notes such as in % |\tabularnote{Note 1}\tabularnote{Note 2}\tabularnote{Note 3}|. % We will have to compose the labels of theses notes as a comma separated list % (e.g. \textsuperscript{\emph{a},\emph{b},\emph{c}}). % \begin{macrocode} \int_incr:N \l_@@_number_of_notes_int % \end{macrocode} % We expand the content of the note at the point of use of % |\tabularnote| as does |\footnote|. % \begin{macrocode} \seq_gput_right:Nn \g_@@_tabularnotes_seq { #1 } \peek_meaning:NF \tabularnote { % \end{macrocode} % If the following token is \emph{not} a |\tabularnote|, we have finished the % sequence of successive commands |\tabularnote| and we have to format the % labels of these tabular notes (in the array). We compose those labels in a box % |\l_tmpa_box| because we will do a special construction in order to have this % box in a overlapping position if we are at the end of a cell. % \begin{macrocode} \hbox_set:Nn \l_tmpa_box { % \end{macrocode} % We remind that it is the command |\@@_notes_label_in_tabular:n| that will % (most of the time) put the labels in a |\textsuperscript|. % \begin{macrocode} \@@_notes_label_in_tabular:n { \stepcounter { tabularnote } \@@_notes_style:n { tabularnote } \prg_replicate:nn { \l_@@_number_of_notes_int - 1 } { , \stepcounter { tabularnote } \@@_notes_style:n { tabularnote } } } } % \end{macrocode} % We use |\refstepcounter| in order to have the (last) tabular note referenceable % (with the standard command |\label|) and that's why we have to go back with a % decrementation of the counter |tabularnote| first. % \begin{macrocode} \addtocounter { tabularnote } { -1 } \refstepcounter { tabularnote } \int_zero:N \l_@@_number_of_notes_int \hbox_overlap_right:n { \box_use:N \l_tmpa_box } % \end{macrocode} % If the command |\tabularnote| is used exactly at the end of the cell, the % |\unskip| (inserted by \pkg{array}?) will delete the skip we insert now % and the label of the footnote will be composed in an overlapping position (by % design). % \begin{macrocode} \skip_horizontal:n { \box_wd:N \l_tmpa_box } } } } } } % \end{macrocode} % % % % \subsection*{Command for creation of rectangle nodes} % % The following command should be used in a |{pgfpicture}|. It creates a % rectangle (empty but with a name). % % |#1| is the name of the node which will be created; % |#2| and |#3| are the coordinates of one of the corner of the rectangle; % |#4| and |#5| are the coordinates of the opposite corner. % \begin{macrocode} \cs_new_protected:Npn \@@_pgf_rect_node:nnnnn #1 #2 #3 #4 #5 { \begin { pgfscope } \pgfset { outer~sep = \c_zero_dim , inner~sep = \c_zero_dim , minimum~size = \c_zero_dim } \pgftransformshift { \pgfpoint { 0.5 * ( #2 + #4 ) } { 0.5 * ( #3 + #5 ) } } \pgfnode { rectangle } { center } { \vbox_to_ht:nn { \dim_abs:n { #5 - #3 } } { \vfill \hbox_to_wd:nn { \dim_abs:n { #4 - #2 } } { } } } { #1 } { } \end { pgfscope } } % \end{macrocode} % % \medskip % The command |\@@_pgf_rect_node:nnn| is a variant of |\@@_pgf_rect_node:nnnn|: % it takes two \textsc{pgf} points as arguments instead of the four dimensions % which are the coordinates. % \begin{macrocode} \cs_new_protected:Npn \@@_pgf_rect_node:nnn #1 #2 #3 { \begin { pgfscope } \pgfset { outer~sep = \c_zero_dim , inner~sep = \c_zero_dim , minimum~size = \c_zero_dim } \pgftransformshift { \pgfpointscale { 0.5 } { \pgfpointadd { #2 } { #3 } } } \pgfpointdiff { #3 } { #2 } \pgfgetlastxy \l_tmpa_dim \l_tmpb_dim \pgfnode { rectangle } { center } { \vbox_to_ht:nn { \dim_abs:n \l_tmpb_dim } { \vfill \hbox_to_wd:nn { \dim_abs:n \l_tmpa_dim } { } } } { #1 } { } \end { pgfscope } } % \end{macrocode} % % % \bigskip % \subsection*{The options} % % By default, the commands |\cellcolor| and |\rowcolor| are available for the % user in the cells of the tabular (the user may use the commands provided by % |\colortbl|). However, if the key |colortbl-like| is used, these % commands are available. % \begin{macrocode} \bool_new:N \l_@@_colortbl_like_bool % \end{macrocode} % % \bigskip % By default, the behaviour of |\cline| is changed in the environments of % \pkg{nicematrix}: a |\cline| spreads the array by an amount equal to % |\arrayrulewidht|. It's possible to disable this feature with the key % |\l_@@_standard_line_bool|. % \begin{macrocode} \bool_new:N \l_@@_standard_cline_bool % \end{macrocode} % % \bigskip % The following dimensions correspond to the options |cell-space-top-limit| and co % (these parameters are inspired by the package \pkg{cellspace}). % \begin{macrocode} \dim_new:N \l_@@_cell_space_top_limit_dim \dim_new:N \l_@@_cell_space_bottom_limit_dim % \end{macrocode} % % \bigskip % The following dimension is the distance between two dots for the dotted lines % (when |line-style| is equal to |standard|, which is the initial value). The % initial value is 0.45~em but it will be changed if the option |small| is used. % \begin{macrocode} \dim_new:N \l_@@_inter_dots_dim \AtBeginDocument { \dim_set:Nn \l_@@_inter_dots_dim { 0.45 em } } % \end{macrocode} % The |\AtBeginDocument| is only a security in case \cls{revtex4-1} is used % (even though it is obsolete). % % \bigskip % The following dimension is the minimal distance between a node (in fact an % anchor of that node) and a dotted line (we say ``minimal'' because, by % definition, a dotted line is not a continuous line and, therefore, this % distance may vary a little). % \begin{macrocode} \dim_new:N \l_@@_xdots_shorten_dim \AtBeginDocument { \dim_set:Nn \l_@@_xdots_shorten_dim { 0.3 em } } % \end{macrocode} % The |\AtBeginDocument| is only a security in case \cls{revtex4-1} is used % (even though it is obsolete). % % \bigskip % The following dimension is the radius of the dots for the dotted lines (when % |line-style| is equal to |standard|, which is the initial value). The initial % value is 0.53~pt but it will be changed if the option |small| is used. % \begin{macrocode} \dim_new:N \l_@@_radius_dim \AtBeginDocument { \dim_set:Nn \l_@@_radius_dim { 0.53 pt } } % \end{macrocode} % The |\AtBeginDocument| is only a security in case \cls{revtex4-1} is used % (even if it is obsolete). % % % \bigskip % The token list |\l_@@_xdots_line_style_tl| corresponds to the option |tikz| of the % commands |\Cdots|, |\Ldots|, etc. and of the options |line-style| for the % environments and |\NiceMatrixOptions|. The constant |\c_@@_standard_tl| will % be used in some tests. % \begin{macrocode} \tl_new:N \l_@@_xdots_line_style_tl \tl_const:Nn \c_@@_standard_tl { standard } \tl_set_eq:NN \l_@@_xdots_line_style_tl \c_@@_standard_tl % \end{macrocode} % % \bigskip % The boolean |\l_@@_light_syntax_bool| corresponds to the option |light-syntax|. % \begin{macrocode} \bool_new:N \l_@@_light_syntax_bool % \end{macrocode} % % \bigskip % The string |\l_@@_baseline_tl| may contain one of the three values |t|, % |c| or |b| as in the option of the environment |{array}|. However, it may also % contain an integer (which represents the number of the row to which align the % array). % \begin{macrocode} \tl_new:N \l_@@_baseline_tl \tl_set:Nn \l_@@_baseline_tl c % \end{macrocode} % % \bigskip % The flag |\l_@@_exterior_arraycolsep_bool| corresponds to the option % |exterior-arraycolsep|. If this option is set, a space equal to |\arraycolsep| % will be put on both sides of an environment |{NiceArray}| (as it is done in % |{array}| of \pkg{array}). % \begin{macrocode} \bool_new:N \l_@@_exterior_arraycolsep_bool % \end{macrocode} % % \bigskip % The flag |\l_@@_parallelize_diags_bool| controls whether the diagonals are % parallelized. The initial value is~|true|. % \begin{macrocode} \bool_new:N \l_@@_parallelize_diags_bool \bool_set_true:N \l_@@_parallelize_diags_bool % \end{macrocode} % % \bigskip % The following parameter correspond to the key |corners|. The elements of that % |clist| must be in |NW|, |SW|, |NE| and |SE|. % \begin{macrocode} \clist_new:N \l_@@_corners_clist % \end{macrocode} % % \bigskip % \begin{macrocode} \dim_new:N \l_@@_notes_above_space_dim \AtBeginDocument { \dim_set:Nn \l_@@_notes_above_space_dim { 1 mm } } % \end{macrocode} % The |\AtBeginDocument| is only a security in case \cls{revtex4-1} is used % (even if it is obsolete). % % \bigskip % The flag |\l_@@_nullify_dots_bool| corresponds to the option |nullify-dots|. % When the flag is down, the instructions like |\vdots| are inserted within a % |\hphantom| (and so the constructed matrix has exactly the same size as a % matrix constructed with the classical |{matrix}| and |\ldots|, |\vdots|, % etc.). % \begin{macrocode} \bool_new:N \l_@@_nullify_dots_bool % \end{macrocode} % % % \bigskip % The following flag will be used when the current options specify that all the % columns of the array must have the same width equal to the largest width of a % cell of the array (except the cells of the potential exterior columns). % \begin{macrocode} \bool_new:N \l_@@_auto_columns_width_bool % \end{macrocode} % % \bigskip % The following boolean corresponds to the key |create-cell-nodes| of the % keyword |\CodeBefore|. % \begin{macrocode} \bool_new:N \g_@@_recreate_cell_nodes_bool % \end{macrocode} % % \bigskip % The string |\l_@@_name_str| will contain the optional name of the % environment: this name can be used to access to the Tikz nodes created in the % array from outside the environment. % \begin{macrocode} \str_new:N \l_@@_name_str % \end{macrocode} % % \bigskip % The boolean |\l_@@_medium_nodes_bool| will be used to indicate whether the % ``medium nodes'' are created in the array. Idem for the ``large nodes''. % \begin{macrocode} \bool_new:N \l_@@_medium_nodes_bool \bool_new:N \l_@@_large_nodes_bool % \end{macrocode} % % \bigskip % The boolean |\l_@@_except_borders_bool| will be raised when the key % |hvlines-except-borders| will be used (but that key has also other effects). % \begin{macrocode} \bool_new:N \l_@@_except_borders_bool % \end{macrocode} % % % \bigskip % The dimension |\l_@@_left_margin_dim| correspond to the option |left-margin|. % Idem for the right margin. These parameters are involved in the creation of % the ``medium nodes'' but also in the placement of the delimiters and the % drawing of the horizontal dotted lines (|\hdottedline|). % \begin{macrocode} \dim_new:N \l_@@_left_margin_dim \dim_new:N \l_@@_right_margin_dim % \end{macrocode} % % % \bigskip % The dimensions |\l_@@_extra_left_margin_dim| and % |\l_@@_extra_right_margin_dim| correspond to the options |extra-left-margin| % and |extra-right-margin|. % \begin{macrocode} \dim_new:N \l_@@_extra_left_margin_dim \dim_new:N \l_@@_extra_right_margin_dim % \end{macrocode} % % \medskip % The token list |\l_@@_end_of_row_tl| corresponds to the option |end-of-row|. % It specifies the symbol used to mark the ends of rows when the light syntax is % used. % \begin{macrocode} \tl_new:N \l_@@_end_of_row_tl \tl_set:Nn \l_@@_end_of_row_tl { ; } % \end{macrocode} % % \medskip % The following parameter is for the color the dotted lines drawn by |\Cdots|, % |\Ldots|, |\Vdots|, |\Ddots|, |\Iddots| and |\Hdotsfor| but \emph{not} the % dotted lines drawn by |\hdottedline| and ``|:|''. % \begin{macrocode} \tl_new:N \l_@@_xdots_color_tl % \end{macrocode} % % \bigskip % The following token list corresponds to the key |delimiters/color|. % \begin{macrocode} \tl_new:N \l_@@_delimiters_color_tl % \end{macrocode} % % \bigskip % Sometimes, we want to have several arrays vertically juxtaposed in order to % have an alignment of the columns of these arrays. To acheive this goal, one % may wish to use the same width for all the columns (for example with the % option |columns-width| or the option |auto-columns-width| of the environment % |{NiceMatrixBlock}|). However, even if we use the same type of delimiters, the % width of the delimiters may be different from an array to another because the % width of the delimiter is fonction of its size. That's why we create an option % called |delimiters/max-width| which will give to the delimiters the width of % a delimiter (of the same type) of big size. The following boolean corresponds % to this option. % \begin{macrocode} \bool_new:N \l_@@_delimiters_max_width_bool % \end{macrocode} % % \bigskip % \begin{macrocode} \keys_define:nn { NiceMatrix / xdots } { line-style .code:n = { \bool_lazy_or:nnTF % \end{macrocode} % We can't use |\c_@@_tikz_loaded_bool| to test whether \pkg{tikz} is loaded % because |\NiceMatrixOptions| may be used in the preamble of the document. % \begin{macrocode} { \cs_if_exist_p:N \tikzpicture } { \str_if_eq_p:nn { #1 } { standard } } { \tl_set:Nn \l_@@_xdots_line_style_tl { #1 } } { \@@_error:n { bad~option~for~line-style } } } , line-style .value_required:n = true , color .tl_set:N = \l_@@_xdots_color_tl , color .value_required:n = true , shorten .dim_set:N = \l_@@_xdots_shorten_dim , shorten .value_required:n = true , % \end{macrocode} % The options |down| and |up| are not documented for the final user because he % should use the syntax with |^| and |_|. % \begin{macrocode} down .tl_set:N = \l_@@_xdots_down_tl , up .tl_set:N = \l_@@_xdots_up_tl , % \end{macrocode} % The key |draw-first|, which is meant to be used only with |\Ddots| and % |\Iddots|, which be catched when |\Ddots| or |\Iddots| is used (during the % construction of the array and not when we draw the dotted lines). % \begin{macrocode} draw-first .code:n = \prg_do_nothing: , unknown .code:n = \@@_error:n { Unknown~key~for~xdots } } % \end{macrocode} % % % \bigskip % \begin{macrocode} \keys_define:nn { NiceMatrix / rules } { color .tl_set:N = \l_@@_rules_color_tl , color .value_required:n = true , width .dim_set:N = \arrayrulewidth , width .value_required:n = true } % \end{macrocode} % % % \bigskip % First, we define a set of keys ``|NiceMatrix / Global|'' which will be used % (with the mechanism of |.inherit:n|) by other sets of keys. % % \begin{macrocode} \keys_define:nn { NiceMatrix / Global } { delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , delimiters .value_required:n = true , rules .code:n = \keys_set:nn { NiceMatrix / rules } { #1 } , rules .value_required:n = true , standard-cline .bool_set:N = \l_@@_standard_cline_bool , standard-cline .default:n = true , cell-space-top-limit .dim_set:N = \l_@@_cell_space_top_limit_dim , cell-space-top-limit .value_required:n = true , cell-space-bottom-limit .dim_set:N = \l_@@_cell_space_bottom_limit_dim , cell-space-bottom-limit .value_required:n = true , cell-space-limits .meta:n = { cell-space-top-limit = #1 , cell-space-bottom-limit = #1 , } , cell-space-limits .value_required:n = true , xdots .code:n = \keys_set:nn { NiceMatrix / xdots } { #1 } , light-syntax .bool_set:N = \l_@@_light_syntax_bool , light-syntax .default:n = true , end-of-row .tl_set:N = \l_@@_end_of_row_tl , end-of-row .value_required:n = true , first-col .code:n = \int_zero:N \l_@@_first_col_int , first-row .code:n = \int_zero:N \l_@@_first_row_int , last-row .int_set:N = \l_@@_last_row_int , last-row .default:n = -1 , code-for-first-col .tl_set:N = \l_@@_code_for_first_col_tl , code-for-first-col .value_required:n = true , code-for-last-col .tl_set:N = \l_@@_code_for_last_col_tl , code-for-last-col .value_required:n = true , code-for-first-row .tl_set:N = \l_@@_code_for_first_row_tl , code-for-first-row .value_required:n = true , code-for-last-row .tl_set:N = \l_@@_code_for_last_row_tl , code-for-last-row .value_required:n = true , hlines .clist_set:N = \l_@@_hlines_clist , vlines .clist_set:N = \l_@@_vlines_clist , hlines .default:n = all , vlines .default:n = all , vlines-in-sub-matrix .code:n = { \tl_if_single_token:nTF { #1 } { \tl_set:Nn \l_@@_letter_vlism_tl { #1 } } { \@@_error:n { One~letter~allowed } } } , vlines-in-sub-matrix .value_required:n = true , hvlines .code:n = { \clist_set:Nn \l_@@_vlines_clist { all } \clist_set:Nn \l_@@_hlines_clist { all } } , hvlines-except-borders .code:n = { \clist_set:Nn \l_@@_vlines_clist { all } \clist_set:Nn \l_@@_hlines_clist { all } \bool_set_true:N \l_@@_except_borders_bool } , parallelize-diags .bool_set:N = \l_@@_parallelize_diags_bool , % \end{macrocode} % % \bigskip % With the option |renew-dots|, the command |\cdots|, |\ldots|, |\vdots|, % |\ddots|, etc. are redefined and behave like the commands |\Cdots|, |\Ldots|, % |\Vdots|, |\Ddots|, etc. % \begin{macrocode} renew-dots .bool_set:N = \l_@@_renew_dots_bool , renew-dots .value_forbidden:n = true , nullify-dots .bool_set:N = \l_@@_nullify_dots_bool , create-medium-nodes .bool_set:N = \l_@@_medium_nodes_bool , create-large-nodes .bool_set:N = \l_@@_large_nodes_bool , create-extra-nodes .meta:n = { create-medium-nodes , create-large-nodes } , left-margin .dim_set:N = \l_@@_left_margin_dim , left-margin .default:n = \arraycolsep , right-margin .dim_set:N = \l_@@_right_margin_dim , right-margin .default:n = \arraycolsep , margin .meta:n = { left-margin = #1 , right-margin = #1 } , margin .default:n = \arraycolsep , extra-left-margin .dim_set:N = \l_@@_extra_left_margin_dim , extra-right-margin .dim_set:N = \l_@@_extra_right_margin_dim , extra-margin .meta:n = { extra-left-margin = #1 , extra-right-margin = #1 } , extra-margin .value_required:n = true , } % \end{macrocode} % % \bigskip % We define a set of keys used by the environments of \pkg{nicematrix} (but not % by the command |\NiceMatrixOptions|). % \begin{macrocode} \keys_define:nn { NiceMatrix / Env } { % \end{macrocode} % The key |hvlines-except-corners| is now deprecated (use |hvlines| and % |corners| instead). % \begin{macrocode} hvlines-except-corners .code:n = { \clist_set:Nn \l_@@_corners_clist { #1 } \clist_set:Nn \l_@@_vlines_clist { all } \clist_set:Nn \l_@@_hlines_clist { all } } , hvlines-except-corners .default:n = { NW , SW , NE , SE } , corners .clist_set:N = \l_@@_corners_clist , corners .default:n = { NW , SW , NE , SE } , code-before .code:n = { \tl_if_empty:nF { #1 } { \tl_put_right:Nn \l_@@_code_before_tl { #1 } \bool_set_true:N \l_@@_code_before_bool } } , % \end{macrocode} % \bigskip % The options |c|, |t| and |b| of the environment |{NiceArray}| have the same % meaning as the option of the classical environment |{array}|. % \begin{macrocode} c .code:n = \tl_set:Nn \l_@@_baseline_tl c , t .code:n = \tl_set:Nn \l_@@_baseline_tl t , b .code:n = \tl_set:Nn \l_@@_baseline_tl b , baseline .tl_set:N = \l_@@_baseline_tl , baseline .value_required:n = true , columns-width .code:n = \tl_if_eq:nnTF { #1 } { auto } { \bool_set_true:N \l_@@_auto_columns_width_bool } { \dim_set:Nn \l_@@_columns_width_dim { #1 } } , columns-width .value_required:n = true , name .code:n = % \end{macrocode} % We test whether we are in the measuring phase of an environment of % \pkg{amsmath} (always loaded by \pkg{nicematrix}) because we want to avoid a % fallacious message of duplicate name in this case. % \begin{macrocode} \legacy_if:nF { measuring@ } { \str_set:Nn \l_tmpa_str { #1 } \seq_if_in:NVTF \g_@@_names_seq \l_tmpa_str { \@@_error:nn { Duplicate~name } { #1 } } { \seq_gput_left:NV \g_@@_names_seq \l_tmpa_str } \str_set_eq:NN \l_@@_name_str \l_tmpa_str } , name .value_required:n = true , code-after .tl_gset:N = \g_nicematrix_code_after_tl , code-after .value_required:n = true , colortbl-like .code:n = \bool_set_true:N \l_@@_colortbl_like_bool \bool_set_true:N \l_@@_code_before_bool , colortbl-like .value_forbidden:n = true } % \end{macrocode} % % \begin{macrocode} \keys_define:nn { NiceMatrix / notes } { para .bool_set:N = \l_@@_notes_para_bool , para .default:n = true , code-before .tl_set:N = \l_@@_notes_code_before_tl , code-before .value_required:n = true , code-after .tl_set:N = \l_@@_notes_code_after_tl , code-after .value_required:n = true , bottomrule .bool_set:N = \l_@@_notes_bottomrule_bool , bottomrule .default:n = true , style .code:n = \cs_set:Nn \@@_notes_style:n { #1 } , style .value_required:n = true , label-in-tabular .code:n = \cs_set:Nn \@@_notes_label_in_tabular:n { #1 } , label-in-tabular .value_required:n = true , label-in-list .code:n = \cs_set:Nn \@@_notes_label_in_list:n { #1 } , label-in-list .value_required:n = true , enumitem-keys .code:n = { \bool_if:NTF \c_@@_in_preamble_bool { \AtBeginDocument { \bool_if:NT \c_@@_enumitem_loaded_bool { \setlist* [ tabularnotes ] { #1 } } } } { \bool_if:NT \c_@@_enumitem_loaded_bool { \setlist* [ tabularnotes ] { #1 } } } } , enumitem-keys .value_required:n = true , enumitem-keys-para .code:n = { \bool_if:NTF \c_@@_in_preamble_bool { \AtBeginDocument { \bool_if:NT \c_@@_enumitem_loaded_bool { \setlist* [ tabularnotes* ] { #1 } } } } { \bool_if:NT \c_@@_enumitem_loaded_bool { \setlist* [ tabularnotes* ] { #1 } } } } , enumitem-keys-para .value_required:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~notes } } % \end{macrocode} % % \begin{macrocode} \keys_define:nn { NiceMatrix / delimiters } { max-width .bool_set:N = \l_@@_delimiters_max_width_bool , max-width .default:n = true , color .tl_set:N = \l_@@_delimiters_color_tl , color .value_required:n = true , } % \end{macrocode} % % \bigskip % We begin the construction of the major sets of keys (used by the different % user commands and environments). % \begin{macrocode} \keys_define:nn { NiceMatrix } { NiceMatrixOptions .inherit:n = { NiceMatrix / Global } , NiceMatrixOptions / xdots .inherit:n = NiceMatrix / xdots , NiceMatrixOptions / rules .inherit:n = NiceMatrix / rules , NiceMatrixOptions / notes .inherit:n = NiceMatrix / notes , NiceMatrixOptions / delimiters .inherit:n = NiceMatrix / delimiters , NiceMatrixOptions / sub-matrix .inherit:n = NiceMatrix / sub-matrix , SubMatrix / rules .inherit:n = NiceMatrix / rules , CodeAfter / xdots .inherit:n = NiceMatrix / xdots , NiceMatrix .inherit:n = { NiceMatrix / Global , NiceMatrix / Env , } , NiceMatrix / xdots .inherit:n = NiceMatrix / xdots , NiceMatrix / rules .inherit:n = NiceMatrix / rules , NiceMatrix / delimiters .inherit:n = NiceMatrix / delimiters , NiceTabular .inherit:n = { NiceMatrix / Global , NiceMatrix / Env } , NiceTabular / xdots .inherit:n = NiceMatrix / xdots , NiceTabular / rules .inherit:n = NiceMatrix / rules , NiceTabular / delimiters .inherit:n = NiceMatrix / delimiters , NiceArray .inherit:n = { NiceMatrix / Global , NiceMatrix / Env , } , NiceArray / xdots .inherit:n = NiceMatrix / xdots , NiceArray / rules .inherit:n = NiceMatrix / rules , NiceArray / delimiters .inherit:n = NiceMatrix / delimiters , pNiceArray .inherit:n = { NiceMatrix / Global , NiceMatrix / Env , } , pNiceArray / xdots .inherit:n = NiceMatrix / xdots , pNiceArray / rules .inherit:n = NiceMatrix / rules , pNiceArray / delimiters .inherit:n = NiceMatrix / delimiters , } % \end{macrocode} % % % \bigskip % We finalise the definition of the set of keys % ``|NiceMatrix / NiceMatrixOptions|'' with the options specific to % |\NiceMatrixOptions|. % \begin{macrocode} \keys_define:nn { NiceMatrix / NiceMatrixOptions } { last-col .code:n = \tl_if_empty:nF { #1 } { \@@_error:n { last-col~non~empty~for~NiceMatrixOptions } } \int_zero:N \l_@@_last_col_int , small .bool_set:N = \l_@@_small_bool , small .value_forbidden:n = true , % \end{macrocode} % % With the option |renew-matrix|, the environment |{matrix}| of \pkg{amsmath} % and its variants are redefined to behave like the environment |{NiceMatrix}| % and its variants. % \begin{macrocode} renew-matrix .code:n = \@@_renew_matrix: , renew-matrix .value_forbidden:n = true , % \end{macrocode} % The key |transparent| is now considered as obsolete (because its name is ambiguous). % \begin{macrocode} transparent .code:n = { \@@_renew_matrix: \bool_set_true:N \l_@@_renew_dots_bool \@@_error:n { Key~transparent } } , transparent .value_forbidden:n = true, % \end{macrocode} % % % \bigskip % The option |exterior-arraycolsep| will have effect only in |{NiceArray}| for % those who want to have for |{NiceArray}| the same behaviour as |{array}|. % \begin{macrocode} exterior-arraycolsep .bool_set:N = \l_@@_exterior_arraycolsep_bool , % \end{macrocode} % % \bigskip % If the option |columns-width| is used, all the columns will have the same % width. % % In |\NiceMatrixOptions|, the special value |auto| is not available. % \begin{macrocode} columns-width .code:n = \tl_if_eq:nnTF { #1 } { auto } { \@@_error:n { Option~auto~for~columns-width } } { \dim_set:Nn \l_@@_columns_width_dim { #1 } } , % \end{macrocode} % % \bigskip % Usually, an error is raised when the user tries to give the same name to two % distincts environments of \pkg{nicematrix} (theses names are global and not % local to the current TeX scope). However, the option |allow-duplicate-names| % disables this feature. % \begin{macrocode} allow-duplicate-names .code:n = \@@_msg_redirect_name:nn { Duplicate~name } { none } , allow-duplicate-names .value_forbidden:n = true , % \end{macrocode} % % \bigskip % By default, the specifier used in the preamble of the array (for example in % |{pNiceArray}|) to draw a vertical dotted line between two columns is the % colon ``|:|''. However, it's possible to change this letter with % |letter-for-dotted-lines| and, by the way, the letter ``|:|'' will remain free % for other packages (for example \pkg{arydshln}). % \begin{macrocode} letter-for-dotted-lines .code:n = { \tl_if_single_token:nTF { #1 } { \str_set:Nx \l_@@_letter_for_dotted_lines_str { #1 } } { \@@_error:n { One~letter~allowed } } } , letter-for-dotted-lines .value_required:n = true , notes .code:n = \keys_set:nn { NiceMatrix / notes } { #1 } , notes .value_required:n = true , sub-matrix .code:n = \keys_set:nn { NiceMatrix / sub-matrix } { #1 } , sub-matrix .value_required:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~NiceMatrixOptions } } % \end{macrocode} % % % \begin{macrocode} \str_new:N \l_@@_letter_for_dotted_lines_str \str_set_eq:NN \l_@@_letter_for_dotted_lines_str \c_colon_str % \end{macrocode} % % \bigskip % |\NiceMatrixOptions| is the command of the \pkg{nicematrix} package to fix % options at the document level. The scope of these specifications is the % current TeX group. % \begin{macrocode} \NewDocumentCommand \NiceMatrixOptions { m } { \keys_set:nn { NiceMatrix / NiceMatrixOptions } { #1 } } % \end{macrocode} % % % \bigskip % We finalise the definition of the set of keys % ``|NiceMatrix / NiceMatrix|'' with the options specific to |{NiceMatrix}|. % % \begin{macrocode} \keys_define:nn { NiceMatrix / NiceMatrix } { last-col .code:n = \tl_if_empty:nTF {#1} { \bool_set_true:N \l_@@_last_col_without_value_bool \int_set:Nn \l_@@_last_col_int { -1 } } { \int_set:Nn \l_@@_last_col_int { #1 } } , l .code:n = \tl_set:Nn \l_@@_type_of_col_tl l , r .code:n = \tl_set:Nn \l_@@_type_of_col_tl r , small .bool_set:N = \l_@@_small_bool , small .value_forbidden:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~NiceMatrix } } % \end{macrocode} % % % % \bigskip % We finalise the definition of the set of keys ``|NiceMatrix / NiceArray|'' % with the options specific to |{NiceArray}|. % % \begin{macrocode} \keys_define:nn { NiceMatrix / NiceArray } { % \end{macrocode} % % In the environments |{NiceArray}| and its variants, the option |last-col| must % be used without value because the number of columns of the array is read % from the preamble of the array. % \begin{macrocode} small .bool_set:N = \l_@@_small_bool , small .value_forbidden:n = true , last-col .code:n = \tl_if_empty:nF { #1 } { \@@_error:n { last-col~non~empty~for~NiceArray } } \int_zero:N \l_@@_last_col_int , notes / para .bool_set:N = \l_@@_notes_para_bool , notes / para .default:n = true , notes / bottomrule .bool_set:N = \l_@@_notes_bottomrule_bool , notes / bottomrule .default:n = true , tabularnote .tl_set:N = \l_@@_tabularnote_tl , tabularnote .value_required:n = true , r .code:n = \@@_error:n { r~or~l~with~preamble } , l .code:n = \@@_error:n { r~or~l~with~preamble } , unknown .code:n = \@@_error:n { Unknown~key~for~NiceArray } } % \end{macrocode} % % % % \begin{macrocode} \keys_define:nn { NiceMatrix / pNiceArray } { first-col .code:n = \int_zero:N \l_@@_first_col_int , last-col .code:n = \tl_if_empty:nF {#1} { \@@_error:n { last-col~non~empty~for~NiceArray } } \int_zero:N \l_@@_last_col_int , first-row .code:n = \int_zero:N \l_@@_first_row_int , small .bool_set:N = \l_@@_small_bool , small .value_forbidden:n = true , r .code:n = \@@_error:n { r~or~l~with~preamble } , l .code:n = \@@_error:n { r~or~l~with~preamble } , unknown .code:n = \@@_error:n { Unknown~key~for~NiceMatrix } } % \end{macrocode} % % \bigskip % We finalise the definition of the set of keys ``|NiceMatrix / NiceTabular|'' % with the options specific to |{NiceTabular}|. % % \begin{macrocode} \keys_define:nn { NiceMatrix / NiceTabular } { % \end{macrocode} % The dimension |width| will be used if at least a column of type |X| is used. % \begin{macrocode} width .code:n = \dim_set:Nn \l_@@_width_dim { #1 } \bool_set_true:N \l_@@_width_used_bool , width .value_required:n = true , notes / para .bool_set:N = \l_@@_notes_para_bool , notes / para .default:n = true , notes / bottomrule .bool_set:N = \l_@@_notes_bottomrule_bool , notes / bottomrule .default:n = true , tabularnote .tl_set:N = \l_@@_tabularnote_tl , tabularnote .value_required:n = true , last-col .code:n = \tl_if_empty:nF {#1} { \@@_error:n { last-col~non~empty~for~NiceArray } } \int_zero:N \l_@@_last_col_int , r .code:n = \@@_error:n { r~or~l~with~preamble } , l .code:n = \@@_error:n { r~or~l~with~preamble } , unknown .code:n = \@@_error:n { Unknown~key~for~NiceTabular } } % \end{macrocode} % % \bigskip % \subsection*{Important code used by \{NiceArrayWithDelims\} } % % The pseudo-environment |\@@_cell_begin:w|--|\@@_cell_end:| will be used to format the % cells of the array. In the code, the affectations are global because this % pseudo-environment will be used in the cells of a |\halign| (via an % environment |{array}|). % % \begin{macrocode} \cs_new_protected:Npn \@@_cell_begin:w { % \end{macrocode} % The token list |\g_@@_post_action_cell_tl| will be set during the % composition of the box |\l_@@_cell_box| and will be used \emph{after} the % composition in order to modify that box (that's why it's called a % \emph{post-action}). % \begin{macrocode} \tl_gclear:N \g_@@_post_action_cell_tl % \end{macrocode} % At the beginning of the cell, we link |\CodeAfter| to a command which do % \emph{not} begin with |\omit| (whereas the standard version of |\CodeAfter| % begins with |\omit|). % \begin{macrocode} \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i:n % \end{macrocode} % We increment |\c@jCol|, which is the counter of the columns. % \begin{macrocode} \int_gincr:N \c@jCol % \end{macrocode} % Now, we increment the counter of the rows. We don't do this incrementation in % the |\everycr| because some packages, like \pkg{arydshln}, create special rows % in the |\halign| that we don't want to take into account. % \begin{macrocode} \int_compare:nNnT \c@jCol = 1 { \int_compare:nNnT \l_@@_first_col_int = 1 \@@_begin_of_row: } % \end{macrocode} % The content of the cell is composed in the box |\l_@@_cell_box| because we want % to compute some dimensions of the box. The |\hbox_set_end:| corresponding to % this |\hbox_set:Nw| will be in the |\@@_cell_end:| (and the potential % |\c_math_toggle_token| also). % \begin{macrocode} \hbox_set:Nw \l_@@_cell_box \bool_if:NF \l_@@_NiceTabular_bool { \c_math_toggle_token \bool_if:NT \l_@@_small_bool \scriptstyle } % \end{macrocode} % % We will call \emph{corners} of the matrix the cases which are at the % intersection of the exterior rows and exterior columns (of course, the four % corners doesn't always exist simultaneously). % % The codes |\l_@@_code_for_first_row_tl| and \emph{al} don't apply in the % corners of the matrix. % \begin{macrocode} \g_@@_row_style_tl \int_compare:nNnTF \c@iRow = 0 { \int_compare:nNnT \c@jCol > 0 { \l_@@_code_for_first_row_tl \xglobal \colorlet { nicematrix-first-row } { . } } } { \int_compare:nNnT \c@iRow = \l_@@_last_row_int { \l_@@_code_for_last_row_tl \xglobal \colorlet { nicematrix-last-row } { . } } } } % \end{macrocode} % % \interitem % The following macro |\@@_begin_of_row| is usually used in the cell % number~$1$ of the row. However, when the key |first-col| is used, % |\@@_begin_of_row| is executed in the cell number~$0$ of the row. % \begin{macrocode} \cs_new_protected:Npn \@@_begin_of_row: { \tl_gclear:N \g_@@_row_style_tl \int_gincr:N \c@iRow \dim_gset_eq:NN \g_@@_dp_ante_last_row_dim \g_@@_dp_last_row_dim \dim_gset:Nn \g_@@_dp_last_row_dim { \box_dp:N \@arstrutbox } \dim_gset:Nn \g_@@_ht_last_row_dim { \box_ht:N \@arstrutbox } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - row - \int_use:N \c@iRow - base } { \pgfpoint \c_zero_dim { 0.5 \arrayrulewidth } } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - row - \int_use:N \c@iRow - base } { \@@_env: - row - \int_use:N \c@iRow - base } } \endpgfpicture } % \end{macrocode} % Remark: If the key |recreate-cell-nodes| of the |\CodeBefore| is used, then we % will add some lines to that command. % % % \interitem % The following code is used in each cell of the array. It actualises quantities % that, at the end of the array, will give informations about the vertical % dimension of the two first rows and the two last rows. If the user uses the % |last-row|, some lines of code will be dynamically added to this command. % \begin{macrocode} \cs_new_protected:Npn \@@_update_for_first_and_last_row: { \int_compare:nNnTF \c@iRow = 0 { \dim_gset:Nn \g_@@_dp_row_zero_dim { \dim_max:nn \g_@@_dp_row_zero_dim { \box_dp:N \l_@@_cell_box } } \dim_gset:Nn \g_@@_ht_row_zero_dim { \dim_max:nn \g_@@_ht_row_zero_dim { \box_ht:N \l_@@_cell_box } } } { \int_compare:nNnT \c@iRow = 1 { \dim_gset:Nn \g_@@_ht_row_one_dim { \dim_max:nn \g_@@_ht_row_one_dim { \box_ht:N \l_@@_cell_box } } } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_rotate_cell_box: { \box_rotate:Nn \l_@@_cell_box { 90 } \int_compare:nNnT \c@iRow = \l_@@_last_row_int { \vbox_set_top:Nn \l_@@_cell_box { \vbox_to_zero:n { } \skip_vertical:n { - \box_ht:N \@arstrutbox + 0.8 ex } \box_use:N \l_@@_cell_box } } \bool_gset_false:N \g_@@_rotate_bool } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_adjust_size_box: { \dim_compare:nNnT \g_@@_blocks_wd_dim > \c_zero_dim { \box_set_wd:Nn \l_@@_cell_box { \dim_max:nn { \box_wd:N \l_@@_cell_box } \g_@@_blocks_wd_dim } \dim_gzero:N \g_@@_blocks_wd_dim } \dim_compare:nNnT \g_@@_blocks_dp_dim > \c_zero_dim { \box_set_dp:Nn \l_@@_cell_box { \dim_max:nn { \box_dp:N \l_@@_cell_box } \g_@@_blocks_dp_dim } \dim_gzero:N \g_@@_blocks_dp_dim } \dim_compare:nNnT \g_@@_blocks_ht_dim > \c_zero_dim { \box_set_ht:Nn \l_@@_cell_box { \dim_max:nn { \box_ht:N \l_@@_cell_box } \g_@@_blocks_ht_dim } \dim_gzero:N \g_@@_blocks_ht_dim } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_cell_end: { \@@_math_toggle_token: \hbox_set_end: % \end{macrocode} % The token list |\g_@@_post_action_cell_tl| is (potentially) set during the % composition of the box |\l_@@_cell_box| and is used now \emph{after} the % composition in order to modify that box. % \begin{macrocode} \g_@@_post_action_cell_tl \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: \@@_adjust_size_box: % \end{macrocode} % % \begin{macrocode} \box_set_ht:Nn \l_@@_cell_box { \box_ht:N \l_@@_cell_box + \l_@@_cell_space_top_limit_dim } \box_set_dp:Nn \l_@@_cell_box { \box_dp:N \l_@@_cell_box + \l_@@_cell_space_bottom_limit_dim } % \end{macrocode} % % We want to compute in |\g_@@_max_cell_width_dim| the width of the widest cell % of the array (except the cells of the ``first column'' and the ``last % column''). % \begin{macrocode} \dim_gset:Nn \g_@@_max_cell_width_dim { \dim_max:nn \g_@@_max_cell_width_dim { \box_wd:N \l_@@_cell_box } } % \end{macrocode} % % The following computations are for the ``first row'' and the ``last row''. % \begin{macrocode} \@@_update_for_first_and_last_row: % \end{macrocode} % % \medskip % If the cell is empty, or may be considered as if, we must not create the % \textsc{pgf} node, for two reasons: % \begin{itemize} % \item it's a waste of time since such a node would be rather pointless; % \item we test the existence of these nodes in order to determine whether a % cell is empty when we search the extremities of a dotted line. % \end{itemize} % However, it's very difficult to determine whether a cell is empty. Up to now % we use the following technic: % \begin{itemize} % \item if the width of the box |\l_@@_cell_box| (created with the content of % the cell) is equal to zero, we consider the cell as empty (however, % this is not perfect since the user may have used a |\rlap|, a |\llap| or a % |\mathclap| of \pkg{mathtools}. % \item the cells with a command |\Ldots| or |\Cdots|, |\Vdots|, etc., % should also be considered as empty; if |nullify-dots| is in force, there would % be nothing to do (in this case the previous commands only write an instruction % in a kind of |\CodeAfter|); however, if |nullify-dots| is not in force, a % phantom of |\ldots|, |\cdots|, |\vdots| is inserted and its width is not equal % to zero; that's why these commands raise a boolean |\g_@@_empty_cell_bool| and % we begin by testing this boolean. % \end{itemize} % \begin{macrocode} \bool_if:NTF \g_@@_empty_cell_bool { \box_use_drop:N \l_@@_cell_box } { \bool_lazy_or:nnTF \g_@@_not_empty_cell_bool { \dim_compare_p:nNn { \box_wd:N \l_@@_cell_box } > \c_zero_dim } \@@_node_for_cell: { \box_use_drop:N \l_@@_cell_box } } \int_gset:Nn \g_@@_col_total_int { \int_max:nn \g_@@_col_total_int \c@jCol } \bool_gset_false:N \g_@@_empty_cell_bool \bool_gset_false:N \g_@@_not_empty_cell_bool } % \end{macrocode} % % \medskip % The following command creates the \textsc{pgf} name of the node with, of % course, |\l_@@_cell_box| as the content. % \begin{macrocode} \cs_new_protected:Npn \@@_node_for_cell: { \pgfpicture \pgfsetbaseline \c_zero_dim \pgfrememberpicturepositiononpagetrue \pgfset { inner~sep = \c_zero_dim , minimum~width = \c_zero_dim } \pgfnode { rectangle } { base } { \box_use_drop:N \l_@@_cell_box } { \@@_env: - \int_use:N \c@iRow - \int_use:N \c@jCol } { } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - \int_use:N \c@iRow - \int_use:N \c@jCol } { \@@_env: - \int_use:N \c@iRow - \int_use:N \c@jCol } } \endpgfpicture } % \end{macrocode} % % \medskip % As its name says, the following command is a patch for the command % |\@@_node_for_cell:|. This patch will be appended on the left of % |\@@_node_for_the_cell:| when the construction of the cell nodes (of the form % |(i-j)|) in the |\CodeBefore| is required. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_node_for_cell:n #1 { \cs_new_protected:Npn \@@_patch_node_for_cell: { \hbox_set:Nn \l_@@_cell_box { \box_move_up:nn { \box_ht:N \l_@@_cell_box} \hbox_overlap_left:n { \pgfsys@markposition { \@@_env: - \int_use:N \c@iRow - \int_use:N \c@jCol - NW } % \end{macrocode} % I don't know why the following adjustement is needed when the compilation is % done with XeLaTeX or with the classical way |latex|, |divps|, |ps2pdf| (or % Adobe Distiller). However, it seems to work. % \begin{macrocode} #1 } \box_use:N \l_@@_cell_box \box_move_down:nn { \box_dp:N \l_@@_cell_box } \hbox_overlap_left:n { \pgfsys@markposition { \@@_env: - \int_use:N \c@iRow - \int_use:N \c@jCol - SE } #1 } } } } % \end{macrocode} % % \bigskip % We have no explanation for the different behaviour between the TeX engines... % \begin{macrocode} \bool_lazy_or:nnTF \sys_if_engine_xetex_p: \sys_if_output_dvi_p: { \@@_patch_node_for_cell:n { \skip_horizontal:n { 0.5 \box_wd:N \l_@@_cell_box } } } { \@@_patch_node_for_cell:n { } } % \end{macrocode} % % % \interitem % The second argument of the following command |\@@_instruction_of_type:nnn| % defined below is the type of the instruction (|Cdots|, |Vdots|, |Ddots|, % etc.). The third argument is the list of options. This command writes in the % corresponding |\g_@@_|\textsl{type}|_lines_tl| the instruction which will % actually draw the line after the construction of the matrix. % % \medskip % For example, for the following matrix, % % \smallskip % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % \begin{pNiceMatrix} % 1 & 2 & 3 & 4 \\ % 5 & \Cdots & & 6 \\ % 7 & \Cdots[color=red] % \end{pNiceMatrix} % \end{BVerbatim} % $\begin{pNiceMatrix} % 1 & 2 & 3 & 4 \\ % 5 & \Cdots & & 6 \\ % 7 & \Cdots[color=red] % \end{pNiceMatrix}$ % % \smallskip % the content of |\g_@@_Cdots_lines_tl| will be: % % \smallskip % \begin{scope} % \color{gray} % |\@@_draw_Cdots:nnn {2}{2}{}| % % |\@@_draw_Cdots:nnn {3}{2}{color=red}| % \end{scope} % % % \bigskip % The first argument is a boolean which indicates whether you must put the % instruction on the left or on the right on the list of instructions. % \begin{macrocode} \cs_new_protected:Npn \@@_instruction_of_type:nnn #1 #2 #3 { \bool_if:nTF { #1 } \tl_gput_left:cx \tl_gput_right:cx { g_@@_ #2 _ lines _ tl } { \use:c { @@ _ draw _ #2 : nnn } { \int_use:N \c@iRow } { \int_use:N \c@jCol } { \exp_not:n { #3 } } } } % \end{macrocode} % % % \bigskip % We want to use |\array| of \pkg{array}. However, if the class used is % \cls{revtex4-1} or \cls{revtex4-2}, we have to do some tuning and use the % command |\@array@array| instead of |\array| because these classes do a % redefinition of |\array| incompatible with our use of |\array|. % % \begin{macrocode} \cs_new_protected:Npn \@@_revtex_array: { \cs_set_eq:NN \@acoll \@arrayacol \cs_set_eq:NN \@acolr \@arrayacol \cs_set_eq:NN \@acol \@arrayacol \cs_set_nopar:Npn \@halignto { } \@array@array } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_array: { \bool_if:NTF \c_@@_revtex_bool \@@_revtex_array: { \bool_if:NTF \l_@@_NiceTabular_bool { \dim_set_eq:NN \col@sep \tabcolsep } { \dim_set_eq:NN \col@sep \arraycolsep } \dim_compare:nNnTF \l_@@_tabular_width_dim = \c_zero_dim { \cs_set_nopar:Npn \@halignto { } } { \cs_set_nopar:Npx \@halignto { to \dim_use:N \l_@@_tabular_width_dim } } % \end{macrocode} % It \pkg{colortbl} is loaded, |\@tabarray| has been redefined to incorporate % |\CT@start|. % \begin{macrocode} \@tabarray } % \end{macrocode} % |\l_@@_baseline_tl| may have the value |t|, |c| or |b|. However, if the value % is |b|, we compose the |\array| (of \pkg{array}) with the option |t| and the % right translation will be done further. Remark that |\str_if_eq:VnTF| is % fully expandable and you need something fully expandable here. % \begin{macrocode} [ \str_if_eq:VnTF \l_@@_baseline_tl c c t ] } % \end{macrocode} % % \medskip % We keep in memory the standard version of |\ialign| because we will redefine % |\ialign| in the environment |{NiceArrayWithDelims}| but restore the standard % version for use in the cells of the array. % \begin{macrocode} \cs_set_eq:NN \@@_old_ialign: \ialign % \end{macrocode} % % % The following command creates a |row| node (and not a row of nodes!). % \begin{macrocode} \cs_new_protected:Npn \@@_create_row_node: { % \end{macrocode} % The |\hbox:n| (or |\hbox|) is mandatory. % \begin{macrocode} \hbox { \bool_if:NT \l_@@_code_before_bool { \vtop { \skip_vertical:N 0.5\arrayrulewidth \pgfsys@markposition { \@@_env: - row - \@@_succ:n \c@iRow } \skip_vertical:N -0.5\arrayrulewidth } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - row - \@@_succ:n \c@iRow } { \pgfpoint \c_zero_dim { - 0.5 \arrayrulewidth } } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - row - \@@_succ:n \c@iRow } { \@@_env: - row - \@@_succ:n \c@iRow } } \endpgfpicture } } % \end{macrocode} % % % % \bigskip % The following must \emph{not} be protected because it begins with |\noalign|. % \begin{macrocode} \cs_new:Npn \@@_everycr: { \noalign { \@@_everycr_i: } } % \end{macrocode} % % % \begin{macrocode} \cs_new_protected:Npn \@@_everycr_i: { \int_gzero:N \c@jCol \bool_gset_false:N \g_@@_after_col_zero_bool \bool_if:NF \g_@@_row_of_col_done_bool { \@@_create_row_node: % \end{macrocode} % We don't draw the rules of the key |hlines| (or |hvlines|) but we reserve the % vertical space for theses rules. % \begin{macrocode} \tl_if_empty:NF \l_@@_hlines_clist { \tl_if_eq:NnF \l_@@_hlines_clist { all } { \exp_args:NNx \clist_if_in:NnT \l_@@_hlines_clist { \@@_succ:n \c@iRow } } { % \end{macrocode} % The counter |\c@iRow| has the value $-1$ only if there is a ``first % row'' and that we are before that ``first row'', i.e. just before the % beginning of the array. % \begin{macrocode} \int_compare:nNnT \c@iRow > { -1 } { \int_compare:nNnF \c@iRow = \l_@@_last_row_int % \end{macrocode} % The command |\CT@arc@| is a command of \pkg{colortbl} which sets the color of % the rules in the array. The package \pkg{nicematrix} uses it even if % \pkg{colortbl} is not loaded. We use a TeX group in order to limit the scope % of |\CT@arc@|. % \begin{macrocode} { \hrule height \arrayrulewidth width \c_zero_dim } } } } } } % \end{macrocode} % % \bigskip % The command |\@@_newcolumntype| is the command |\newcolumntype| of % \pkg{array} without the warnings for redefinitions of columns types (we will % use it to redefine the columns types |w| and |W|). % \begin{macrocode} \cs_set_protected:Npn \@@_newcolumntype #1 { \cs_set:cpn { NC @ find @ #1 } ##1 #1 { \NC@ { ##1 } } \peek_meaning:NTF [ { \newcol@ #1 } { \newcol@ #1 [ 0 ] } } % \end{macrocode} % % % \bigskip % When the key |renew-dots| is used, the following code will be executed. % \begin{macrocode} \cs_set_protected:Npn \@@_renew_dots: { \cs_set_eq:NN \ldots \@@_Ldots \cs_set_eq:NN \cdots \@@_Cdots \cs_set_eq:NN \vdots \@@_Vdots \cs_set_eq:NN \ddots \@@_Ddots \cs_set_eq:NN \iddots \@@_Iddots \cs_set_eq:NN \dots \@@_Ldots \cs_set_eq:NN \hdotsfor \@@_Hdotsfor: } % \end{macrocode} % % \bigskip % When the key |colortbl-like| is used, the following code will be executed. % \begin{macrocode} \cs_new_protected:Npn \@@_colortbl_like: { \cs_set_eq:NN \cellcolor \@@_cellcolor_tabular \cs_set_eq:NN \rowcolor \@@_rowcolor_tabular \cs_set_eq:NN \columncolor \@@_columncolor_preamble } % \end{macrocode} % % \bigskip % The following code |\@@_pre_array_ii:| is used in |{NiceArrayWithDelims}|. It % exists as a standalone macro only for legibility. % \label{prearray} % % \begin{macrocode} \cs_new_protected:Npn \@@_pre_array_ii: { % \end{macrocode} % The number of letters |X| in the preamble of the array. % \begin{macrocode} \int_gzero:N \g_@@_total_X_weight_int % \end{macrocode} % If \pkg{booktabs} is loaded, we have to patch the macro |\@BTnormal| which is % a macro of \pkg{booktabs}. The macro |\@BTnormal| draws an horizontal rule but % it occurs after a vertical skip done by a low level TeX command. When this % macro |\@BTnormal| occurs, the |row| node has yet been inserted by % \pkg{nicematrix} \emph{before} the vertical skip (and thus, at a wrong place). % That why we decide to create a new |row| node (for the same row). We patch the % macro |\@BTnormal| to create this |row| node. This new |row| node will % overwrite the previous definition of that |row| node and we have managed to % avoid the error messages of that redefinition % \footnote{cf. |\nicematrix@redefine@check@rerun|}. % \begin{macrocode} \bool_if:NT \c_@@_booktabs_loaded_bool { \tl_put_left:Nn \@BTnormal \@@_create_row_node: } \box_clear_new:N \l_@@_cell_box \normalbaselines % \end{macrocode} % If the option |small| is used, we have to do some tuning. In particular, we % change the value of |\arraystretch| (this parameter is used in the % construction of |\@arstrutbox| in the beginning of |{array}|). % \begin{macrocode} \bool_if:NT \l_@@_small_bool { % \end{macrocode} % \begin{macrocode} \cs_set_nopar:Npn \arraystretch { 0.47 } \dim_set:Nn \arraycolsep { 1.45 pt } } % \end{macrocode} % % \bigskip % \begin{macrocode} \bool_if:NT \g_@@_recreate_cell_nodes_bool { \tl_put_right:Nn \@@_begin_of_row: { \pgfsys@markposition { \@@_env: - row - \int_use:N \c@iRow - base } } } % \end{macrocode} % % \bigskip % The environment |{array}| uses internally the command |\ialign|. We change the % definition of |\ialign| for several reasons. In particular, |\ialign| sets % |\everycr| to |{ }| and we \emph{need} to have to change the value of % |\everycr|. % \begin{macrocode} \cs_set_nopar:Npn \ialign { \bool_if:NTF \c_@@_colortbl_loaded_bool { \CT@everycr { \noalign { \cs_gset_eq:NN \CT@row@color \prg_do_nothing: } \@@_everycr: } } { \everycr { \@@_everycr: } } \tabskip = \c_zero_skip % \end{macrocode} % % The box |\@arstrutbox| is a box constructed in the beginning of the % environment |{array}|. The construction of that box takes into account the % current value of |\arraystretch|\footnote{The option |small| of % \pkg{nicematrix} changes (among other) the value of |\arraystretch|. This is % done, of course, before the call of |{array}|.} and |\extrarowheight| (of % \pkg{array}). That box is inserted (via |\@arstrut|) in the beginning of each % row of the array. That's why we use the dimensions of that box to initialize % the variables which will be the dimensions of the potential first and last row % of the environment. This initialization must be done after the creation of % |\@arstrutbox| and that's why we do it in the |\ialign|. % \begin{macrocode} \dim_gzero_new:N \g_@@_dp_row_zero_dim \dim_gset:Nn \g_@@_dp_row_zero_dim { \box_dp:N \@arstrutbox } \dim_gzero_new:N \g_@@_ht_row_zero_dim \dim_gset:Nn \g_@@_ht_row_zero_dim { \box_ht:N \@arstrutbox } \dim_gzero_new:N \g_@@_ht_row_one_dim \dim_gset:Nn \g_@@_ht_row_one_dim { \box_ht:N \@arstrutbox } \dim_gzero_new:N \g_@@_dp_ante_last_row_dim \dim_gzero_new:N \g_@@_ht_last_row_dim \dim_gset:Nn \g_@@_ht_last_row_dim { \box_ht:N \@arstrutbox } \dim_gzero_new:N \g_@@_dp_last_row_dim \dim_gset:Nn \g_@@_dp_last_row_dim { \box_dp:N \@arstrutbox } % \end{macrocode} % After its first use, the definition of |\ialign| will revert % automatically to its default definition. With this programmation, we will % have, in the cells of the array, a clean version of |\ialign|. % \begin{macrocode} \cs_set_eq:NN \ialign \@@_old_ialign: \halign } % \end{macrocode} % % We keep in memory the old versions or |\ldots|, |\cdots|, etc. only because we % use them inside |\phantom| commands in order that the new commands |\Ldots|, % |\Cdots|, etc. give the same spacing (except when the option |nullify-dots| is % used). % \begin{macrocode} \cs_set_eq:NN \@@_old_ldots \ldots \cs_set_eq:NN \@@_old_cdots \cdots \cs_set_eq:NN \@@_old_vdots \vdots \cs_set_eq:NN \@@_old_ddots \ddots \cs_set_eq:NN \@@_old_iddots \iddots \bool_if:NTF \l_@@_standard_cline_bool { \cs_set_eq:NN \cline \@@_standard_cline } { \cs_set_eq:NN \cline \@@_cline } \cs_set_eq:NN \Ldots \@@_Ldots \cs_set_eq:NN \Cdots \@@_Cdots \cs_set_eq:NN \Vdots \@@_Vdots \cs_set_eq:NN \Ddots \@@_Ddots \cs_set_eq:NN \Iddots \@@_Iddots \cs_set_eq:NN \hdottedline \@@_hdottedline: \cs_set_eq:NN \Hline \@@_Hline: \cs_set_eq:NN \Hspace \@@_Hspace: \cs_set_eq:NN \Hdotsfor \@@_Hdotsfor: \cs_set_eq:NN \Vdotsfor \@@_Vdotsfor: \cs_set_eq:NN \Block \@@_Block: \cs_set_eq:NN \rotate \@@_rotate: \cs_set_eq:NN \OnlyMainNiceMatrix \@@_OnlyMainNiceMatrix:n \cs_set_eq:NN \dotfill \@@_old_dotfill: \cs_set_eq:NN \CodeAfter \@@_CodeAfter: \cs_set_eq:NN \diagbox \@@_diagbox:nn \cs_set_eq:NN \NotEmpty \@@_NotEmpty: \cs_set_eq:NN \RowStyle \@@_RowStyle:n \bool_if:NT \l_@@_colortbl_like_bool \@@_colortbl_like: \bool_if:NT \l_@@_renew_dots_bool \@@_renew_dots: % \end{macrocode} % We redefine |\multicolumn| and, since we want |\multicolumn| to be available % in the potential environments |{tabular}| nested in the environments of % \pkg{nicematrix}, we patch |{tabular}| to go back to the original definition. % The command |\AtBeginEnvironment| is the command of \pkg{l3hooks} and, if this % command is not available (versions of LaTeX prior to 2020-10-01), % \pkg{etoolbox} is loaded and the command |\AtBeginDocument| of \pkg{etoolbox} % is used. % \begin{macrocode} \cs_set_eq:NN \multicolumn \@@_multicolumn:nnn \AtBeginEnvironment { tabular } { \cs_set_eq:NN \multicolumn \@@_old_multicolumn } % \end{macrocode} % % % The sequence |\g_@@_multicolumn_cells_seq| will contain the list of the cells % of the array where a command |\multicolumn{|$n$|}{...}{...}| with $n>1$ is % issued. In |\g_@@_multicolumn_sizes_seq|, the ``sizes'' (that is to say the % values of $n$) correspondant will be stored. These lists will be used for the % creation of the ``medium nodes'' (if they are created). % \begin{macrocode} \seq_gclear:N \g_@@_multicolumn_cells_seq \seq_gclear:N \g_@@_multicolumn_sizes_seq % \end{macrocode} % % % The counter |\c@iRow| will be used to count the rows of the array (its % incrementation will be in the first cell of the row). % \begin{macrocode} \int_gset:Nn \c@iRow { \l_@@_first_row_int - 1 } % \end{macrocode} % % At the end of the environment |{array}|, |\c@iRow| will be the total % number de rows. % % |\g_@@_row_total_int| will be the number or rows excepted the last row (if % |\l_@@_last_row_bool| has been raised with the option |last-row|). % \begin{macrocode} \int_gzero_new:N \g_@@_row_total_int % \end{macrocode} % % The counter |\c@jCol| will be used to count the columns of the array. % Since we want to know the total number of columns of the matrix, we also % create a counter |\g_@@_col_total_int|. These counters are updated in the % command |\@@_cell_begin:w| executed at the beginning of each cell. % \begin{macrocode} \int_gzero_new:N \g_@@_col_total_int % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \@ifnextchar \new@ifnextchar % \end{macrocode} % % \begin{macrocode} \@@_renew_NC@rewrite@S: % \end{macrocode} % % \begin{macrocode} \bool_gset_false:N \g_@@_last_col_found_bool % \end{macrocode} % % \medskip % During the construction of the array, the instructions |\Cdots|, |\Ldots|, % etc. will be written in token lists |\g_@@_Cdots_lines_tl|, etc. which will be % executed after the construction of the array. % \begin{macrocode} \tl_gclear_new:N \g_@@_Cdots_lines_tl \tl_gclear_new:N \g_@@_Ldots_lines_tl \tl_gclear_new:N \g_@@_Vdots_lines_tl \tl_gclear_new:N \g_@@_Ddots_lines_tl \tl_gclear_new:N \g_@@_Iddots_lines_tl \tl_gclear_new:N \g_@@_HVdotsfor_lines_tl % \end{macrocode} % % \medskip % \begin{macrocode} \tl_gclear_new:N \g_nicematrix_code_before_tl } % \end{macrocode} % This is the end of |\@@_pre_array_ii:|. % % % \bigskip % The command |\@@_pre_array:| will be executed after analyse of the keys of the % environment. % \begin{macrocode} \cs_new_protected:Npn \@@_pre_array: { % \end{macrocode} % % \begin{macrocode} \cs_if_exist:NT \theiRow { \int_set_eq:NN \l_@@_old_iRow_int \c@iRow } \int_gzero_new:N \c@iRow \cs_if_exist:NT \thejCol { \int_set_eq:NN \l_@@_old_jCol_int \c@jCol } \int_gzero_new:N \c@jCol % \end{macrocode} % % \bigskip % We recall that |\l_@@_last_row_int| and |\l_@@_last_column_int| are \emph{not} % the numbers of the last row and last column of the array. There are only the % values of the keys |last-row| and |last-column| (maybe the user has provided % erroneous values). The meaning of that counters does not change during the % environment of \pkg{nicematrix}. There is only a slight adjustment: if the % user have used one of those keys without value, we provide now the right value % as read on the |aux| file (of course, it's possible only after the first compilation). % \begin{macrocode} \int_compare:nNnT \l_@@_last_row_int = { -1 } { \bool_set_true:N \l_@@_last_row_without_value_bool \bool_if:NT \g_@@_aux_found_bool { \int_set:Nn \l_@@_last_row_int { \seq_item:Nn \c_@@_size_seq 3 } } } \int_compare:nNnT \l_@@_last_col_int = { -1 } { \bool_if:NT \g_@@_aux_found_bool { \int_set:Nn \l_@@_last_col_int { \seq_item:Nn \c_@@_size_seq 6 } } } % \end{macrocode} % % \bigskip % If there is a exterior row, we patch a command used in |\@@_cell_begin:w| in order to % keep track of some dimensions needed to the construction of that ``last row''. % \begin{macrocode} \int_compare:nNnT \l_@@_last_row_int > { -2 } { \tl_put_right:Nn \@@_update_for_first_and_last_row: { \dim_gset:Nn \g_@@_ht_last_row_dim { \dim_max:nn \g_@@_ht_last_row_dim { \box_ht:N \l_@@_cell_box } } \dim_gset:Nn \g_@@_dp_last_row_dim { \dim_max:nn \g_@@_dp_last_row_dim { \box_dp:N \l_@@_cell_box } } } } % \end{macrocode} % % \bigskip % \begin{macrocode} \seq_gclear:N \g_@@_submatrix_seq % \end{macrocode} % % \bigskip % Now the |\CodeBefore|. % \begin{macrocode} \bool_if:NT \l_@@_code_before_bool \@@_exec_code_before: % \end{macrocode} % % \bigskip % The value of |\g_@@_pos_of_blocks_seq| has been written on the |aux| file and % loaded before the (potential) execution of the |\CodeBefore|. Now, we clear % that variable because it will be reconstructed during the creation of the % array. % \begin{macrocode} \seq_gclear:N \g_@@_pos_of_blocks_seq % \end{macrocode} % Idem for other sequences written on the |aux| file. % \begin{macrocode} \seq_gclear_new:N \g_@@_multicolumn_cells_seq \seq_gclear_new:N \g_@@_multicolumn_sizes_seq % \end{macrocode} % % % \interitem % The code in |\@@_pre_array_ii:| is used only here. % \begin{macrocode} \@@_pre_array_ii: % \end{macrocode} % % \medskip % The array will be composed in a box (named |\l_@@_the_array_box|) because we % have to do manipulations concerning the potential exterior rows. % \begin{macrocode} \box_clear_new:N \l_@@_the_array_box % \end{macrocode} % % % \bigskip % The preamble will be constructed in |\g_@@_preamble_tl|. % \begin{macrocode} \@@_construct_preamble: % \end{macrocode} % Now, the preamble is constructed in |\g_@@_preamble_tl| % % \medskip % We compute the width of both delimiters. We remember that, when the % environment |{NiceArray}| is used, it's possible to specify the delimiters in % the preamble (eg |[ccc]|). % \begin{macrocode} \dim_zero_new:N \l_@@_left_delim_dim \dim_zero_new:N \l_@@_right_delim_dim \bool_if:NTF \l_@@_NiceArray_bool { \dim_gset:Nn \l_@@_left_delim_dim { 2 \arraycolsep } \dim_gset:Nn \l_@@_right_delim_dim { 2 \arraycolsep } } { % \end{macrocode} % The command |\bBigg@| is a command of \pkg{amsmath}. % \begin{macrocode} \hbox_set:Nn \l_tmpa_box { $ \bBigg@ 5 \g_@@_left_delim_tl $ } \dim_set:Nn \l_@@_left_delim_dim { \box_wd:N \l_tmpa_box } \hbox_set:Nn \l_tmpa_box { $ \bBigg@ 5 \g_@@_right_delim_tl $ } \dim_set:Nn \l_@@_right_delim_dim { \box_wd:N \l_tmpa_box } } % \end{macrocode} % % \bigskip % Here is the beginning of the box which will contain the array. The % |\hbox_set_end:| corresponding to this |\hbox_set:Nw| will be in the second % part of the environment (and the closing |\c_math_toggle_token| also). % \begin{macrocode} \hbox_set:Nw \l_@@_the_array_box % \end{macrocode} % % \begin{macrocode} \skip_horizontal:N \l_@@_left_margin_dim \skip_horizontal:N \l_@@_extra_left_margin_dim \c_math_toggle_token \bool_if:NTF \l_@@_light_syntax_bool { \use:c { @@-light-syntax } } { \use:c { @@-normal-syntax } } } % \end{macrocode} % % \bigskip % The following command |\@@_pre_array_i:w| will be used when the keyword % |\CodeBefore| is present at the beginning of the environment. % \begin{macrocode} \cs_new_protected:Npn \@@_pre_array_i:w #1 \Body { \tl_put_right:Nn \l_@@_code_before_tl { #1 } \bool_set_true:N \l_@@_code_before_bool % \end{macrocode} % We go on with |\@@_pre_array:| which will (among other) execute the % |\CodeBefore| (specified in the key |code-before| or after the keyword % |\CodeBefore|). By definition, the |\CodeBefore| must be executed before the % body of the array... % \begin{macrocode} \@@_pre_array: } % \end{macrocode} % % \bigskip % \begin{macrocode} \keys_define:nn { NiceMatrix / RowStyle } { cell-space-top-limit .code:n = { \tl_gput_right:Nn \g_@@_row_style_tl { \tl_gput_right:Nn \g_@@_post_action_cell_tl { \dim_set:Nn \l_@@_cell_space_top_limit_dim { #1 } } } } , cell-space-top-limit .value_required:n = true , cell-space-bottom-limit .code:n = { \tl_gput_right:Nn \g_@@_row_style_tl { \tl_gput_right:Nn \g_@@_post_action_cell_tl { \dim_set:Nn \l_@@_cell_space_bottom_limit_dim { #1 } } } } , cell-space-bottom-limit .value_required:n = true , cell-space-limits .meta:n = { cell-space-top-limit = #1 , cell-space-bottom-limit = #1 , } , color .code:n = { \leavevmode \color { #1 } \tl_gput_right:Nn \g_@@_row_style_tl { \leavevmode \color { #1 } } } , color .value_required:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~RowStyle } } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_RowStyle:n { O { } m } { \tl_gset:Nn \g_@@_row_style_tl { #2 } \keys_set:nn { NiceMatrix / RowStyle } { #1 } #2 \ignorespaces } % \end{macrocode} % % \bigskip % \subsection*{The \textbackslash CodeBefore} % % The following command will be executed if the |\CodeBefore| has to be actually executed. % \begin{macrocode} \cs_new_protected:Npn \@@_pre_code_before: { % \end{macrocode} % First, we give values to the LaTeX counters |iRow| and |jCol|. We remind that, % in the |\CodeBefore| (and in the |\CodeAfter|) they represent the numbers of % rows and columns of the array (without the potential last row and last % column). The value of |\g_@@_row_total_int| is the number of the last row % (with potentially a last exterior row) and |\g_@@_col_total_int| is the number % of the last column (with potentially a last exterior column). % \begin{macrocode} \int_set:Nn \c@iRow { \seq_item:Nn \c_@@_size_seq 2 } \int_set:Nn \c@jCol { \seq_item:Nn \c_@@_size_seq 5 } \int_set_eq:NN \g_@@_row_total_int { \seq_item:Nn \c_@@_size_seq 3 } \int_set_eq:NN \g_@@_col_total_int { \seq_item:Nn \c_@@_size_seq 6 } % \end{macrocode} % % % Now, we will create all the |col| nodes and |row| nodes with the informations % written in the |aux| file. You use the technique described in the page~1229 of % |pgfmanual.pdf|, version~3.1.4b. % \begin{macrocode} \pgfsys@markposition { \@@_env: - position } \pgfsys@getposition { \@@_env: - position } \@@_picture_position: \pgfpicture \pgf@relevantforpicturesizefalse % \end{macrocode} % First, the recreation of the |row| nodes. % \begin{macrocode} \int_step_inline:nnn \l_@@_first_row_int { \g_@@_row_total_int + 1 } { \pgfsys@getposition { \@@_env: - row - ##1 } \@@_node_position: \pgfcoordinate { \@@_env: - row - ##1 } { \pgfpointdiff \@@_picture_position: \@@_node_position: } } % \end{macrocode} % Now, the recreation of the |col| nodes. % \begin{macrocode} \int_step_inline:nnn \l_@@_first_col_int { \g_@@_col_total_int + 1 } { \pgfsys@getposition { \@@_env: - col - ##1 } \@@_node_position: \pgfcoordinate { \@@_env: - col - ##1 } { \pgfpointdiff \@@_picture_position: \@@_node_position: } } % \end{macrocode} % Now, you recreate the diagonal nodes by using the |row| nodes and the |col| % nodes. % \begin{macrocode} \@@_create_diag_nodes: % \end{macrocode} % % \medskip % Now, the creation of the cell nodes |(i-j)|, and, maybe also the ``medium % nodes'' and the ``large nodes''. % \begin{macrocode} \bool_if:NT \g_@@_recreate_cell_nodes_bool \@@_recreate_cell_nodes: \endpgfpicture % \end{macrocode} % % \begin{macrocode} \bool_if:NT \c_@@_tikz_loaded_bool { \tikzset { every~picture / .style = { overlay , name~prefix = \@@_env: - } } } \cs_set_eq:NN \cellcolor \@@_cellcolor \cs_set_eq:NN \rectanglecolor \@@_rectanglecolor \cs_set_eq:NN \roundedrectanglecolor \@@_roundedrectanglecolor \cs_set_eq:NN \rowcolor \@@_rowcolor \cs_set_eq:NN \rowcolors \@@_rowcolors \cs_set_eq:NN \rowlistcolors \@@_rowlistcolors \cs_set_eq:NN \arraycolor \@@_arraycolor \cs_set_eq:NN \columncolor \@@_columncolor \cs_set_eq:NN \chessboardcolors \@@_chessboardcolors \cs_set_eq:NN \SubMatrix \@@_SubMatrix_in_code_before } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_exec_code_before: { \seq_gclear_new:N \g_@@_colors_seq \bool_gset_false:N \g_@@_recreate_cell_nodes_bool \group_begin: % \end{macrocode} % % We compose the |code-before| in math mode in order to nullify the spaces put % by the user between instructions in the |code-before|. % \begin{macrocode} \bool_if:NT \l_@@_NiceTabular_bool \c_math_toggle_token % \end{macrocode} % % Here is the |\CodeBefore|. The construction is a bit complicated because % |\l_@@_code_before_tl| may begin with keys between square brackets. Moreover, % after the analyze of those keys, we sometimes have to decide to do \emph{not} % execute the rest of |\l_@@_code_before_tl| (when it is asked for the creation % of cell nodes in the |\CodeBefore|). That's why we begin with a |\q_stop|: it % will be used to discard the rest of |\l_@@_code_before_tl|. % \begin{macrocode} \exp_last_unbraced:NV \@@_CodeBefore_keys: \l_@@_code_before_tl \q_stop % \end{macrocode} % Now, all the cells which are specified to be colored by instructions in the % |\CodeBefore| will actually be colored. It's a two-stages mechanism because we % want to draw all the cells with the same color at the same time to absolutely % avoid thin white lines in some \textsc{pdf} viewers. % \begin{macrocode} \@@_actually_color: \bool_if:NT \l_@@_NiceTabular_bool \c_math_toggle_token \group_end: \bool_if:NT \g_@@_recreate_cell_nodes_bool { \tl_put_left:Nn \@@_node_for_cell: \@@_patch_node_for_cell: } } % \end{macrocode} % % \bigskip % \begin{macrocode} \keys_define:nn { NiceMatrix / CodeBefore } { create-cell-nodes .bool_gset:N = \g_@@_recreate_cell_nodes_bool , create-cell-nodes .default:n = true , sub-matrix .code:n = \keys_set:nn { NiceMatrix / sub-matrix } { #1 } , sub-matrix .value_required:n = true , delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , delimiters / color .value_required:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~CodeAfter } } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \@@_CodeBefore_keys: { O { } } { \keys_set:nn { NiceMatrix / CodeBefore } { #1 } \@@_CodeBefore:w } % \end{macrocode} % % We have extracted the options of the keyword |\CodeBefore| in order to see % whether the key |create-cell-nodes| has been used. Now, you can execute the % rest of the |\CodeAfter|, excepted, of course, if we are in the first % compilation. % \begin{macrocode} \cs_new_protected:Npn \@@_CodeBefore:w #1 \q_stop { \bool_if:NT \g_@@_aux_found_bool { \@@_pre_code_before: #1 } } % \end{macrocode} % % \bigskip % % % \bigskip % By default, if the user uses the |\CodeBefore|, only the |col| nodes, |row| % nodes and |diag| nodes are available in that |\CodeBefore|. With the key % |create-cell-nodes|, the cell nodes, that is to say the nodes of the form % |(i-j)| (but not the extra nodes) are also available because those nodes also % are recreated and that recreation is done by the following command. % \begin{macrocode} \cs_new_protected:Npn \@@_recreate_cell_nodes: { \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { \pgfsys@getposition { \@@_env: - ##1 - base } \@@_node_position: \pgfcoordinate { \@@_env: - row - ##1 - base } { \pgfpointdiff \@@_picture_position: \@@_node_position: } \int_step_inline:nnn \l_@@_first_col_int \g_@@_col_total_int { \cs_if_exist:cT { pgf @ sys @ pdf @ mark @ pos @ \@@_env: - ##1 - ####1 - NW } { \pgfsys@getposition { \@@_env: - ##1 - ####1 - NW } \@@_node_position: \pgfsys@getposition { \@@_env: - ##1 - ####1 - SE } \@@_node_position_i: \@@_pgf_rect_node:nnn { \@@_env: - ##1 - ####1 } { \pgfpointdiff \@@_picture_position: \@@_node_position: } { \pgfpointdiff \@@_picture_position: \@@_node_position_i: } } } } \@@_create_extra_nodes: } % \end{macrocode} % % % \bigskip % \subsection*{The environment \{NiceArrayWithDelims\}} % % \begin{macrocode} \NewDocumentEnvironment { NiceArrayWithDelims } { m m O { } m ! O { } t \CodeBefore } { % \end{macrocode} % % \begin{macrocode} \@@_provide_pgfsyspdfmark: \bool_if:NT \c_@@_footnote_bool \savenotes % \end{macrocode} % % The aim of the following |\bgroup| (the corresponding |\egroup| is, of course, % at the end of the environment) is to be able to put an exposant to a matrix in % a mathematical formula. % \begin{macrocode} \bgroup % \end{macrocode} % % \bigskip % \begin{macrocode} \tl_gset:Nn \g_@@_left_delim_tl { #1 } \tl_gset:Nn \g_@@_right_delim_tl { #2 } \tl_gset:Nn \g_@@_preamble_tl { #4 } % \end{macrocode} % % % \bigskip % % \begin{macrocode} \int_gzero:N \g_@@_block_box_int \dim_zero:N \g_@@_width_last_col_dim \dim_zero:N \g_@@_width_first_col_dim \bool_gset_false:N \g_@@_row_of_col_done_bool \str_if_empty:NT \g_@@_name_env_str { \str_gset:Nn \g_@@_name_env_str { NiceArrayWithDelims } } % \end{macrocode} % The following line will be deleted when we will consider that only versions of % \pkg{siunitx} after v3.0 are compatible with \pkg{nicematrix}. % \begin{macrocode} \@@_adapt_S_column: \bool_if:NTF \l_@@_NiceTabular_bool \mode_leave_vertical: \@@_test_if_math_mode: \bool_if:NT \l_@@_in_env_bool { \@@_fatal:n { Yet~in~env } } \bool_set_true:N \l_@@_in_env_bool % \end{macrocode} % The command |\CT@arc@| contains the instruction of color for the rules of the % array\footnote{e.g. |\color[rgb]{0.5,0.5,0}|}. This command is used by |\CT@arc@| but % we use it also for compatibility with \pkg{colortbl}. But we want also to be % able to use color for the rules of the array when \pkg{colortbl} is \emph{not} % loaded. That's why we do the following instruction which is in the patch of % the beginning of arrays done by \pkg{colortbl}. Of course, we restore the % value of |\CT@arc@| at the end of our environment. % \begin{macrocode} \cs_gset_eq:NN \@@_old_CT@arc@ \CT@arc@ % \end{macrocode} % % We deactivate Tikz externalization because we will use \textsc{pgf} pictures % with the options |overlay| and |remember picture| (or equivalent forms). We % deactivate with |\tikzexternaldisable| and not with % |\tikzset{external/export=false}| which is \emph{not} equivalent. % \begin{macrocode} \cs_if_exist:NT \tikz@library@external@loaded { \tikzexternaldisable \cs_if_exist:NT \ifstandalone { \tikzset { external / optimize = false } } } % \end{macrocode} % % We increment the counter |\g_@@_env_int| which counts the environments % of the package. % \begin{macrocode} \int_gincr:N \g_@@_env_int \bool_if:NF \l_@@_block_auto_columns_width_bool { \dim_gzero_new:N \g_@@_max_cell_width_dim } % \end{macrocode} % % % The sequence |\g_@@_blocks_seq| will contain the carateristics of the blocks % (specified by |\Block|) of the array. The sequence |\g_@@_pos_of_blocks_seq| % will contain only the position of the blocks (except the blocks with the key % |hvlines|). % \begin{macrocode} \seq_gclear:N \g_@@_blocks_seq \seq_gclear:N \g_@@_pos_of_blocks_seq % \end{macrocode} % In fact, the sequence |\g_@@_pos_of_blocks_seq| will also contain the % positions of the cells with a |\diagbox|. % % \begin{macrocode} \seq_gclear:N \g_@@_pos_of_stroken_blocks_seq \seq_gclear:N \g_@@_pos_of_xdots_seq \tl_gclear_new:N \g_@@_code_before_tl \tl_gclear:N \g_@@_row_style_tl % \end{macrocode} % % \bigskip % We load all the informations written in the |aux| file during previous % compilations corresponding to the current environment. % \begin{macrocode} \bool_gset_false:N \g_@@_aux_found_bool \tl_if_exist:cT { c_@@ _ \int_use:N \g_@@_env_int _ tl } { \bool_gset_true:N \g_@@_aux_found_bool \use:c { c_@@ _ \int_use:N \g_@@_env_int _ tl } } % \end{macrocode} % Now, we prepare the token list for the instructions that we will have to write % on the |aux| file at the end of the environment. % \begin{macrocode} \tl_gclear:N \g_@@_aux_tl % \end{macrocode} % % \begin{macrocode} \tl_if_empty:NF \g_@@_code_before_tl { \bool_set_true:N \l_@@_code_before_bool \tl_put_right:NV \l_@@_code_before_tl \g_@@_code_before_tl } % \end{macrocode} % % The set of keys is not exactly the same for |{NiceArray}| and for the variants % of |{NiceArray}| (|{pNiceArray}|, |{bNiceArray}|, etc.) because, for % |{NiceArray}|, we have the options |t|, |c|, |b| and |baseline|. % \begin{macrocode} \bool_if:NTF \l_@@_NiceArray_bool { \keys_set:nn { NiceMatrix / NiceArray } } { \keys_set:nn { NiceMatrix / pNiceArray } } { #3 , #5 } % \end{macrocode} % % \bigskip % \begin{macrocode} \tl_if_empty:NF \l_@@_rules_color_tl { \exp_after:wN \@@_set_CT@arc@: \l_@@_rules_color_tl \q_stop } % \end{macrocode} % % \bigskip % The argument |#6| is the last argument of |{NiceArrayWithDelims}|. With that % argument of type ``|t \CodeBefore|'', we test whether there is the keyword % |\CodeBefore| at the beginning of the body of the environment. If that keyword % is present, we have now to extract all the content between that keyword % |\CodeBefore| and the (other) keyword |\Body|. It's the job that will do the % command |\@@_pre_array_i:w|. After that job, the command |\@@_pre_array_i:w| % will go on with |\@@_pre_array:|. % \begin{macrocode} \IfBooleanTF { #6 } \@@_pre_array_i:w \@@_pre_array: } % \end{macrocode} % % \begin{macrocode} { \bool_if:NTF \l_@@_light_syntax_bool { \use:c { end @@-light-syntax } } { \use:c { end @@-normal-syntax } } \c_math_toggle_token \skip_horizontal:N \l_@@_right_margin_dim \skip_horizontal:N \l_@@_extra_right_margin_dim \hbox_set_end: % \end{macrocode} % End of the construction of the array (in the box |\l_@@_the_array_box|). % % \bigskip % If the user has used the key |width| without any column |X|, we raise an error. % \begin{macrocode} \bool_if:NT \l_@@_width_used_bool { \int_compare:nNnT \g_@@_total_X_weight_int = 0 { \@@_error:n { width~without~X~columns } } } % \end{macrocode} % % \bigskip % Now, if there is at least one |X|-column in the environment, we compute the % width that those columns will have (in the next compilation). In fact, % |l_@@_X_columns_dim| will be the width of a column of weight $1$. For a % |X|-column of weight~$n$, the width will be |l_@@_X_columns_dim| multiplied % by~$n$. % \begin{macrocode} \int_compare:nNnT \g_@@_total_X_weight_int > 0 { \tl_gput_right:Nx \g_@@_aux_tl { \bool_set_true:N \l_@@_X_columns_aux_bool \dim_set:Nn \l_@@_X_columns_dim { \dim_compare:nNnTF { \dim_abs:n { \l_@@_width_dim - \box_wd:N \l_@@_the_array_box } } < { 0.001 pt } { \dim_use:N \l_@@_X_columns_dim } { \dim_eval:n { ( \l_@@_width_dim - \box_wd:N \l_@@_the_array_box ) / \int_use:N \g_@@_total_X_weight_int + \l_@@_X_columns_dim } } } } } % \end{macrocode} % % \bigskip % It the user has used the key |last-row| with a value, we control that the % given value is correct (since we have just constructed the array, we know the % real number of rows of the array). % \begin{macrocode} \int_compare:nNnT \l_@@_last_row_int > { -2 } { \bool_if:NF \l_@@_last_row_without_value_bool { \int_compare:nNnF \l_@@_last_row_int = \c@iRow { \@@_error:n { Wrong~last~row } \int_gset_eq:NN \l_@@_last_row_int \c@iRow } } } % \end{macrocode} % % Now, the definition of |\c@jCol| and |\g_@@_col_total_int| change: |\c@jCol| % will be the number of columns without the ``last column''; % |\g_@@_col_total_int| will be the number of columns with this ``last % column''.\footnote{We remind that the potential ``first column'' (exterior) % has the number~$0$.} % \begin{macrocode} \int_gset_eq:NN \c@jCol \g_@@_col_total_int \bool_if:nTF \g_@@_last_col_found_bool { \int_gdecr:N \c@jCol } { \int_compare:nNnT \l_@@_last_col_int > { -1 } { \@@_error:n { last~col~not~used } } } % \end{macrocode} % % We fix also the value of |\c@iRow| and |\g_@@_row_total_int| with the % same principle. % \begin{macrocode} \int_gset_eq:NN \g_@@_row_total_int \c@iRow \int_compare:nNnT \l_@@_last_row_int > { -1 } { \int_gdecr:N \c@iRow } % \end{macrocode} % % % \bigskip % \textbf{Now, we begin the real construction in the output flow of TeX}. First, we take % into account a potential ``first column'' (we remind that this ``first % column'' has been constructed in an overlapping position and that we have % computed its width in |\g_@@_width_first_col_dim|: see % p.~\pageref{overlap-left}). % \begin{macrocode} \int_compare:nNnT \l_@@_first_col_int = 0 { \skip_horizontal:N \col@sep \skip_horizontal:N \g_@@_width_first_col_dim } % \end{macrocode} % % The construction of the real box is different when |\l_@@_NiceArray_bool| is % true (|{NiceArray}| or |{NiceTabular}|) and in the other environments because, % in |{NiceArray}| or |{NiceTabular}|, we have no delimiter to put (but we have % tabular notes to put). We begin with this case. % % \begin{macrocode} \bool_if:NTF \l_@@_NiceArray_bool { \str_case:VnF \l_@@_baseline_tl { b \@@_use_arraybox_with_notes_b: c \@@_use_arraybox_with_notes_c: } \@@_use_arraybox_with_notes: } % \end{macrocode} % % Now, in the case of an environment |{pNiceArray}|, |{bNiceArray}|, etc. We % compute |\l_tmpa_dim| which is the total height of the ``first row'' above the % array (when the key |first-row| is used). % \begin{macrocode} { \int_compare:nNnTF \l_@@_first_row_int = 0 { \dim_set_eq:NN \l_tmpa_dim \g_@@_dp_row_zero_dim \dim_add:Nn \l_tmpa_dim \g_@@_ht_row_zero_dim } { \dim_zero:N \l_tmpa_dim } % \end{macrocode} % % We compute |\l_tmpb_dim| which is the total height of the ``last row'' % below the array (when the key |last-row| is used). A value of $-2$ for % |\l_@@_last_row_int| means that there is no ``last row''.\footnote{A value of % $-1$ for |\l_@@_last_row_int| means that there is a ``last row'' but the % the user have not set the value with the option |last row| (and we are in the % first compilation).} % \begin{macrocode} \int_compare:nNnTF \l_@@_last_row_int > { -2 } { \dim_set_eq:NN \l_tmpb_dim \g_@@_ht_last_row_dim \dim_add:Nn \l_tmpb_dim \g_@@_dp_last_row_dim } { \dim_zero:N \l_tmpb_dim } % \end{macrocode} % % \begin{macrocode} \hbox_set:Nn \l_tmpa_box { \c_math_toggle_token \tl_if_empty:NF \l_@@_delimiters_color_tl { \color { \l_@@_delimiters_color_tl } } \exp_after:wN \left \g_@@_left_delim_tl \vcenter { % \end{macrocode} % We take into account the ``first row'' (we have previously computed its total % height in |\l_tmpa_dim|). The |\hbox:n| (or |\hbox|) is necessary here. % \begin{macrocode} \skip_vertical:N -\l_tmpa_dim \hbox { \bool_if:NTF \l_@@_NiceTabular_bool { \skip_horizontal:N -\tabcolsep } { \skip_horizontal:N -\arraycolsep } \@@_use_arraybox_with_notes_c: \bool_if:NTF \l_@@_NiceTabular_bool { \skip_horizontal:N -\tabcolsep } { \skip_horizontal:N -\arraycolsep } } % \end{macrocode} % We take into account the ``last row'' (we have previously computed its total % height in |\l_tmpb_dim|). % \begin{macrocode} \skip_vertical:N -\l_tmpb_dim } % \end{macrocode} % Curiously, we have to put again the following specification of color. % Otherwise, with XeLaTeX (and not with the other engines), the closing % delimiter is not colored. % \begin{macrocode} \tl_if_empty:NF \l_@@_delimiters_color_tl { \color { \l_@@_delimiters_color_tl } } \exp_after:wN \right \g_@@_right_delim_tl \c_math_toggle_token } % \end{macrocode} % Now, the box |\l_tmpa_box| is created with the correct delimiters. % % \smallskip % We will put the box in the TeX flow. However, we have a small work to do % when the option |delimiters/max-width| is used. % \begin{macrocode} \bool_if:NTF \l_@@_delimiters_max_width_bool { \@@_put_box_in_flow_bis:nn \g_@@_left_delim_tl \g_@@_right_delim_tl } \@@_put_box_in_flow: } % \end{macrocode} % % We take into account a potential ``last column'' (this ``last column'' has % been constructed in an overlapping position and we have computed its width in % |\g_@@_width_last_col_dim|: see p.~\pageref{overlap-right}). % \begin{macrocode} \bool_if:NT \g_@@_last_col_found_bool { \skip_horizontal:N \g_@@_width_last_col_dim \skip_horizontal:N \col@sep } \bool_if:NF \l_@@_Matrix_bool { \int_compare:nNnT \c@jCol < \g_@@_static_num_of_col_int { \@@_error:n { columns~not~used } } } \group_begin: \globaldefs = 1 \@@_msg_redirect_name:nn { columns~not~used } { error } \group_end: \@@_after_array: % \end{macrocode} % The aim of the following |\egroup| (the corresponding |\bgroup| is, of course, % at the beginning of the environment) is to be able to put an exposant to a matrix in % a mathematical formula. % \begin{macrocode} \egroup % \end{macrocode} % % \bigskip % We want to write on the |aux| file all the informations corresponding to the % current environment. % \begin{macrocode} \iow_now:Nn \@mainaux { \ExplSyntaxOn } \iow_now:Nn \@mainaux { \char_set_catcode_space:n { 32 } } \iow_now:Nx \@mainaux { \tl_gset:cn { c_@@_ \int_use:N \g_@@_env_int _ tl } { \exp_not:V \g_@@_aux_tl } } \iow_now:Nn \@mainaux { \ExplSyntaxOff } % \end{macrocode} % % \bigskip % \begin{macrocode} \bool_if:NT \c_@@_footnote_bool \endsavenotes } % \end{macrocode} % This is the end of the environment |{NiceArrayWithDelims}|. % % \vspace{1cm} % \subsection*{We construct the preamble of the array} % % The transformation of the preamble is an operation in several steps. % % \bigskip % The preamble given by the final user is in |\g_@@_preamble_tl| and the modified % version will be stored in |\g_@@_preamble_tl| also. % % \begin{macrocode} \cs_new_protected:Npn \@@_construct_preamble: { % \end{macrocode} % First, we will do an ``expansion'' of the preamble with the tools of the % package \pkg{array} itself. This ``expansion'' will expand all the constructions % with |*| and with all column types (defined by the user or by various packages % using |\newcolumntype|). % % Since we use the tools of \pkg{array} to do this expansion, we will have a % programmation which is not in the style of the L3 programming layer. % % % \bigskip % We redefine the column types |w| and |W|. We use |\@@_newcolumntype| instead % of |\newcolumtype| because we don't want warnings for column types already % defined. These redefinitions are in fact \emph{protections} of the letters |w| % and |W|. We don't want these columns type expanded because we will do the % patch ourselves after. We want to be able the standard column types |w| and % |W| in potential |{tabular}| of \pkg{array} in some cells of our array. That's % why we do those redefinitions in a TeX group. % \begin{macrocode} \group_begin: % \end{macrocode} % % If we are in an environment without explicit preamble, we have nothing to do % (excepted the treatment on both sides of the preamble which will be done at % the end). % \begin{macrocode} \bool_if:NF \l_@@_Matrix_bool { \@@_newcolumntype w [ 2 ] { \@@_w: { ##1 } { ##2 } } \@@_newcolumntype W [ 2 ] { \@@_W: { ##1 } { ##2 } } % \end{macrocode} % % First, we have to store our preamble in the token register |\@temptokena| % (those ``token registers'' are \emph{not} supported by the L3 programming layer). % \begin{macrocode} \exp_args:NV \@temptokena \g_@@_preamble_tl % \end{macrocode} % Initialisation of a flag used by \pkg{array} to detect the end of the expansion. % \begin{macrocode} \@tempswatrue % \end{macrocode} % The following line actually does the expansion (it's has been copied from % |array.sty|). The expanded version is still in |\@temptokena|. % \begin{macrocode} \@whilesw \if@tempswa \fi { \@tempswafalse \the \NC@list } % \end{macrocode} % % % \bigskip % Now, we have to ``patch'' that preamble by transforming some columns. % We will insert in the TeX flow the preamble in its actual form (that is to say % after the ``expansion'') following by a marker |\q_stop| and we will consume % these tokens constructing the (new form of the) preamble in % |\g_@@_preamble_tl|. This is done recursively with the command % |\@@_patch_preamble:n|. In the same time, we will count the columns with the % counter |\c@jCol|. % \begin{macrocode} \int_gzero:N \c@jCol \tl_gclear:N \g_@@_preamble_tl % \end{macrocode} % |\g_tmpb_bool| will be raised if you have a \verb+|+ at the end of the preamble. % \begin{macrocode} \bool_gset_false:N \g_tmpb_bool \tl_if_eq:NnTF \l_@@_vlines_clist { all } { \tl_gset:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N \arrayrulewidth } } } { \clist_if_in:NnT \l_@@_vlines_clist 1 { \tl_gset:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N \arrayrulewidth } } } } % \end{macrocode} % The sequence |\g_@@_cols_vlsim_seq| will contain the numbers of the columns % where you will to have to draw vertical lines in the potential sub-matrices % (hence the name |vlism|). % \begin{macrocode} \seq_clear:N \g_@@_cols_vlism_seq % \end{macrocode} % The counter |\l_tmpa_int| will count the number of consecutive occurrences % of the symbol \verb+|+. % \begin{macrocode} \int_zero:N \l_tmpa_int % \end{macrocode} % Now, we actually patch the preamble (and it is constructed in % |\g_@@_preamble_tl|). % \begin{macrocode} \exp_after:wN \@@_patch_preamble:n \the \@temptokena \q_stop \int_gset_eq:NN \g_@@_static_num_of_col_int \c@jCol } % \end{macrocode} % % \medskip % Now, we replace |\columncolor| by |\@@_columncolor_preamble|. % \begin{macrocode} \bool_if:NT \l_@@_colortbl_like_bool { \regex_replace_all:NnN \c_@@_columncolor_regex { \c { @@_columncolor_preamble } } \g_@@_preamble_tl } % \end{macrocode} % % \medskip % Now, we can close the TeX group which was opened for the redefinition of % the columns of type |w| and |W|. % \begin{macrocode} \group_end: % \end{macrocode} % % \medskip % If there was delimiters at the beginning or at the end of the preamble, the % environment |{NiceArray}| is transformed into an environment |{xNiceMatrix}|. % \begin{macrocode} \bool_lazy_or:nnT { ! \str_if_eq_p:Vn \g_@@_left_delim_tl { . } } { ! \str_if_eq_p:Vn \g_@@_right_delim_tl { . } } { \bool_set_false:N \l_@@_NiceArray_bool } % \end{macrocode} % % \medskip % We want to remind whether there is a specifier \verb+|+ at the end of the preamble. % \begin{macrocode} \bool_if:NT \g_tmpb_bool { \bool_set_true:N \l_@@_bar_at_end_of_pream_bool } % \end{macrocode} % % \bigskip % We complete the preamble with the potential ``exterior columns'' (on both sides). % \begin{macrocode} \int_compare:nNnTF \l_@@_first_col_int = 0 { \tl_gput_left:NV \g_@@_preamble_tl \c_@@_preamble_first_col_tl } { \bool_lazy_all:nT { \l_@@_NiceArray_bool { \bool_not_p:n \l_@@_NiceTabular_bool } { \tl_if_empty_p:N \l_@@_vlines_clist } { \bool_not_p:n \l_@@_exterior_arraycolsep_bool } } { \tl_gput_left:Nn \g_@@_preamble_tl { @ { } } } } \int_compare:nNnTF \l_@@_last_col_int > { -1 } { \tl_gput_right:NV \g_@@_preamble_tl \c_@@_preamble_last_col_tl } { \bool_lazy_all:nT { \l_@@_NiceArray_bool { \bool_not_p:n \l_@@_NiceTabular_bool } { \tl_if_empty_p:N \l_@@_vlines_clist } { \bool_not_p:n \l_@@_exterior_arraycolsep_bool } } { \tl_gput_right:Nn \g_@@_preamble_tl { @ { } } } } % \end{macrocode} % We add a last column to raise a good error message when the user puts more % columns than allowed by its preamble. However, for technical reasons, it's not % possible to do that in |{NiceTabular*}| (|\l_@@_tabular_width_dim|=0pt). % \begin{macrocode} \dim_compare:nNnT \l_@@_tabular_width_dim = \c_zero_dim { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_error_too_much_cols: } l } } } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble:n #1 { \str_case:nnF { #1 } { c { \@@_patch_preamble_i:n #1 } l { \@@_patch_preamble_i:n #1 } r { \@@_patch_preamble_i:n #1 } > { \@@_patch_preamble_ii:nn #1 } ! { \@@_patch_preamble_ii:nn #1 } @ { \@@_patch_preamble_ii:nn #1 } | { \@@_patch_preamble_iii:n #1 } p { \@@_patch_preamble_iv:n #1 } b { \@@_patch_preamble_iv:n #1 } m { \@@_patch_preamble_iv:n #1 } \@@_w: { \@@_patch_preamble_v:nnnn { } #1 } \@@_W: { \@@_patch_preamble_v:nnnn { \cs_set_eq:NN \hss \hfil } #1 } \@@_S: { \@@_patch_preamble_vi:n } ( { \@@_patch_preamble_vii:nn #1 } [ { \@@_patch_preamble_vii:nn #1 } \{ { \@@_patch_preamble_vii:nn #1 } ) { \@@_patch_preamble_viii:nn #1 } ] { \@@_patch_preamble_viii:nn #1 } \} { \@@_patch_preamble_viii:nn #1 } X { \@@_patch_preamble_ix:n } \q_stop { } } { \str_if_eq:VnTF \l_@@_letter_for_dotted_lines_str { #1 } { \@@_patch_preamble_xi:n #1 } { \str_if_eq:VnTF \l_@@_letter_vlism_tl { #1 } { \seq_gput_right:Nx \g_@@_cols_vlism_seq { \int_eval:n { \c@jCol + 1 } } \tl_gput_right:Nx \g_@@_preamble_tl { \exp_not:N ! { \skip_horizontal:N \arrayrulewidth } } \@@_patch_preamble:n } { \bool_lazy_and:nnTF { \str_if_eq_p:nn { : } { #1 } } \c_@@_arydshln_loaded_bool { \tl_gput_right:Nn \g_@@_preamble_tl { : } \@@_patch_preamble:n } { \@@_fatal:nn { unknown~column~type } { #1 } } } } } } % \end{macrocode} % % \medskip % For |c|, |l| and |r| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_i:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_cell_begin:w \str_set:Nn \l_@@_hpos_cell_str { #1 } } #1 < \@@_cell_end: } % \end{macrocode} % % We increment the counter of columns and then we test for the presence of a |<|. % \begin{macrocode} \int_gincr:N \c@jCol \@@_patch_preamble_x:n } % \end{macrocode} % % \medskip % For |>|, |!| and |@| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_ii:nn #1 #2 { \tl_gput_right:Nn \g_@@_preamble_tl { #1 { #2 } } \@@_patch_preamble:n } % \end{macrocode} % % % \medskip % For \verb+|+ % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iii:n #1 { % \end{macrocode} % |\l_tmpa_int| is the number of successive occurrences of \verb+|+ % \begin{macrocode} \int_incr:N \l_tmpa_int \@@_patch_preamble_iii_i:n } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iii_i:n #1 { \str_if_eq:nnTF { #1 } | { \@@_patch_preamble_iii:n | } { \tl_gput_right:Nx \g_@@_preamble_tl { \exp_not:N ! { \skip_horizontal:n { \dim_eval:n { \arrayrulewidth * \l_tmpa_int + \doublerulesep * ( \l_tmpa_int - 1) } } } } \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_vline:nnnn { \@@_succ:n \c@jCol } { \int_use:N \l_tmpa_int } { 1 } { } } \int_zero:N \l_tmpa_int \str_if_eq:nnT { #1 } { \q_stop } { \bool_gset_true:N \g_tmpb_bool } \@@_patch_preamble:n #1 } } % \end{macrocode} % % \begin{macrocode} \bool_new:N \l_@@_bar_at_end_of_pream_bool % \end{macrocode} % % \bigskip % The specifier |p| (and also the specifiers |m| and |b|) have an optional % argument between square brackets for a list of \emph{key}-\emph{value} pairs. % Here are the corresponding keys. This set of keys will also be used by the |X| % columns. % \begin{macrocode} \keys_define:nn { WithArrows / p-column } { r .code:n = \str_set:Nn \l_@@_hpos_col_str { r } , r .value_forbidden:n = true , c .code:n = \str_set:Nn \l_@@_hpos_col_str { c } , c .value_forbidden:n = true , l .code:n = \str_set:Nn \l_@@_hpos_col_str { l } , l .value_forbidden:n = true , si .code:n = \str_set:Nn \l_@@_hpos_col_str { si } , si .value_forbidden:n = true , p .code:n = \str_set:Nn \l_@@_vpos_col_str { p } , p .value_forbidden:n = true , t .meta:n = p , m .code:n = \str_set:Nn \l_@@_vpos_col_str { m } , m .value_forbidden:n = true , b .code:n = \str_set:Nn \l_@@_vpos_col_str { b } , b .value_forbidden:n = true , } % \end{macrocode} % % % \medskip % For |p|, |b| and |m|. The argument |#1| is that value : |p|, |b| or |m|. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iv:n #1 { \str_set:Nn \l_@@_vpos_col_str { #1 } % \end{macrocode} % Now, you look for a potential character |[| after the letter of the specifier % (for the options). % \begin{macrocode} \@@_patch_preamble_iv_i:n } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iv_i:n #1 { \str_if_eq:nnTF { #1 } { [ } { \@@_patch_preamble_iv_ii:w [ } { \@@_patch_preamble_iv_ii:w [ ] { #1 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iv_ii:w [ #1 ] { \@@_patch_preamble_iv_iii:nn { #1 } } % \end{macrocode} % % \medskip % |#1| is the optional argument of the specifier (a list of % \emph{key}-\emph{value} pairs). % % |#2| is the mandatory argument of the specifier: the width of the column. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iv_iii:nn #1 #2 { % \end{macrocode} % The possible values of |\l_@@_hpos_col_str| are |j| (for \emph{justified} which is % the initial value), |l|, |c| and |r| (when the user has used the corresponding % key in the optional argument of the specifier). % \begin{macrocode} \str_set:Nn \l_@@_hpos_col_str { j } \keys_set:nn { WithArrows / p-column } { #1 } \@@_patch_preamble_iv_iv:n { #2 } } % \end{macrocode} % % \medskip % The argument is the width of the column. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iv_iv:n #1 { \use:x { \@@_patch_preamble_iv_v:nnnnnn { \str_if_eq:VnTF \l_@@_vpos_col_str { p } { t } { b } } { \dim_eval:n { #1 } } { % \end{macrocode} % The parameter |\l_@@_hpos_col_str| (as |\l_@@_vpos_col_str|) exists only % during the construction of the preamble. During the composition of the array % itself, you will have, in each cell, the parameter |\l_@@_hpos_cell_str| which % will provide the horizontal alignment of the column to which belongs the cell. % \begin{macrocode} \str_if_eq:VnTF \l_@@_hpos_col_str j { \str_set:Nn \exp_not:N \l_@@_hpos_cell_str { c } } { \str_set:Nn \exp_not:N \l_@@_hpos_cell_str { \l_@@_hpos_col_str } } \str_case:Vn \l_@@_hpos_col_str { c { \exp_not:N \centering } l { \exp_not:N \raggedright } r { \exp_not:N \raggedleft } } } { \str_if_eq:VnT \l_@@_vpos_col_str { m } \@@_center_cell_box: } { \str_if_eq:VnT \l_@@_hpos_col_str { si } \siunitx_cell_begin:w } { \str_if_eq:VnT \l_@@_hpos_col_str { si } \siunitx_cell_end: } } % \end{macrocode} % % We increment the counter of columns, and then we test for the presence of a |<|. % \begin{macrocode} \int_gincr:N \c@jCol \@@_patch_preamble_x:n } % \end{macrocode} % % \medskip % |#1| is the optional argument of |{minipage}|: |t| of |b|. Indeed, for the % columns of type |m|, we use the value |b| here because there is a special % post-action in order to center vertically the box (see |#4|). % % |#2| is the width of the |{minipage}|, that is to say also the width of the % column. % % |#3| is the coding for the horizontal position of the content of the cell % (|\centering|, |\raggedright|, |\raggedleft| or nothing). % % |#4| is an extra-code which contains |\l_@@_center_cell_box| (when the column % is a |m| column) or nothing (in the other cases). % % |#5| is a code put just before the |c|. % % |#6| is a code put just after the |c|. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_iv_v:nnnnnn #1 #2 #3 #4 #5 #6 { \tl_gput_right:Nn \g_@@_preamble_tl { > { % \end{macrocode} % The parameter |\l_@@_col_width_dim|, which is the width of the current column, % will be available in each cell of the column. It will be used by the % mono-column blocks. % \begin{macrocode} \dim_set:Nn \l_@@_col_width_dim { #2 } \@@_cell_begin:w \begin { minipage } [ #1 ] { #2 } % \end{macrocode} % The following lines have been taken from |array.sty|. % \begin{macrocode} \everypar { \vrule height \box_ht:N \@arstrutbox width \c_zero_dim \everypar { } } % \end{macrocode} % Now, the potential code for the horizontal position of the content of the cell % (|\centering|, |\raggedright|, |\raggedleft| or nothing). % \begin{macrocode} #3 % \end{macrocode} % The following code is to allow something like |\centering| in |\RowStyle|. % \begin{macrocode} \g_@@_row_style_tl \arraybackslash #5 } c < { #6 % \end{macrocode} % The following line has been taken from |array.sty|. % \begin{macrocode} \@finalstrut \@arstrutbox \end { minipage } % \end{macrocode} % If the letter in the preamble is |m|, |#3| will be equal to % |\@@_center_cell_box:| (see just below). % \begin{macrocode} #4 \@@_cell_end: } } } % \end{macrocode} % % \bigskip % The following command will be used in |m|-columns in order to center % vertically the box. In fact, despite its name, the command does not always % center the cell. Indeed, if there is only one row in the cell, it should not % be centered vertically. It's not possible to know the number of rows of the % cell. However, we consider (as in \pkg{array}) that if the height of the cell % is no more that the height of |\@arstrutbox|, there is only one row. % \begin{macrocode} \cs_new_protected:Npn \@@_center_cell_box: { % \end{macrocode} % By putting instructions in |\g_@@_post_action_cell_tl|, we require a % post-action of the box |\l_@@_cell_box|. % \begin{macrocode} \tl_gput_right:Nn \g_@@_post_action_cell_tl { \int_compare:nNnT { \box_ht:N \l_@@_cell_box } > { \box_ht:N \@arstrutbox } { \hbox_set:Nn \l_@@_cell_box { \box_move_down:nn { ( \box_ht:N \l_@@_cell_box - \box_ht:N \@arstrutbox + \baselineskip ) / 2 } { \box_use:N \l_@@_cell_box } } } } } % \end{macrocode} % % % \medskip % For |w| and |W| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_v:nnnn #1 #2 #3 #4 { \tl_gput_right:Nn \g_@@_preamble_tl { > { % \end{macrocode} % The parameter |\l_@@_col_width_dim|, which is the width of the current column, % will be available in each cell of the column. It will be used by the % mono-column blocks. % \begin{macrocode} \dim_set:Nn \l_@@_col_width_dim { #4 } \hbox_set:Nw \l_@@_cell_box \@@_cell_begin:w \str_set:Nn \l_@@_hpos_cell_str { #3 } } c < { \@@_cell_end: #1 \hbox_set_end: \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: \@@_adjust_size_box: \makebox [ #4 ] [ #3 ] { \box_use_drop:N \l_@@_cell_box } } } % \end{macrocode} % We increment the counter of columns and then we test for the presence of a |<|. % \begin{macrocode} \int_gincr:N \c@jCol \@@_patch_preamble_x:n } % \end{macrocode} % % \medskip % For |\@@_S:|. If the user has used |S[...]|, |S| has been replaced by |\@@_S:| % during the first expansion of the preamble (done with the tools of standard % LaTeX and \pkg{array}). % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_vi:n #1 { \str_if_eq:nnTF { #1 } { [ } { \@@_patch_preamble_vi_i:w [ } { \@@_patch_preamble_vi_i:w [ ] { #1 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_vi_i:w [ #1 ] { \@@_patch_preamble_vi_ii:n { #1 } } % \end{macrocode} % % For version of \pkg{siunitx} at least equal to 3.0, the adaptation is different % from previous ones. We test the version of \pkg{siunitx} by the existence of the % control sequence |\siunitx_cell_begin:w|. When we will decide that only the % previous posterior to 3.0 are supported by \pkg{nicematrix}, we will delete % the second definition of |\@@_patch_preamble_vi_ii:n|. % \begin{macrocode} \AtBeginDocument { \cs_if_exist:NTF \siunitx_cell_begin:w { \cs_new_protected:Npn \@@_patch_preamble_vi_ii:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_cell_begin:w \keys_set:nn { siunitx } { #1 } \siunitx_cell_begin:w } c < { \siunitx_cell_end: \@@_cell_end: } } % \end{macrocode} % We increment the counter of columns and then we test for the presence of a |<|. % \begin{macrocode} \int_gincr:N \c@jCol \@@_patch_preamble_x:n } } { \cs_new_protected:Npn \@@_patch_preamble_vi_ii:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_cell_begin:w \c_@@_table_collect_begin_tl S { #1 } } c < { \c_@@_table_print_tl \@@_cell_end: } } \int_gincr:N \c@jCol \@@_patch_preamble_x:n } } } % \end{macrocode} % % % \medskip % For |(|, |[| and |\{|. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_vii:nn #1 #2 { \bool_if:NT \l_@@_small_bool { \@@_fatal:n { Delimiter~with~small } } % \end{macrocode} % If we are before the column 1 and not in |{NiceArray}|, we reserve space for % the left delimiter. % \begin{macrocode} \int_compare:nNnTF \c@jCol = \c_zero_int { \str_if_eq:VnTF \g_@@_left_delim_tl { . } { % \end{macrocode} % In that case, in fact, the first letter of the preamble must be considered as % the left delimiter of the array. % \begin{macrocode} \tl_gset:Nn \g_@@_left_delim_tl { #1 } \tl_gset:Nn \g_@@_right_delim_tl { . } \@@_patch_preamble:n #2 } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } \@@_patch_preamble_vii_i:nn { #1 } { #2 } } } { \@@_patch_preamble_vii_i:nn { #1 } { #2 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_vii_i:nn #1 #2 { \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_delimiter:nnn #1 { \@@_succ:n \c@jCol } \c_true_bool } \tl_if_in:nnTF { ( [ \{ ) ] \} } { #2 } { \@@_error:nn { delimiter~after~opening } { #2 } \@@_patch_preamble:n } { \@@_patch_preamble:n #2 } } % \end{macrocode} % % \bigskip % For |)|, |]| and |\}|. We have two arguments for the following command because % we directly read the following letter in the preamble (we have to see whether % we have a opening delimiter following and we also have to see whether we are % at the end of the preamble because, in that case, our letter must be % considered as the right delimiter of the environment if the environment is % |{NiceArray}|). % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_viii:nn #1 #2 { \bool_if:NT \l_@@_small_bool { \@@_fatal:n { Delimiter~with~small } } \tl_if_in:nnTF { ) ] \} } { #2 } { \@@_patch_preamble_viii_i:nnn #1 #2 } { \tl_if_eq:nnTF { \q_stop } { #2 } { \str_if_eq:VnTF \g_@@_right_delim_tl { . } { \tl_gset:Nn \g_@@_right_delim_tl { #1 } } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } \@@_patch_preamble:n #2 } } { \tl_if_in:nnT { ( [ \{ } { #2 } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } } \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } \@@_patch_preamble:n #2 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_viii_i:nnn #1 #2 #3 { \tl_if_eq:nnTF { \q_stop } { #3 } { \str_if_eq:VnTF \g_@@_right_delim_tl { . } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } \tl_gset:Nn \g_@@_right_delim_tl { #2 } } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } \@@_error:nn { double~closing~delimiter } { #2 } } } { \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } \@@_error:nn { double~closing~delimiter } { #2 } \@@_patch_preamble:n #3 } } % \end{macrocode} % % \bigskip % For the case of a letter |X|. This specifier may take in an optional argument % (between square brackets). That's why we test whether there is a |[| after the % letter |X|. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_ix:n #1 { \str_if_eq:nnTF { #1 } { [ } { \@@_patch_preamble_ix_i:w [ } { \@@_patch_preamble_ix_i:w [ ] #1 } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_ix_i:w [ #1 ] { \@@_patch_preamble_ix_ii:n { #1 } } % \end{macrocode} % |#1| is the optional argument of the |X| specifier (a list of % \emph{key}-\emph{value} pairs). % % \medskip % The following set of keys is for the specifier |X| in the preamble of the % array. Such specifier may have as keys all the keys of % |{ WithArrows / p-column }| but also a key as 1, 2, 3, etc. The following set % of keys will be used to retrieve that value (in the counter |\l_@@_weight_int|). % \begin{macrocode} \keys_define:nn { WithArrows / X-column } { unknown .code:n = \int_set:Nn \l_@@_weight_int { \l_keys_key_str } } % \end{macrocode} % % % \medskip % In the following command, |#1| is the list of the options of the specifier |X|. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_ix_ii:n #1 { % \end{macrocode} % The possible values of |\l_@@_hpos_col_str| are |j| (for \emph{justified} which is % the initial value), |l|, |c| and |r| (when the user has used the corresponding % key in the optional argument of the specifier |X|). % \begin{macrocode} \str_set:Nn \l_@@_hpos_col_str { j } % \end{macrocode} % The possible values of |\l_@@_vpos_col_str| are |p| (the initial value), |m| and |b| % (when the user has used the corresponding key in the optional argument of the % specifier |X|). % \begin{macrocode} \tl_set:Nn \l_@@_vpos_col_str { p } % \end{macrocode} % % The integer |\l_@@_weight_int| will be the weight of the |X| column (the % initial value is $1$). The user may specify a different value (such as $2$, % $3$, etc.) by putting that value in the optional argument of the specifier. % The weights of the |X| columns are used in the computation of the actual width % of those columns as in \pkg{tabu} of \pkg{tabularray}. % \begin{macrocode} \int_zero_new:N \l_@@_weight_int \int_set:Nn \l_@@_weight_int { 1 } \keys_set_known:nnN { WithArrows / p-column } { #1 } \l_tmpa_tl \keys_set:nV { WithArrows / X-column } \l_tmpa_tl \int_gadd:Nn \g_@@_total_X_weight_int \l_@@_weight_int % \end{macrocode} % % We test whether we know the width of the |X|-columns by reading the |aux| file % (after the first compilation, the width of the |X|-columns is computed and % written in the |aux| file). % \begin{macrocode} \bool_if:NTF \l_@@_X_columns_aux_bool { \@@_patch_preamble_iv_iv:n { \l_@@_weight_int \l_@@_X_columns_dim } } { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_cell_begin:w \bool_set_true:N \l_@@_X_column_bool % \end{macrocode} % The following code will nullify the box of the cell. % \begin{macrocode} \tl_gput_right:Nn \g_@@_post_action_cell_tl { \hbox_set:Nn \l_@@_cell_box { } } % \end{macrocode} % We put a |{minipage}| to give to the user the ability to put a command such as % |\centering| in the |\RowStyle|. % \begin{macrocode} \begin { minipage } { 5 cm } \arraybackslash } c < { \end { minipage } \@@_cell_end: } } \int_gincr:N \c@jCol \@@_patch_preamble_x:n } } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_xi:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N 2\l_@@_radius_dim } } % \end{macrocode} % The command |\@@_vdottedline:n| is protected, and, therefore, won't be % expanded before writing on |\g_@@_internal_code_after_tl|. % \begin{macrocode} \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_vdottedline:n { \int_use:N \c@jCol } } \@@_patch_preamble:n } % \end{macrocode} % % \bigskip % After a specifier of column, we have to test whether there is one or several % |<{..}| because, after those potential |<{...}|, we have to insert % |!{\skip_horizontal:N ...}| when the key |vlines| is used. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_x:n #1 { \str_if_eq:nnTF { #1 } { < } \@@_patch_preamble_xii:n { \tl_if_eq:NnTF \l_@@_vlines_clist { all } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N \arrayrulewidth } } } { \exp_args:NNx \clist_if_in:NnT \l_@@_vlines_clist { \@@_succ:n \c@jCol } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N \arrayrulewidth } } } } \@@_patch_preamble:n { #1 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_preamble_xii:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { < { #1 } } \@@_patch_preamble_x:n } % \end{macrocode} % % % \bigskip % \subsection*{The redefinition of \textbackslash multicolumn} % % \medskip % The following command must \emph{not} be protected since it begins with % |\multispan| (a TeX primitive). % \begin{macrocode} \cs_new:Npn \@@_multicolumn:nnn #1 #2 #3 { % \end{macrocode} % The following lines are from the definition of |\multicolumn| in \pkg{array} % (and \emph{not} in standard LaTeX). The first line aims to raise an error if % the user has put more that one column specifier in the preamble of % |\multicolumn|. % \begin{macrocode} \multispan { #1 } \begingroup \cs_set:Npn \@addamp { \if@firstamp \@firstampfalse \else \@preamerr 5 \fi } % \end{macrocode} % % \medskip % You do the expansion of the (small) preamble with the tools of \pkg{array}. % \begin{macrocode} \@temptokena = { #2 } \@tempswatrue \@whilesw \if@tempswa \fi { \@tempswafalse \the \NC@list } % \end{macrocode} % % \medskip % Now, we patch the (small) preamble as we have done with the main preamble of % the array. % \begin{macrocode} \tl_gclear:N \g_@@_preamble_tl \exp_after:wN \@@_patch_m_preamble:n \the \@temptokena \q_stop % \end{macrocode} % % \medskip % The following lines are an adaptation of the definition of |\multicolumn| in % \pkg{array}. % \begin{macrocode} \exp_args:NV \@mkpream \g_@@_preamble_tl \@addtopreamble \@empty \endgroup % \end{macrocode} % % \medskip % Now, you do a treatment specific to \pkg{nicematrix} which has no equivalent % in the original definition of |\multicolumn|. % \begin{macrocode} \int_compare:nNnT { #1 } > 1 { \seq_gput_left:Nx \g_@@_multicolumn_cells_seq { \int_use:N \c@iRow - \@@_succ:n \c@jCol } \seq_gput_left:Nn \g_@@_multicolumn_sizes_seq { #1 } \seq_gput_right:Nx \g_@@_pos_of_blocks_seq { { \int_use:N \c@iRow } { \int_eval:n { \c@jCol + 1 } } { \int_use:N \c@iRow } { \int_eval:n { \c@jCol + #1 } } } } % \end{macrocode} % % \medskip % The following lines were in the original definition of |\multicolumn|. % \begin{macrocode} \cs_set:Npn \@sharp { #3 } \@arstrut \@preamble \null % \end{macrocode} % % \medskip % We add some lines. % \begin{macrocode} \int_gadd:Nn \c@jCol { #1 - 1 } \int_compare:nNnT \c@jCol > \g_@@_col_total_int { \int_gset_eq:NN \g_@@_col_total_int \c@jCol } \ignorespaces } % \end{macrocode} % % \bigskip % The following commands will patch the (small) preamble of the |\multicolumn|. % All those commands have a |m| in their name to recall that they deal with the % redefinition of |\multicolumn|. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble:n #1 { \str_case:nnF { #1 } { c { \@@_patch_m_preamble_i:n #1 } l { \@@_patch_m_preamble_i:n #1 } r { \@@_patch_m_preamble_i:n #1 } > { \@@_patch_m_preamble_ii:nn #1 } ! { \@@_patch_m_preamble_ii:nn #1 } @ { \@@_patch_m_preamble_ii:nn #1 } | { \@@_patch_m_preamble_iii:n #1 } p { \@@_patch_m_preamble_iv:nnn t #1 } m { \@@_patch_m_preamble_iv:nnn c #1 } b { \@@_patch_m_preamble_iv:nnn b #1 } \@@_w: { \@@_patch_m_preamble_v:nnnn { } #1 } \@@_W: { \@@_patch_m_preamble_v:nnnn { \cs_set_eq:NN \hss \hfil } #1 } \@@_true_c: { \@@_patch_m_preamble_vi:n #1 } \q_stop { } } { \@@_fatal:nn { unknown~column~type } { #1 } } } % \end{macrocode} % % \medskip % For |c|, |l| and |r| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_i:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_cell_begin:w \str_set:Nn \l_@@_hpos_cell_str { #1 } } #1 < \@@_cell_end: } % \end{macrocode} % % We test for the presence of a |<|. % \begin{macrocode} \@@_patch_m_preamble_x:n } % \end{macrocode} % % \medskip % For |>|, |!| and |@| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_ii:nn #1 #2 { \tl_gput_right:Nn \g_@@_preamble_tl { #1 { #2 } } \@@_patch_m_preamble:n } % \end{macrocode} % % % \medskip % For \verb+|+ % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_iii:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { #1 } \@@_patch_m_preamble:n } % \end{macrocode} % % \medskip % For |p|, |m| and |b| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_iv:nnn #1 #2 #3 { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_cell_begin:w \begin { minipage } [ #1 ] { \dim_eval:n { #3 } } \mode_leave_vertical: \arraybackslash \vrule height \box_ht:N \@arstrutbox depth 0 pt width 0 pt } c < { \vrule height 0 pt depth \box_dp:N \@arstrutbox width 0 pt \end { minipage } \@@_cell_end: } } % \end{macrocode} % We test for the presence of a |<|. % \begin{macrocode} \@@_patch_m_preamble_x:n } % \end{macrocode} % % \medskip % For |w| and |W| % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_v:nnnn #1 #2 #3 #4 { \tl_gput_right:Nn \g_@@_preamble_tl { > { \hbox_set:Nw \l_@@_cell_box \@@_cell_begin:w \str_set:Nn \l_@@_hpos_cell_str { #3 } } c < { \@@_cell_end: #1 \hbox_set_end: \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: \@@_adjust_size_box: \makebox [ #4 ] [ #3 ] { \box_use_drop:N \l_@@_cell_box } } } % \end{macrocode} % We test for the presence of a |<|. % \begin{macrocode} \@@_patch_m_preamble_x:n } % \end{macrocode} % % \medskip % For |\@@_true_c:| which will appear in our redefinition of the columns of type % |S| (of \pkg{siunitx}). % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_vi:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { c } % \end{macrocode} % We test for the presence of a |<|. % \begin{macrocode} \@@_patch_m_preamble_x:n } % \end{macrocode} % % % After a specifier of column, we have to test whether there is one or several % |<{..}| because, after those potential |<{...}|, we have to insert % |!{\skip_horizontal:N ...}| when the key |vlines| is used. % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_x:n #1 { \str_if_eq:nnTF { #1 } { < } \@@_patch_m_preamble_ix:n { \tl_if_eq:NnTF \l_@@_vlines_clist { all } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N \arrayrulewidth } } } { \exp_args:NNx \clist_if_in:NnT \l_@@_vlines_clist { \@@_succ:n \c@jCol } { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \skip_horizontal:N \arrayrulewidth } } } } \@@_patch_m_preamble:n { #1 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_m_preamble_ix:n #1 { \tl_gput_right:Nn \g_@@_preamble_tl { < { #1 } } \@@_patch_m_preamble_x:n } % \end{macrocode} % % % % \bigskip % The command |\@@_put_box_in_flow:| puts the box |\l_tmpa_box| (which contains % the array) in the flow. It is used for the environments with delimiters. % First, we have to modify the height and the depth to take back into account % the potential exterior rows (the total height of the first row has been % computed in |\l_tmpa_dim| and the total height of the potential last row in % |\l_tmpb_dim|). % \begin{macrocode} \cs_new_protected:Npn \@@_put_box_in_flow: { \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + \l_tmpa_dim } \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + \l_tmpb_dim } \tl_if_eq:NnTF \l_@@_baseline_tl { c } { \box_use_drop:N \l_tmpa_box } \@@_put_box_in_flow_i: } % \end{macrocode} % % \medskip % The command |\@@_put_box_in_flow_i:| is used when the value of % |\l_@@_baseline_tl| is different of |c| (which is the initial value and the % most used). % \begin{macrocode} \cs_new_protected:Npn \@@_put_box_in_flow_i: { \pgfpicture \@@_qpoint:n { row - 1 } \dim_gset_eq:NN \g_tmpa_dim \pgf@y \@@_qpoint:n { row - \@@_succ:n \c@iRow } \dim_gadd:Nn \g_tmpa_dim \pgf@y \dim_gset:Nn \g_tmpa_dim { 0.5 \g_tmpa_dim } % \end{macrocode} % Now, |\g_tmpa_dim| contains the $y$-value of the center of the array (the % delimiters are centered in relation with this value). % \begin{macrocode} \str_if_in:NnTF \l_@@_baseline_tl { line- } { \int_set:Nn \l_tmpa_int { \str_range:Nnn \l_@@_baseline_tl 6 { \tl_count:V \l_@@_baseline_tl } } \@@_qpoint:n { row - \int_use:N \l_tmpa_int } } { \str_case:VnF \l_@@_baseline_tl { { t } { \int_set:Nn \l_tmpa_int 1 } { b } { \int_set_eq:NN \l_tmpa_int \c@iRow } } { \int_set:Nn \l_tmpa_int \l_@@_baseline_tl } \bool_lazy_or:nnT { \int_compare_p:nNn \l_tmpa_int < \l_@@_first_row_int } { \int_compare_p:nNn \l_tmpa_int > \g_@@_row_total_int } { \@@_error:n { bad~value~for~baseline } \int_set:Nn \l_tmpa_int 1 } \@@_qpoint:n { row - \int_use:N \l_tmpa_int - base } % \end{macrocode} % We take into account the position of the mathematical axis. % \begin{macrocode} \dim_gsub:Nn \g_tmpa_dim { \fontdimen22 \textfont2 } } \dim_gsub:Nn \g_tmpa_dim \pgf@y % \end{macrocode} % Now, |\g_tmpa_dim| contains the value of the $y$ translation we have to to. % \begin{macrocode} \endpgfpicture \box_move_up:nn \g_tmpa_dim { \box_use_drop:N \l_tmpa_box } \box_use_drop:N \l_tmpa_box } % \end{macrocode} % % \bigskip % The following command is \emph{always} used by |{NiceArrayWithDelims}| (even % if, in fact, there is no tabular notes: in fact, it's not possible to know % whether there is tabular notes or not before the composition of the blocks). % \begin{macrocode} \cs_new_protected:Npn \@@_use_arraybox_with_notes_c: { % \end{macrocode} % With an environment |{Matrix}|, you want to remove the exterior |\arraycolsep| % but we don't know the number of columns (since there is no preamble) and % that's why we can't put |@{}| at the end of the preamble. That's why we remove % a |\arraycolsep| now. % \begin{macrocode} \bool_lazy_and:nnT \l_@@_Matrix_bool \l_@@_NiceArray_bool { \box_set_wd:Nn \l_@@_the_array_box { \box_wd:N \l_@@_the_array_box - \arraycolsep } } % \end{macrocode} % We need a |{minipage}| because we will insert a LaTeX list for the tabular % notes (that means that a |\vtop{\hsize=...}| is not enough). % \begin{macrocode} \begin { minipage } [ t ] { \box_wd:N \l_@@_the_array_box } % \end{macrocode} % The |\hbox| avoids that the |pgfpicture| inside |\@@_draw_blocks| adds a extra % vertical space before the notes. % \begin{macrocode} \hbox:n { \box_use_drop:N \l_@@_the_array_box % \end{macrocode} % We have to draw the blocks right now because there may be tabular notes in % some blocks (which are not mono-column: the blocks which are mono-column % have been composed in boxes yet)... and we have to create (potentially) the % extra nodes before creating the blocks since there are |medium| nodes to create % for the blocks. % \begin{macrocode} \@@_create_extra_nodes: \seq_if_empty:NF \g_@@_blocks_seq \@@_draw_blocks: } \bool_lazy_or:nnT { \int_compare_p:nNn \c@tabularnote > 0 } { ! \tl_if_empty_p:V \l_@@_tabularnote_tl } \@@_insert_tabularnotes: \end { minipage } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_insert_tabularnotes: { \skip_vertical:N 0.65ex % \end{macrocode} % The TeX group is for potential specifications in the % |\l_@@_notes_code_before_tl|. % \begin{macrocode} \group_begin: \l_@@_notes_code_before_tl \tl_if_empty:NF \l_@@_tabularnote_tl { \l_@@_tabularnote_tl \par } % \end{macrocode} % We compose the tabular notes with a list of \pkg{enumitem}. The |\strut| and % the |\unskip| are designed to give the ability to put a |\bottomrule| at the % end of the notes with a good vertical space. % \begin{macrocode} \int_compare:nNnT \c@tabularnote > 0 { \bool_if:NTF \l_@@_notes_para_bool { \begin { tabularnotes* } \seq_map_inline:Nn \g_@@_tabularnotes_seq { \item ##1 } \strut \end { tabularnotes* } % \end{macrocode} % The following |\par| is mandatory for the event that the user has put % |\footnotesize| (for example) in the |notes/code-before|. % \begin{macrocode} \par } { \tabularnotes \seq_map_inline:Nn \g_@@_tabularnotes_seq { \item ##1 } \strut \endtabularnotes } } \unskip \group_end: \bool_if:NT \l_@@_notes_bottomrule_bool { \bool_if:NTF \c_@@_booktabs_loaded_bool { % \end{macrocode} % The two dimensions |\aboverulesep| et |\heavyrulewidth| are parameters defined % by \pkg{booktabs}. % \begin{macrocode} \skip_vertical:N \aboverulesep % \end{macrocode} % |\CT@arc@| is the specification of color defined by \pkg{colortbl} but you use it % even if \pkg{colortbl} is not loaded. % \begin{macrocode} { \CT@arc@ \hrule height \heavyrulewidth } } { \@@_error:n { bottomrule~without~booktabs } } } \l_@@_notes_code_after_tl \seq_gclear:N \g_@@_tabularnotes_seq \int_gzero:N \c@tabularnote } % \end{macrocode} % % \medskip % The case of |baseline| equal to |b|. Remember that, when the key |b| is used, % the |{array}| (of \pkg{array}) is constructed with the option |t| (and not % |b|). Now, we do the translation to take into account the option |b|. % \begin{macrocode} \cs_new_protected:Npn \@@_use_arraybox_with_notes_b: { \pgfpicture \@@_qpoint:n { row - 1 } \dim_gset_eq:NN \g_tmpa_dim \pgf@y \@@_qpoint:n { row - \int_use:N \c@iRow - base } \dim_gsub:Nn \g_tmpa_dim \pgf@y \endpgfpicture \dim_gadd:Nn \g_tmpa_dim \arrayrulewidth \int_compare:nNnT \l_@@_first_row_int = 0 { \dim_gadd:Nn \g_tmpa_dim \g_@@_ht_row_zero_dim \dim_gadd:Nn \g_tmpa_dim \g_@@_dp_row_zero_dim } \box_move_up:nn \g_tmpa_dim { \hbox { \@@_use_arraybox_with_notes_c: } } } % \end{macrocode} % % \medskip % Now, the general case. % \begin{macrocode} \cs_new_protected:Npn \@@_use_arraybox_with_notes: { % \end{macrocode} % We convert a value of |t| to a value of |1|. % \begin{macrocode} \tl_if_eq:NnT \l_@@_baseline_tl { t } { \tl_set:Nn \l_@@_baseline_tl { 1 } } % \end{macrocode} % Now, we convert the value of |\l_@@_baseline_tl| (which should represent an % integer) to an integer stored in |\l_tmpa_int|. % \begin{macrocode} \pgfpicture \@@_qpoint:n { row - 1 } \dim_gset_eq:NN \g_tmpa_dim \pgf@y \str_if_in:NnTF \l_@@_baseline_tl { line- } { \int_set:Nn \l_tmpa_int { \str_range:Nnn \l_@@_baseline_tl 6 { \tl_count:V \l_@@_baseline_tl } } \@@_qpoint:n { row - \int_use:N \l_tmpa_int } } { \int_set:Nn \l_tmpa_int \l_@@_baseline_tl \bool_lazy_or:nnT { \int_compare_p:nNn \l_tmpa_int < \l_@@_first_row_int } { \int_compare_p:nNn \l_tmpa_int > \g_@@_row_total_int } { \@@_error:n { bad~value~for~baseline } \int_set:Nn \l_tmpa_int 1 } \@@_qpoint:n { row - \int_use:N \l_tmpa_int - base } } \dim_gsub:Nn \g_tmpa_dim \pgf@y \endpgfpicture \dim_gadd:Nn \g_tmpa_dim \arrayrulewidth \int_compare:nNnT \l_@@_first_row_int = 0 { \dim_gadd:Nn \g_tmpa_dim \g_@@_ht_row_zero_dim \dim_gadd:Nn \g_tmpa_dim \g_@@_dp_row_zero_dim } \box_move_up:nn \g_tmpa_dim { \hbox { \@@_use_arraybox_with_notes_c: } } } % \end{macrocode} % % % % \bigskip % The command |\@@_put_box_in_flow_bis:| is used when the option % |delimiters/max-width| is used because, in this case, we have to adjust the % widths of the delimiters. The arguments |#1| and |#2| are the delimiters % specified by the user. % \begin{macrocode} \cs_new_protected:Npn \@@_put_box_in_flow_bis:nn #1 #2 { % \end{macrocode} % We will compute the real width of both delimiters used. % \begin{macrocode} \dim_zero_new:N \l_@@_real_left_delim_dim \dim_zero_new:N \l_@@_real_right_delim_dim \hbox_set:Nn \l_tmpb_box { \c_math_toggle_token \left #1 \vcenter { \vbox_to_ht:nn % \end{macrocode} % Here, you should use |\box_ht_plus_dp:N| when TeXLive 2021 will be available % on Overleaf. % \begin{macrocode} { \box_ht:N \l_tmpa_box + \box_dp:N \l_tmpa_box } { } } \right . \c_math_toggle_token } \dim_set:Nn \l_@@_real_left_delim_dim { \box_wd:N \l_tmpb_box - \nulldelimiterspace } \hbox_set:Nn \l_tmpb_box { \c_math_toggle_token \left . \vbox_to_ht:nn % \end{macrocode} % Here, you should use |\box_ht_plus_dp:N| when TeXLive 2021 will be available % on Overleaf. % \begin{macrocode} { \box_ht:N \l_tmpa_box + \box_dp:N \l_tmpa_box } { } \right #2 \c_math_toggle_token } \dim_set:Nn \l_@@_real_right_delim_dim { \box_wd:N \l_tmpb_box - \nulldelimiterspace } % \end{macrocode} % % Now, we can put the box in the TeX flow with the horizontal adjustments on % both sides. % \begin{macrocode} \skip_horizontal:N \l_@@_left_delim_dim \skip_horizontal:N -\l_@@_real_left_delim_dim \@@_put_box_in_flow: \skip_horizontal:N \l_@@_right_delim_dim \skip_horizontal:N -\l_@@_real_right_delim_dim } % \end{macrocode} % % \interitem % The construction of the array in the environment |{NiceArrayWithDelims}| is, % in fact, done by the environment |{@@-light-syntax}| or by the environment % |{@@-normal-syntax}| (whether the option |light-syntax| is in force or not). % When the key |light-syntax| is not used, the construction is a standard % environment (and, thus, it's possible to use verbatim in the array). % \begin{macrocode} \NewDocumentEnvironment { @@-normal-syntax } { } % \end{macrocode} % First, we test whether the environment is empty. If it is empty, we raise a % fatal error (it's only a security). In order to detect whether it is empty, we % test whether the next token is |\end| and, if it's the case, we test if this % is the end of the environment (if it is not, an standard error will be raised % by LaTeX for incorrect nested environments). % \begin{macrocode} { \peek_meaning_ignore_spaces:NTF \end \@@_analyze_end:Nn % \end{macrocode} % Here is the call to |\array| (we have a dedicated macro |\@@_array:| because % of compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}). % \begin{macrocode} { \exp_args:NV \@@_array: \g_@@_preamble_tl } } { \@@_create_col_nodes: \endarray } % \end{macrocode} % % % \bigskip % When the key |light-syntax| is in force, we use an environment which takes its % whole body as an argument (with the specifier |b| of \pkg{xparse}). % % \label{code-light-syntax} % \begin{macrocode} \NewDocumentEnvironment { @@-light-syntax } { b } { % \end{macrocode} % First, we test whether the environment is empty. It's only a security. Of % course, this test is more easy than the similar test for the ``normal syntax'' % because we have the whole body of the environment in |#1|. % \begin{macrocode} \tl_if_empty:nT { #1 } { \@@_fatal:n { empty~environment } } \tl_map_inline:nn { #1 } { \str_if_eq:nnT { ##1 } { & } { \@@_fatal:n { ampersand~in~light-syntax } } \str_if_eq:nnT { ##1 } { \\ } { \@@_fatal:n { double-backslash~in~light-syntax } } } % \end{macrocode} % Now, you extract the |\CodeAfter| of the body of the environment. Maybe, there % is no command |\CodeAfter| in the body. That's why you put a marker % |\CodeAfter| after |#1|. If there is yet a |\CodeAfter| in |#1|, this second % (or third...) |\CodeAfter| will be catched in the value of % |\g_nicematrix_code_after_tl|. That doesn't matter because |\CodeAfter| will % be set to \textsl{no-op} before the execution of % |\g_nicematrix_code_after_tl|. % \begin{macrocode} \@@_light_syntax_i #1 \CodeAfter \q_stop } % \end{macrocode} % Now, the second part of the environment. It is empty. That's not surprising % because we have caught the whole body of the environment with the specifier % |b| provided by \pkg{xparse}. % \begin{macrocode} { } % \end{macrocode} % % % \begin{macrocode} \cs_new_protected:Npn \@@_light_syntax_i #1\CodeAfter #2\q_stop { \tl_gput_right:Nn \g_nicematrix_code_after_tl { #2 } % \end{macrocode} % The body of the array, which is stored in the argument |#1|, is now % splitted into items (and \emph{not} tokens). % \begin{macrocode} \seq_gclear_new:N \g_@@_rows_seq \tl_set_rescan:Nno \l_@@_end_of_row_tl { } \l_@@_end_of_row_tl \exp_args:NNV \seq_gset_split:Nnn \g_@@_rows_seq \l_@@_end_of_row_tl { #1 } % \end{macrocode} % If the environment uses the option |last-row| without value (i.e. without % saying the number of the rows), we have now the opportunity to know that % value. We do it, and so, if the token list |\l_@@_code_for_last_row_tl| is not % empty, we will use directly where it should be. % \begin{macrocode} \int_compare:nNnT \l_@@_last_row_int = { -1 } { \int_set:Nn \l_@@_last_row_int { \seq_count:N \g_@@_rows_seq } } % \end{macrocode} % Here is the call to |\array| (we have a dedicated macro |\@@_array:| because % of compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}). % \begin{macrocode} \exp_args:NV \@@_array: \g_@@_preamble_tl % \end{macrocode} % We need a global affectation because, when executing |\l_tmpa_tl|, we will % exit the first cell of the array. % \begin{macrocode} \seq_gpop_left:NN \g_@@_rows_seq \l_tmpa_tl \exp_args:NV \@@_line_with_light_syntax_i:n \l_tmpa_tl \seq_map_function:NN \g_@@_rows_seq \@@_line_with_light_syntax:n \@@_create_col_nodes: \endarray } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_line_with_light_syntax:n #1 { \tl_if_empty:nF { #1 } { \\ \@@_line_with_light_syntax_i:n { #1 } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_line_with_light_syntax_i:n #1 { \seq_gclear_new:N \g_@@_cells_seq \seq_gset_split:Nnn \g_@@_cells_seq { ~ } { #1 } \seq_gpop_left:NN \g_@@_cells_seq \l_tmpa_tl \l_tmpa_tl \seq_map_inline:Nn \g_@@_cells_seq { & ##1 } } % \end{macrocode} % % \bigskip % The following command is used by the code which detects whether the % environment is empty (we raise a fatal error in this case: it's only a % security). % \begin{macrocode} \cs_new_protected:Npn \@@_analyze_end:Nn #1 #2 { \str_if_eq:VnT \g_@@_name_env_str { #2 } { \@@_fatal:n { empty~environment } } % \end{macrocode} % We reput in the stream the |\end{...}| we have extracted and the user will % have an error for incorrect nested environments. % \begin{macrocode} \end { #2 } } % \end{macrocode} % % \bigskip % The command |\@@_create_col_nodes:| will construct a special last row. % That last row is a false row used to create the |col| nodes and to fix the % width of the columns (when the array is constructed with an option which % specifies the width of the columns). % \begin{macrocode} \cs_new:Npn \@@_create_col_nodes: { \crcr \int_compare:nNnT \l_@@_first_col_int = 0 { \omit \hbox_overlap_left:n { \bool_if:NT \l_@@_code_before_bool { \pgfsys@markposition { \@@_env: - col - 0 } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - 0 } \pgfpointorigin \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - 0 } { \@@_env: - col - 0 } } \endpgfpicture \skip_horizontal:N 2\col@sep \skip_horizontal:N \g_@@_width_first_col_dim } & } \omit % \end{macrocode} % The following instruction must be put after the instruction |\omit|. % \begin{macrocode} \bool_gset_true:N \g_@@_row_of_col_done_bool % \end{macrocode} % First, we put a |col| node on the left of the first column (of course, we % have to do that \emph{after} the |\omit|). % \begin{macrocode} \int_compare:nNnTF \l_@@_first_col_int = 0 { \bool_if:NT \l_@@_code_before_bool { \hbox { \skip_horizontal:N -0.5\arrayrulewidth \pgfsys@markposition { \@@_env: - col - 1 } \skip_horizontal:N 0.5\arrayrulewidth } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - 1 } { \pgfpoint { - 0.5 \arrayrulewidth } \c_zero_dim } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - 1 } { \@@_env: - col - 1 } } \endpgfpicture } { \bool_if:NT \l_@@_code_before_bool { \hbox { \skip_horizontal:N 0.5\arrayrulewidth \pgfsys@markposition { \@@_env: - col - 1 } \skip_horizontal:N -0.5\arrayrulewidth } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - 1 } { \pgfpoint { 0.5 \arrayrulewidth } \c_zero_dim } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - 1 } { \@@_env: - col - 1 } } \endpgfpicture } % \end{macrocode} % We compute in |\g_tmpa_skip| the common width of the columns (it's a skip and % not a dimension). We use a global variable because we are in a cell of an % |\halign| and because we have to use this variable in other cells (of the same % row). The affectation of |\g_tmpa_skip|, like all the affectations, must be % done after the |\omit| of the cell. % % \smallskip % We give a default value for |\g_tmpa_skip| (|0 pt plus 1 fill|) but it will % just after be erased by a fixed value in the concerned cases. % \begin{macrocode} \skip_gset:Nn \g_tmpa_skip { 0 pt~plus 1 fill } \bool_if:NF \l_@@_auto_columns_width_bool { \dim_compare:nNnT \l_@@_columns_width_dim > \c_zero_dim } { \bool_lazy_and:nnTF \l_@@_auto_columns_width_bool { \bool_not_p:n \l_@@_block_auto_columns_width_bool } { \skip_gset_eq:NN \g_tmpa_skip \g_@@_max_cell_width_dim } { \skip_gset_eq:NN \g_tmpa_skip \l_@@_columns_width_dim } \skip_gadd:Nn \g_tmpa_skip { 2 \col@sep } } \skip_horizontal:N \g_tmpa_skip \hbox { \bool_if:NT \l_@@_code_before_bool { \hbox { \skip_horizontal:N -0.5\arrayrulewidth \pgfsys@markposition { \@@_env: - col - 2 } \skip_horizontal:N 0.5\arrayrulewidth } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - 2 } { \pgfpoint { - 0.5 \arrayrulewidth } \c_zero_dim } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - 2 } { \@@_env: - col - 2 } } \endpgfpicture } % \end{macrocode} % We begin a loop over the columns. The integer |\g_tmpa_int| will be the % number of the current column. This integer is used for the Tikz nodes. % \begin{macrocode} \int_gset:Nn \g_tmpa_int 1 \bool_if:NTF \g_@@_last_col_found_bool { \prg_replicate:nn { \int_max:nn { \g_@@_col_total_int - 3 } 0 } } { \prg_replicate:nn { \int_max:nn { \g_@@_col_total_int - 2 } 0 } } { & \omit \int_gincr:N \g_tmpa_int % \end{macrocode} % The incrementation of the counter |\g_tmpa_int| must be done after the |\omit| % of the cell. % \begin{macrocode} \skip_horizontal:N \g_tmpa_skip \bool_if:NT \l_@@_code_before_bool { \hbox { \skip_horizontal:N -0.5\arrayrulewidth \pgfsys@markposition { \@@_env: - col - \@@_succ:n \g_tmpa_int } \skip_horizontal:N 0.5\arrayrulewidth } } % \end{macrocode} % We create the |col| node on the right of the current column. % \begin{macrocode} \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - \@@_succ:n \g_tmpa_int } { \pgfpoint { - 0.5 \arrayrulewidth } \c_zero_dim } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - \@@_succ:n \g_tmpa_int } { \@@_env: - col - \@@_succ:n \g_tmpa_int } } \endpgfpicture } % \end{macrocode} % % \bigskip % \begin{macrocode} & \omit \int_gincr:N \g_tmpa_int \skip_horizontal:N \g_tmpa_skip \bool_lazy_all:nT { \l_@@_NiceArray_bool { \bool_not_p:n \l_@@_NiceTabular_bool } { \clist_if_empty_p:N \l_@@_vlines_clist } { \bool_not_p:n \l_@@_exterior_arraycolsep_bool } { ! \l_@@_bar_at_end_of_pream_bool } } { \skip_horizontal:N -\col@sep } \bool_if:NT \l_@@_code_before_bool { \hbox { \skip_horizontal:N -0.5\arrayrulewidth % \end{macrocode} % With an environment |{Matrix}|, you want to remove the exterior |\arraycolsep| % but we don't know the number of columns (since there is no preamble) and % that's why we can't put |@{}| at the end of the preamble. That's why we remove % a |\arraycolsep| now. % \begin{macrocode} \bool_lazy_and:nnT \l_@@_Matrix_bool \l_@@_NiceArray_bool { \skip_horizontal:N -\arraycolsep } \pgfsys@markposition { \@@_env: - col - \@@_succ:n \g_tmpa_int } \skip_horizontal:N 0.5\arrayrulewidth \bool_lazy_and:nnT \l_@@_Matrix_bool \l_@@_NiceArray_bool { \skip_horizontal:N \arraycolsep } } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - \@@_succ:n \g_tmpa_int } { \bool_lazy_and:nnTF \l_@@_Matrix_bool \l_@@_NiceArray_bool { \pgfpoint { - 0.5 \arrayrulewidth - \arraycolsep } \c_zero_dim } { \pgfpoint { - 0.5 \arrayrulewidth } \c_zero_dim } } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - \@@_succ:n \g_tmpa_int } { \@@_env: - col - \@@_succ:n \g_tmpa_int } } \endpgfpicture % \end{macrocode} % % \bigskip % \begin{macrocode} \bool_if:NT \g_@@_last_col_found_bool { \hbox_overlap_right:n { \skip_horizontal:N \g_@@_width_last_col_dim \bool_if:NT \l_@@_code_before_bool { \pgfsys@markposition { \@@_env: - col - \@@_succ:n \g_@@_col_total_int } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgfcoordinate { \@@_env: - col - \@@_succ:n \g_@@_col_total_int } \pgfpointorigin \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - col - \@@_succ:n \g_@@_col_total_int } { \@@_env: - col - \@@_succ:n \g_@@_col_total_int } } \endpgfpicture } } \cr } % \end{macrocode} % % % \interitem % Here is the preamble for the ``first column'' (if the user uses the key % |first-col|) % \begin{macrocode} \tl_const:Nn \c_@@_preamble_first_col_tl { > { % \end{macrocode} % At the beginning of the cell, we link |\CodeAfter| to a command which do % \emph{not} begin with |\omit| (whereas the standard version of |\CodeAfter| % begins with |\omit|). % \begin{macrocode} \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i:n \bool_gset_true:N \g_@@_after_col_zero_bool \@@_begin_of_row: % \end{macrocode} % The contents of the cell is constructed in the box |\l_@@_cell_box| because we % have to compute some dimensions of this box. % \begin{macrocode} \hbox_set:Nw \l_@@_cell_box \@@_math_toggle_token: \bool_if:NT \l_@@_small_bool \scriptstyle % \end{macrocode} % We insert |\l_@@_code_for_first_col_tl|... but we don't insert it in the % potential ``first row'' and in the potential ``last row''. % \begin{macrocode} \bool_lazy_and:nnT { \int_compare_p:nNn \c@iRow > 0 } { \bool_lazy_or_p:nn { \int_compare_p:nNn \l_@@_last_row_int < 0 } { \int_compare_p:nNn \c@iRow < \l_@@_last_row_int } } { \l_@@_code_for_first_col_tl \xglobal \colorlet { nicematrix-first-col } { . } } } % \end{macrocode} % Be careful: despite this letter |l| the cells of the ``first column'' are % composed in a |R| manner since they are composed in a |\hbox_overlap_left:n|. % \begin{macrocode} l < { \@@_math_toggle_token: \hbox_set_end: \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: \@@_adjust_size_box: \@@_update_for_first_and_last_row: % \end{macrocode} % We actualise the width of the ``first column'' because we will use this width % after the construction of the array. % \begin{macrocode} \dim_gset:Nn \g_@@_width_first_col_dim { \dim_max:nn \g_@@_width_first_col_dim { \box_wd:N \l_@@_cell_box } } % \end{macrocode} % The content of the cell is inserted in an overlapping position. % \label{overlap-left} % \begin{macrocode} \hbox_overlap_left:n { \dim_compare:nNnTF { \box_wd:N \l_@@_cell_box } > \c_zero_dim \@@_node_for_cell: { \box_use_drop:N \l_@@_cell_box } \skip_horizontal:N \l_@@_left_delim_dim \skip_horizontal:N \l_@@_left_margin_dim \skip_horizontal:N \l_@@_extra_left_margin_dim } \bool_gset_false:N \g_@@_empty_cell_bool \skip_horizontal:N -2\col@sep } } % \end{macrocode} % % % Here is the preamble for the ``last column'' (if the user uses the key % |last-col|). % \begin{macrocode} \tl_const:Nn \c_@@_preamble_last_col_tl { > { % \end{macrocode} % At the beginning of the cell, we link |\CodeAfter| to a command which do % \emph{not} begin with |\omit| (whereas the standard version of |\CodeAfter| % begins with |\omit|). % \begin{macrocode} \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i:n % \end{macrocode} % With the flag |\g_@@_last_col_found_bool|, we will know that the ``last % column'' is really used. % \begin{macrocode} \bool_gset_true:N \g_@@_last_col_found_bool \int_gincr:N \c@jCol \int_gset_eq:NN \g_@@_col_total_int \c@jCol % \end{macrocode} % The contents of the cell is constructed in the box |\l_tmpa_box| because we % have to compute some dimensions of this box. % \begin{macrocode} \hbox_set:Nw \l_@@_cell_box \@@_math_toggle_token: \bool_if:NT \l_@@_small_bool \scriptstyle % \end{macrocode} % We insert |\l_@@_code_for_last_col_tl|... but we don't insert it in the % potential ``first row'' and in the potential ``last row''. % \begin{macrocode} \int_compare:nNnT \c@iRow > 0 { \bool_lazy_or:nnT { \int_compare_p:nNn \l_@@_last_row_int < 0 } { \int_compare_p:nNn \c@iRow < \l_@@_last_row_int } { \l_@@_code_for_last_col_tl \xglobal \colorlet { nicematrix-last-col } { . } } } } l < { \@@_math_toggle_token: \hbox_set_end: \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: \@@_adjust_size_box: \@@_update_for_first_and_last_row: % \end{macrocode} % We actualise the width of the ``last column'' because we will use this width % after the construction of the array. % \begin{macrocode} \dim_gset:Nn \g_@@_width_last_col_dim { \dim_max:nn \g_@@_width_last_col_dim { \box_wd:N \l_@@_cell_box } } \skip_horizontal:N -2\col@sep % \end{macrocode} % The content of the cell is inserted in an overlapping position. % \label{overlap-right} % \begin{macrocode} \hbox_overlap_right:n { \dim_compare:nNnT { \box_wd:N \l_@@_cell_box } > \c_zero_dim { \skip_horizontal:N \l_@@_right_delim_dim \skip_horizontal:N \l_@@_right_margin_dim \skip_horizontal:N \l_@@_extra_right_margin_dim \@@_node_for_cell: } } \bool_gset_false:N \g_@@_empty_cell_bool } } % \end{macrocode} % % % \interitem % The environment |{NiceArray}| is constructed upon the environment % |{NiceArrayWithDelims}| but, in fact, there is a flag |\l_@@_NiceArray_bool|. % In |{NiceArrayWithDelims}|, some special code will be executed if this flag is % raised. % \begin{macrocode} \NewDocumentEnvironment { NiceArray } { } { \bool_set_true:N \l_@@_NiceArray_bool \str_if_empty:NT \g_@@_name_env_str { \str_gset:Nn \g_@@_name_env_str { NiceArray } } % \end{macrocode} % We put . and . for the delimiters but, in fact, that doesn't matter because % these arguments won't be used in |{NiceArrayWithDelims}| (because the flag % |\l_@@_NiceArray_bool| is raised). % \begin{macrocode} \NiceArrayWithDelims . . } { \endNiceArrayWithDelims } % \end{macrocode} % % % \interitem % We create the variants of the environment |{NiceArrayWithDelims}|. % % \begin{macrocode} \cs_new_protected:Npn \@@_def_env:nnn #1 #2 #3 { \NewDocumentEnvironment { #1 NiceArray } { } { \str_if_empty:NT \g_@@_name_env_str { \str_gset:Nn \g_@@_name_env_str { #1 NiceArray } } \@@_test_if_math_mode: \NiceArrayWithDelims #2 #3 } { \endNiceArrayWithDelims } } % \end{macrocode} % % \begin{macrocode} \@@_def_env:nnn p ( ) \@@_def_env:nnn b [ ] \@@_def_env:nnn B \{ \} \@@_def_env:nnn v | | \@@_def_env:nnn V \| \| % \end{macrocode} % % % \bigskip % \subsection*{The environment \{NiceMatrix\} and its variants} % % % \begin{macrocode} \cs_new_protected:Npn \@@_begin_of_NiceMatrix:nn #1 #2 { \bool_set_true:N \l_@@_Matrix_bool \use:c { #1 NiceArray } { * { \int_compare:nNnTF \l_@@_last_col_int < 0 \c@MaxMatrixCols { \@@_pred:n \l_@@_last_col_int } } { > \@@_cell_begin:w #2 < \@@_cell_end: } } } % \end{macrocode} % % \begin{macrocode} \clist_map_inline:nn { { } , p , b , B , v , V } { \NewDocumentEnvironment { #1 NiceMatrix } { ! O { } } { \str_gset:Nn \g_@@_name_env_str { #1 NiceMatrix } \tl_set:Nn \l_@@_type_of_col_tl c \keys_set:nn { NiceMatrix / NiceMatrix } { ##1 } \exp_args:Nne \@@_begin_of_NiceMatrix:nn { #1 } \l_@@_type_of_col_tl } { \use:c { end #1 NiceArray } } } % \end{macrocode} % % \bigskip % The following command will be linked to |\NotEmpty| in the environments of % \pkg{nicematrix}. % \begin{macrocode} \cs_new_protected:Npn \@@_NotEmpty: { \bool_gset_true:N \g_@@_not_empty_cell_bool } % \end{macrocode} % % \bigskip % \subsection*{\{NiceTabular\}, \{NiceTabularX\} and \{NiceTabular*\}} % % \begin{macrocode} \NewDocumentEnvironment { NiceTabular } { O { } m ! O { } } { % \end{macrocode} % The dimension |\l_@@_width_dim| will be used if at least one column of type % |X| is used. % % \begin{macrocode} \dim_zero_new:N \l_@@_width_dim \dim_set_eq:NN \l_@@_width_dim \linewidth \str_gset:Nn \g_@@_name_env_str { NiceTabular } \keys_set:nn { NiceMatrix / NiceTabular } { #1 , #3 } \bool_set_true:N \l_@@_NiceTabular_bool \NiceArray { #2 } } { \endNiceArray } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentEnvironment { NiceTabularX } { m O { } m ! O { } } { \str_gset:Nn \g_@@_name_env_str { NiceTabularX } \dim_zero_new:N \l_@@_width_dim \dim_set:Nn \l_@@_width_dim { #1 } \keys_set:nn { NiceMatrix / NiceTabular } { #2 , #4 } \bool_set_true:N \l_@@_NiceTabular_bool \NiceArray { #3 } } { \endNiceArray } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentEnvironment { NiceTabular* } { m O { } m ! O { } } { \str_gset:Nn \g_@@_name_env_str { NiceTabular* } \dim_set:Nn \l_@@_tabular_width_dim { #1 } \keys_set:nn { NiceMatrix / NiceTabular } { #2 , #4 } \bool_set_true:N \l_@@_NiceTabular_bool \NiceArray { #3 } } { \endNiceArray } % \end{macrocode} % % % \bigskip % \subsection*{After the construction of the array} % % \medskip % \begin{macrocode} \cs_new_protected:Npn \@@_after_array: { \group_begin: % \end{macrocode} % When the option |last-col| is used in the environments with explicit preambles % (like |{NiceArray}|, |{pNiceArray}|, etc.) a special type of column is used at % the end of the preamble in order to compose the cells in an overlapping % position (with |\hbox_overlap_right:n|) but (if |last-col| has been used), we % don't have the number of that last column. However, we have to know that % number for the color of the potential |\Vdots| drawn in that last column. % That's why we fix the correct value of |\l_@@_last_col_int| in that case. % \begin{macrocode} \bool_if:NT \g_@@_last_col_found_bool { \int_set_eq:NN \l_@@_last_col_int \g_@@_col_total_int } % \end{macrocode} % % If we are in an environment without preamble (like |{NiceMatrix}| or % |{pNiceMatrix}|) and if the option |last-col| has been used without value % we also fix the real value of |\l_@@_last_col_int|. % \begin{macrocode} \bool_if:NT \l_@@_last_col_without_value_bool { \int_set_eq:NN \l_@@_last_col_int \g_@@_col_total_int } % \end{macrocode} % % \medskip % It's also time to give to |\l_@@_last_row_int| its real value. % \begin{macrocode} \bool_if:NT \l_@@_last_row_without_value_bool { \int_set_eq:NN \l_@@_last_row_int \g_@@_row_total_int } % \end{macrocode} % % \medskip % \begin{macrocode} \tl_gput_right:Nx \g_@@_aux_tl { \seq_gset_from_clist:Nn \exp_not:N \c_@@_size_seq { \int_use:N \l_@@_first_row_int , \int_use:N \c@iRow , \int_use:N \g_@@_row_total_int , \int_use:N \l_@@_first_col_int , \int_use:N \c@jCol , \int_use:N \g_@@_col_total_int } } % \end{macrocode} % We write also the potential content of |\g_@@_pos_of_blocks_seq| (it will be % useful if the command |\rowcolors| is used with the key |respect-blocks|). % \begin{macrocode} \seq_if_empty:NF \g_@@_pos_of_blocks_seq { \tl_gput_right:Nx \g_@@_aux_tl { \seq_gset_from_clist:Nn \exp_not:N \g_@@_pos_of_blocks_seq { \seq_use:Nnnn \g_@@_pos_of_blocks_seq , , , } } } \seq_if_empty:NF \g_@@_multicolumn_cells_seq { \tl_gput_right:Nx \g_@@_aux_tl { \seq_gset_from_clist:Nn \exp_not:N \g_@@_multicolumn_cells_seq { \seq_use:Nnnn \g_@@_multicolumn_cells_seq , , , } \seq_gset_from_clist:Nn \exp_not:N \g_@@_multicolumn_sizes_seq { \seq_use:Nnnn \g_@@_multicolumn_sizes_seq , , , } } } % \end{macrocode} % % \medskip % Now, you create the diagonal nodes by using the |row| nodes and the |col| % nodes. % \begin{macrocode} \@@_create_diag_nodes: % \end{macrocode} % % By default, the diagonal lines will be parallelized\footnote{It's possible to % use the option |parallelize-diags| to disable this parallelization.}. There % are two types of diagonals lines: the $|\Ddots|$ diagonals and the |\Iddots| % diagonals. We have to count both types in order to know whether a diagonal is % the first of its type in the current |{NiceArray}| environment. % \begin{macrocode} \bool_if:NT \l_@@_parallelize_diags_bool { \int_gzero_new:N \g_@@_ddots_int \int_gzero_new:N \g_@@_iddots_int % \end{macrocode} % % The dimensions |\g_@@_delta_x_one_dim| and |\g_@@_delta_y_one_dim| will % contain the $\Delta_x$ and $\Delta_y$ of the first |\Ddots| diagonal. We have % to store these values in order to draw the others |\Ddots| diagonals parallel % to the first one. Similarly |\g_@@_delta_x_two_dim| and % |\g_@@_delta_y_two_dim| are the $\Delta_x$ and $\Delta_y$ of the first % |\Iddots| diagonal. % \begin{macrocode} \dim_gzero_new:N \g_@@_delta_x_one_dim \dim_gzero_new:N \g_@@_delta_y_one_dim \dim_gzero_new:N \g_@@_delta_x_two_dim \dim_gzero_new:N \g_@@_delta_y_two_dim } % \end{macrocode} % % \begin{macrocode} \int_zero_new:N \l_@@_initial_i_int \int_zero_new:N \l_@@_initial_j_int \int_zero_new:N \l_@@_final_i_int \int_zero_new:N \l_@@_final_j_int \bool_set_false:N \l_@@_initial_open_bool \bool_set_false:N \l_@@_final_open_bool % \end{macrocode} % % If the option |small| is used, the values |\l_@@_radius_dim| and % |\l_@@_inter_dots_dim| (used to draw the dotted lines created by % |\hdottedline| and |\vdotteline| and also for all the other dotted lines when % |line-style| is equal to |standard|, which is the initial value) are changed. % \begin{macrocode} \bool_if:NT \l_@@_small_bool { \dim_set:Nn \l_@@_radius_dim { 0.37 pt } \dim_set:Nn \l_@@_inter_dots_dim { 0.25 em } % \end{macrocode} % The dimension |\l_@@_xdots_shorten_dim| corresponds to the option % |xdots/shorten| available to the user. That's why we give a new value % according to the current value, and not an absolute value. % \begin{macrocode} \dim_set:Nn \l_@@_xdots_shorten_dim { 0.6 \l_@@_xdots_shorten_dim } } % \end{macrocode} % % \bigskip % Now, we actually draw the dotted lines (specified by |\Cdots|, |\Vdots|, % etc.). % \begin{macrocode} \@@_draw_dotted_lines: % \end{macrocode} % % \bigskip % The following computes the ``corners'' (made up of empty cells) but if there % is no corner to compute, it won't do anything. The corners are computed % in |\l_@@_corners_cells_seq| which will contain all the cells which are empty % (and not in a block) considered in the corners of the array. % \begin{macrocode} \@@_compute_corners: % \end{macrocode} % % \bigskip % The sequence |\g_@@_pos_of_blocks_seq| must be ``adjusted'' (for the case % where the user have written something like |\Block{1-*}|). % \begin{macrocode} \@@_adjust_pos_of_blocks_seq: % \end{macrocode} % % \bigskip % The following code is only for efficiency. We determine whether the potential % horizontal and vertical rules are ``complete'', that is to say drawn in the % whole array. We are sure that all the rules will be complete when there is no % block, no virtual block (determined by a command such as |\Cdots|, |\Vdots|, % etc.) and no corners. In that case, we switch to a shortcut version of % |\@@_vline_i:nn| and |\@@_hline:nn|. % \begin{macrocode} % \bool_lazy_all:nT % { % { \seq_if_empty_p:N \g_@@_pos_of_blocks_seq } % { \seq_if_empty_p:N \g_@@_pos_of_xdots_seq } % { \seq_if_empty_p:N \l_@@_corners_cells_seq } % } % { % \cs_set_eq:NN \@@_vline_i:nn \@@_vline_i_complete:nn % \cs_set_eq:NN \@@_hline_i:nn \@@_hline_i_complete:nn % } \tl_if_empty:NF \l_@@_hlines_clist \@@_draw_hlines: \tl_if_empty:NF \l_@@_vlines_clist \@@_draw_vlines: % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \SubMatrix \@@_SubMatrix % \end{macrocode} % % \bigskip % Now, the internal |code-after| and then, the |\CodeAfter|. % \begin{macrocode} \bool_if:NT \c_@@_tikz_loaded_bool { \tikzset { every~picture / .style = { overlay , remember~picture , name~prefix = \@@_env: - } } } \cs_set_eq:NN \line \@@_line \g_@@_internal_code_after_tl \tl_gclear:N \g_@@_internal_code_after_tl % \end{macrocode} % When |light-syntax| is used, we insert systematically a |\CodeAfter| in the % flow. Thus, it's possible to have two instructions |\CodeAfter| and the second % may be in |\g_nicematrix_code_after_tl|. That's why we set % |\Code-after| to be \textsl{no-op} now. % \begin{macrocode} \cs_set_eq:NN \CodeAfter \prg_do_nothing: % \end{macrocode} % % We clear the list of the names of the potential |\SubMatrix| that will appear % in the |\CodeAfter| (unfortunately, that list has to be global). % \begin{macrocode} \seq_gclear:N \g_@@_submatrix_names_seq % \end{macrocode} % \medskip % We compose the |code-after| in math mode in order to nullify the spaces put % by the user between instructions in the |code-after|. % \begin{macrocode} % \bool_if:NT \l_@@_NiceTabular_bool \c_math_toggle_token % \end{macrocode} % And here's the |\CodeAfter|. Since the |\CodeAfter| may begin with an % ``argument'' between square brackets of the options, we extract and treat that % potential ``argument'' with the command |\@@_CodeAfter_keys:|. % \begin{macrocode} \exp_last_unbraced:NV \@@_CodeAfter_keys: \g_nicematrix_code_after_tl \scan_stop: % \bool_if:NT \l_@@_NiceTabular_bool \c_math_toggle_token \tl_gclear:N \g_nicematrix_code_after_tl \group_end: % \end{macrocode} % % % \medskip % |\g_nicematrix_code_before_tl| is for instructions in the cells of the array such as % |\rowcolor| and |\cellcolor| (when the key |colortbl-like| is in % force). These instructions will be written on the |aux| file to be added to % the |code-before| in the next run. % \begin{macrocode} \tl_if_empty:NF \g_nicematrix_code_before_tl { % \end{macrocode} % The command |\rowcolor| in tabular will in fact use |\rectanglecolor| in order % to follow the behaviour of |\rowcolor| of \pkg{colortbl}. That's why there may % be a command |\rectanglecolor| in |\g_nicematrix_code_before_tl|. In order to avoid an % error during the expansion, we define a protected version of |\rectanglecolor|. % \begin{macrocode} \cs_set_protected:Npn \rectanglecolor { } \cs_set_protected:Npn \columncolor { } \tl_gput_right:Nx \g_@@_aux_tl { \tl_gset:Nn \exp_not:N \g_@@_code_before_tl { \exp_not:V \g_nicematrix_code_before_tl } } \bool_set_true:N \l_@@_code_before_bool } % \end{macrocode} % % % \begin{macrocode} % \bool_if:NT \l_@@_code_before_bool \@@_write_aux_for_cell_nodes: % \end{macrocode} % % \medskip % \begin{macrocode} \str_gclear:N \g_@@_name_env_str \@@_restore_iRow_jCol: % \end{macrocode} % The command |\CT@arc@| contains the instruction of color for the rules of the % array\footnote{e.g. |\color[rgb]{0.5,0.5,0}|}. This command is used by % |\CT@arc@| but we use it also for compatibility with \pkg{colortbl}. But we % want also to be able to use color for the rules of the array when % \pkg{colortbl} is \emph{not} loaded. That's why we do the following % instruction which is in the patch of the end of arrays done by \pkg{colortbl}. % \begin{macrocode} \cs_gset_eq:NN \CT@arc@ \@@_old_CT@arc@ } % \end{macrocode} % % \bigskip % The following command will extract the potential options (between square % brackets) at the beginning of the |\CodeAfter| (that is to say, when % |\CodeAfter| is used, the options of that ``command'' |\CodeAfter|). Idem for % the |\CodeBefore.| % \begin{macrocode} \NewDocumentCommand \@@_CodeAfter_keys: { O { } } { \keys_set:nn { NiceMatrix / CodeAfter } { #1 } } % \end{macrocode} % % % % \bigskip % We remind that the first mandatory argument of the command |\Block| is the % size of the block with the special format $i$|-|$j$. However, the user is % allowed to omit $i$ or $j$ (or both). This will be interpreted as: the last % row (resp. column) of the block will be the last row (resp. column) of the % block (without the potential exterior row---resp. column---of the array). By % convention, this is stored in |\g_@@_pos_of_blocks_seq| (and % |\g_@@_blocks_seq|) as a number of rows (resp. columns) for the block equal to % 100. It's possible, after the construction of the array, to replace these % values by the correct ones (since we know the number of rows and columns of % the array). % \begin{macrocode} \cs_new_protected:Npn \@@_adjust_pos_of_blocks_seq: { \seq_gset_map_x:NNn \g_@@_pos_of_blocks_seq \g_@@_pos_of_blocks_seq { \@@_adjust_pos_of_blocks_seq_i:nnnn ##1 } } % \end{macrocode} % % The following command must \emph{not} be protected. % \begin{macrocode} \cs_new:Npn \@@_adjust_pos_of_blocks_seq_i:nnnn #1 #2 #3 #4 { { #1 } { #2 } { \int_compare:nNnTF { #3 } > { 99 } { \int_use:N \c@iRow } { #3 } } { \int_compare:nNnTF { #4 } > { 99 } { \int_use:N \c@jCol } { #4 } } } % \end{macrocode} % % \bigskip % We recall that, when externalization is used, |\tikzpicture| and % |\endtikzpicture| (or |\pgfpicture| and |\endpgfpicture|) must be directly % ``visible''. That's why we have to define the adequate version of % |\@@_draw_dotted_lines:| whether Tikz is loaded or not (in that case, only % \textsc{pgf} is loaded). % \begin{macrocode} \AtBeginDocument { \cs_new_protected:Npx \@@_draw_dotted_lines: { \c_@@_pgfortikzpicture_tl \@@_draw_dotted_lines_i: \c_@@_endpgfortikzpicture_tl } } % \end{macrocode} % % The following command \emph{must} be protected because it will appear in the % construction of the command |\@@_draw_dotted_lines:|. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_dotted_lines_i: { \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \g_@@_HVdotsfor_lines_tl \g_@@_Vdots_lines_tl \g_@@_Ddots_lines_tl \g_@@_Iddots_lines_tl \g_@@_Cdots_lines_tl \g_@@_Ldots_lines_tl } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_restore_iRow_jCol: { \cs_if_exist:NT \theiRow { \int_gset_eq:NN \c@iRow \l_@@_old_iRow_int } \cs_if_exist:NT \thejCol { \int_gset_eq:NN \c@jCol \l_@@_old_jCol_int } } % \end{macrocode} % % \bigskip % We define a new \textsc{pgf} shape for the diag nodes because we want to % provide a anchor called |.5| for those nodes. % \begin{macrocode} \pgfdeclareshape { @@_diag_node } { \savedanchor { \five } { \dim_gset_eq:NN \pgf@x \l_tmpa_dim \dim_gset_eq:NN \pgf@y \l_tmpb_dim } \anchor { 5 } { \five } \anchor { center } { \pgfpointorigin } } % \end{macrocode} % % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_write_aux_for_cell_nodes: { \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { \int_step_inline:nnn \l_@@_first_col_int \g_@@_col_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - ####1 } { \pgfscope \pgftransformshift { \pgfpointanchor { \@@_env: - ##1 - ####1 } { north~west } } \pgfnode { rectangle } { center } { \hbox { \pgfsys@markposition { \@@_env: - ##1 - ####1 - NW } } } { } { } \endpgfscope \pgfscope \pgftransformshift { \pgfpointanchor { \@@_env: - ##1 - ####1 } { south~east } } \pgfnode { rectangle } { center } { \hbox { \pgfsys@markposition { \@@_env: - ##1 - ####1 - SE } } } { } { } \endpgfscope } } } \endpgfpicture \@@_create_extra_nodes: } % \end{macrocode} % % \bigskip % The following command creates the diagonal nodes (in fact, if the matrix is % not a square matrix, not all the nodes are on the diagonal). % \begin{macrocode} \cs_new_protected:Npn \@@_create_diag_nodes: { \pgfpicture \pgfrememberpicturepositiononpagetrue \int_step_inline:nn { \int_max:nn \c@iRow \c@jCol } { \@@_qpoint:n { col - \int_min:nn { ##1 } { \c@jCol + 1 } } \dim_set_eq:NN \l_tmpa_dim \pgf@x \@@_qpoint:n { row - \int_min:nn { ##1 } { \c@iRow + 1 } } \dim_set_eq:NN \l_tmpb_dim \pgf@y \@@_qpoint:n { col - \int_min:nn { ##1 + 1 } { \c@jCol + 1 } } \dim_set_eq:NN \l_tmpc_dim \pgf@x \@@_qpoint:n { row - \int_min:nn { ##1 + 1 } { \c@iRow + 1 } } \dim_set_eq:NN \l_tmpd_dim \pgf@y \pgftransformshift { \pgfpoint \l_tmpa_dim \l_tmpb_dim } % \end{macrocode} % Now, |\l_tmpa_dim| and |\l_tmpb_dim| become the width and the height of the % node (of shape |@à_diag_node|) that we will construct. % \begin{macrocode} \dim_set:Nn \l_tmpa_dim { ( \l_tmpc_dim - \l_tmpa_dim ) / 2 } \dim_set:Nn \l_tmpb_dim { ( \l_tmpd_dim - \l_tmpb_dim ) / 2 } \pgfnode { @@_diag_node } { center } { } { \@@_env: - ##1 } { } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - ##1 } { \@@_env: - ##1 } } } % \end{macrocode} % Now, the last node. Of course, that is only a |coordinate| because there is % not |.5| anchor for that node. % \begin{macrocode} \int_set:Nn \l_tmpa_int { \int_max:nn \c@iRow \c@jCol + 1 } \@@_qpoint:n { row - \int_min:nn { \l_tmpa_int } { \c@iRow + 1 } } \dim_set_eq:NN \l_tmpa_dim \pgf@y \@@_qpoint:n { col - \int_min:nn { \l_tmpa_int } { \c@jCol + 1 } } \pgfcoordinate { \@@_env: - \int_use:N \l_tmpa_int } { \pgfpoint \pgf@x \l_tmpa_dim } \pgfnodealias { \@@_env: - last } { \@@_env: - \int_eval:n { \int_max:nn \c@iRow \c@jCol + 1 } } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - \int_use:N \l_tmpa_int } { \@@_env: - \int_use:N \l_tmpa_int } \pgfnodealias { \l_@@_name_str - last } { \@@_env: - last } } \endpgfpicture } % \end{macrocode} % % % \bigskip % \subsection*{We draw the dotted lines} % % A dotted line will be said \emph{open} in one of its extremities when it stops % on the edge of the matrix and \emph{closed} otherwise. In the following % matrix, the dotted line is closed on its left extremity and open on its right. % \[ \begin{pNiceMatrix} % a+b+c & a+b & a\\ % a & \Cdots \\ % a & a+b & a+b+c % \end{pNiceMatrix}\] % % % \bigskip % The command |\@@_find_extremities_of_line:nnnn| takes four arguments: % % \begin{itemize} % \item the first argument is the row of the cell where the command was issued; % \item the second argument is the column of the cell where the command was % issued; % \item the third argument is the $x$-value of the orientation vector of the % line; % \item the fourth argument is the $y$-value of the orientation vector of the % line. % \end{itemize} % % This command computes: % % \begin{itemize} % \item |\l_@@_initial_i_int| and |\l_@@_initial_j_int| which are the % coordinates of one extremity of the line; % \item |\l_@@_final_i_int| and |\l_@@_final_j_int| which are the coordinates of % the other extremity of the line; % \item |\l_@@_initial_open_bool| and |\l_@@_final_open_bool| to indicate % whether the extremities are open or not. % \end{itemize} % % \begin{macrocode} \cs_new_protected:Npn \@@_find_extremities_of_line:nnnn #1 #2 #3 #4 { % \end{macrocode} % First, we declare the current cell as ``dotted'' because we forbide % intersections of dotted lines. % \begin{macrocode} \cs_set:cpn { @@ _ dotted _ #1 - #2 } { } % \end{macrocode} % Initialization of variables. % \begin{macrocode} \int_set:Nn \l_@@_initial_i_int { #1 } \int_set:Nn \l_@@_initial_j_int { #2 } \int_set:Nn \l_@@_final_i_int { #1 } \int_set:Nn \l_@@_final_j_int { #2 } % \end{macrocode} % We will do two loops: one when determinating the initial cell and the other % when determinating the final cell. The boolean |\l_@@_stop_loop_bool| will be % used to control these loops. In the first loop, we search the ``final'' % extremity of the line. % \begin{macrocode} \bool_set_false:N \l_@@_stop_loop_bool \bool_do_until:Nn \l_@@_stop_loop_bool { \int_add:Nn \l_@@_final_i_int { #3 } \int_add:Nn \l_@@_final_j_int { #4 } % \end{macrocode} % We test if we are still in the matrix. % \begin{macrocode} \bool_set_false:N \l_@@_final_open_bool \int_compare:nNnTF \l_@@_final_i_int > \l_@@_row_max_int { \int_compare:nNnTF { #3 } = 1 { \bool_set_true:N \l_@@_final_open_bool } { \int_compare:nNnT \l_@@_final_j_int > \l_@@_col_max_int { \bool_set_true:N \l_@@_final_open_bool } } } { \int_compare:nNnTF \l_@@_final_j_int < \l_@@_col_min_int { \int_compare:nNnT { #4 } = { -1 } { \bool_set_true:N \l_@@_final_open_bool } } { \int_compare:nNnT \l_@@_final_j_int > \l_@@_col_max_int { \int_compare:nNnT { #4 } = 1 { \bool_set_true:N \l_@@_final_open_bool } } } } \bool_if:NTF \l_@@_final_open_bool % \end{macrocode} % If we are outside the matrix, we have found the extremity of the dotted line % and it's an \emph{open} extremity. % \begin{macrocode} { % \end{macrocode} % We do a step backwards. % \begin{macrocode} \int_sub:Nn \l_@@_final_i_int { #3 } \int_sub:Nn \l_@@_final_j_int { #4 } \bool_set_true:N \l_@@_stop_loop_bool } % \end{macrocode} % If we are in the matrix, we test whether the cell is empty. If it's not the % case, we stop the loop because we have found the correct values for % |\l_@@_final_i_int| and |\l_@@_final_j_int|. % \begin{macrocode} { \cs_if_exist:cTF { @@ _ dotted _ \int_use:N \l_@@_final_i_int - \int_use:N \l_@@_final_j_int } { \int_sub:Nn \l_@@_final_i_int { #3 } \int_sub:Nn \l_@@_final_j_int { #4 } \bool_set_true:N \l_@@_final_open_bool \bool_set_true:N \l_@@_stop_loop_bool } { \cs_if_exist:cTF { pgf @ sh @ ns @ \@@_env: - \int_use:N \l_@@_final_i_int - \int_use:N \l_@@_final_j_int } { \bool_set_true:N \l_@@_stop_loop_bool } % \end{macrocode} % If the case is empty, we declare that the cell as non-empty. Indeed, we will % draw a dotted line and the cell will be on that dotted line. All the cells of % a dotted line have to be marked as ``dotted'' because we don't want % intersections between dotted lines. We recall that the research of the % extremities of the lines are all done in the same TeX group (the group of the % environment), even though, when the extremities are found, each line is % drawn in a TeX group that we will open for the options of the line. % \begin{macrocode} { \cs_set:cpn { @@ _ dotted _ \int_use:N \l_@@_final_i_int - \int_use:N \l_@@_final_j_int } { } } } } } % \end{macrocode} % % \interitem % For |\l_@@_initial_i_int| and |\l_@@_initial_j_int| the programmation is % similar to the previous one. % \begin{macrocode} \bool_set_false:N \l_@@_stop_loop_bool \bool_do_until:Nn \l_@@_stop_loop_bool { \int_sub:Nn \l_@@_initial_i_int { #3 } \int_sub:Nn \l_@@_initial_j_int { #4 } \bool_set_false:N \l_@@_initial_open_bool \int_compare:nNnTF \l_@@_initial_i_int < \l_@@_row_min_int { \int_compare:nNnTF { #3 } = 1 { \bool_set_true:N \l_@@_initial_open_bool } { \int_compare:nNnT \l_@@_initial_j_int = { \l_@@_col_min_int -1 } { \bool_set_true:N \l_@@_initial_open_bool } } } { \int_compare:nNnTF \l_@@_initial_j_int < \l_@@_col_min_int { \int_compare:nNnT { #4 } = 1 { \bool_set_true:N \l_@@_initial_open_bool } } { \int_compare:nNnT \l_@@_initial_j_int > \l_@@_col_max_int { \int_compare:nNnT { #4 } = { -1 } { \bool_set_true:N \l_@@_initial_open_bool } } } } \bool_if:NTF \l_@@_initial_open_bool { \int_add:Nn \l_@@_initial_i_int { #3 } \int_add:Nn \l_@@_initial_j_int { #4 } \bool_set_true:N \l_@@_stop_loop_bool } { \cs_if_exist:cTF { @@ _ dotted _ \int_use:N \l_@@_initial_i_int - \int_use:N \l_@@_initial_j_int } { \int_add:Nn \l_@@_initial_i_int { #3 } \int_add:Nn \l_@@_initial_j_int { #4 } \bool_set_true:N \l_@@_initial_open_bool \bool_set_true:N \l_@@_stop_loop_bool } { \cs_if_exist:cTF { pgf @ sh @ ns @ \@@_env: - \int_use:N \l_@@_initial_i_int - \int_use:N \l_@@_initial_j_int } { \bool_set_true:N \l_@@_stop_loop_bool } { \cs_set:cpn { @@ _ dotted _ \int_use:N \l_@@_initial_i_int - \int_use:N \l_@@_initial_j_int } { } } } } } % \end{macrocode} % We remind the rectangle described by all the dotted lines in order to respect % the corresponding virtual ``block'' when drawing the horizontal and vertical % rules. % \begin{macrocode} \seq_gput_right:Nx \g_@@_pos_of_xdots_seq { { \int_use:N \l_@@_initial_i_int } { \int_use:N \l_@@_initial_j_int } { \int_use:N \l_@@_final_i_int } { \int_use:N \l_@@_final_j_int } } } % \end{macrocode} % % \medskip % The following commmand (\emph{when it will be written}) will set the four % counters |\l_@@_row_min_int|, |\l_@@_row_max_int|, |\l_@@_col_min_int| and % |\l_@@_col_max_int| to the intersections of the sub-matrices which contains % the cell of row |#1| and column |#2|. As of now, it's only the whole array % (excepted exterior rows and columns). % \begin{macrocode} \cs_new_protected:Npn \@@_adjust_to_submatrix:nn #1 #2 { \int_set:Nn \l_@@_row_min_int 1 \int_set:Nn \l_@@_col_min_int 1 \int_set_eq:NN \l_@@_row_max_int \c@iRow \int_set_eq:NN \l_@@_col_max_int \c@jCol % \end{macrocode} % We do a loop over all the submatrices specified in the |code-before|. We have % stored the position of all those submatrices in |\g_@@_submatrix_seq|. % \begin{macrocode} \seq_map_inline:Nn \g_@@_submatrix_seq { \@@_adjust_to_submatrix:nnnnnn { #1 } { #2 } ##1 } } % \end{macrocode} % % \medskip % |#1| and |#2| are the numbers of row and columns of the cell where the command % of dotted line (ex.: |\Vdots|) has been issued. |#3|, |#4|, |#5| and |#6| are % the specification (in $i$ and $j$) of the submatrix where are analysing. % \begin{macrocode} \cs_set_protected:Npn \@@_adjust_to_submatrix:nnnnnn #1 #2 #3 #4 #5 #6 { \bool_if:nT { \int_compare_p:n { #3 <= #1 } && \int_compare_p:n { #1 <= #5 } && \int_compare_p:n { #4 <= #2 } && \int_compare_p:n { #2 <= #6 } } { \int_set:Nn \l_@@_row_min_int { \int_max:nn \l_@@_row_min_int { #3 } } \int_set:Nn \l_@@_col_min_int { \int_max:nn \l_@@_col_min_int { #4 } } \int_set:Nn \l_@@_row_max_int { \int_min:nn \l_@@_row_max_int { #5 } } \int_set:Nn \l_@@_col_max_int { \int_min:nn \l_@@_col_max_int { #6 } } } } % \end{macrocode} % % \medskip % \begin{macrocode} \cs_new_protected:Npn \@@_set_initial_coords: { \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y } \cs_new_protected:Npn \@@_set_final_coords: { \dim_set_eq:NN \l_@@_x_final_dim \pgf@x \dim_set_eq:NN \l_@@_y_final_dim \pgf@y } \cs_new_protected:Npn \@@_set_initial_coords_from_anchor:n #1 { \pgfpointanchor { \@@_env: - \int_use:N \l_@@_initial_i_int - \int_use:N \l_@@_initial_j_int } { #1 } \@@_set_initial_coords: } \cs_new_protected:Npn \@@_set_final_coords_from_anchor:n #1 { \pgfpointanchor { \@@_env: - \int_use:N \l_@@_final_i_int - \int_use:N \l_@@_final_j_int } { #1 } \@@_set_final_coords: } % \end{macrocode} % % % \begin{macrocode} \cs_new_protected:Npn \@@_open_x_initial_dim: { \dim_set_eq:NN \l_@@_x_initial_dim \c_max_dim \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - \int_use:N \l_@@_initial_j_int } { \pgfpointanchor { \@@_env: - ##1 - \int_use:N \l_@@_initial_j_int } { west } \dim_set:Nn \l_@@_x_initial_dim { \dim_min:nn \l_@@_x_initial_dim \pgf@x } } } % \end{macrocode} % If, in fact, all the cells of the columns are empty (no PGF/Tikz nodes in % those cells). % \begin{macrocode} \dim_compare:nNnT \l_@@_x_initial_dim = \c_max_dim { \@@_qpoint:n { col - \int_use:N \l_@@_initial_j_int } \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x \dim_add:Nn \l_@@_x_initial_dim \col@sep } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_open_x_final_dim: { \dim_set:Nn \l_@@_x_final_dim { - \c_max_dim } \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - \int_use:N \l_@@_final_j_int } { \pgfpointanchor { \@@_env: - ##1 - \int_use:N \l_@@_final_j_int } { east } \dim_set:Nn \l_@@_x_final_dim { \dim_max:nn \l_@@_x_final_dim \pgf@x } } } % \end{macrocode} % If, in fact, all the cells of the columns are empty (no PGF/Tikz nodes in % those cells). % \begin{macrocode} \dim_compare:nNnT \l_@@_x_final_dim = { - \c_max_dim } { \@@_qpoint:n { col - \@@_succ:n \l_@@_final_j_int } \dim_set_eq:NN \l_@@_x_final_dim \pgf@x \dim_sub:Nn \l_@@_x_final_dim \col@sep } } % \end{macrocode} % % % % \interitem % The first and the second arguments are the coordinates of the cell where the % command has been issued. The third argument is the list of the options. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_Ldots:nnn #1 #2 #3 { \@@_adjust_to_submatrix:nn { #1 } { #2 } \cs_if_free:cT { @@ _ dotted _ #1 - #2 } { \@@_find_extremities_of_line:nnnn { #1 } { #2 } 0 1 % \end{macrocode} % The previous command may have changed the current environment by marking some % cells as ``dotted'', but, fortunately, it is outside the group for the options % of the line. % \begin{macrocode} \group_begin: \int_compare:nNnTF { #1 } = 0 { \color { nicematrix-first-row } } { % \end{macrocode} % We remind that, when there is a ``last row'' |\l_@@_last_row_int| will always % be (after the construction of the array) the number of that ``last row'' even % if the option |last-row| has been used without value. % \begin{macrocode} \int_compare:nNnT { #1 } = \l_@@_last_row_int { \color { nicematrix-last-row } } } \keys_set:nn { NiceMatrix / xdots } { #3 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Ldots: \group_end: } } % \end{macrocode} % % % \medskip % The command |\@@_actually_draw_Ldots:| has the following implicit arguments: % \begin{itemize} % \item |\l_@@_initial_i_int| % \item |\l_@@_initial_j_int| % \item |\l_@@_initial_open_bool| % \item |\l_@@_final_i_int| % \item |\l_@@_final_j_int| % \item |\l_@@_final_open_bool|. % \end{itemize} % % The following function is also used by |\Hdotsfor|. % \begin{macrocode} \cs_new_protected:Npn \@@_actually_draw_Ldots: { \bool_if:NTF \l_@@_initial_open_bool { \@@_open_x_initial_dim: \@@_qpoint:n { row - \int_use:N \l_@@_initial_i_int - base } \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y } { \@@_set_initial_coords_from_anchor:n { base~east } } \bool_if:NTF \l_@@_final_open_bool { \@@_open_x_final_dim: \@@_qpoint:n { row - \int_use:N \l_@@_final_i_int - base } \dim_set_eq:NN \l_@@_y_final_dim \pgf@y } { \@@_set_final_coords_from_anchor:n { base~west } } % \end{macrocode} % We raise the line of a quantity equal to the radius of the dots because we % want the dots really ``on'' the line of texte. Of course, maybe we should not % do that when the option |line-style| is used (?). % \begin{macrocode} \dim_add:Nn \l_@@_y_initial_dim \l_@@_radius_dim \dim_add:Nn \l_@@_y_final_dim \l_@@_radius_dim \@@_draw_line: } % \end{macrocode} % % \interitem % The first and the second arguments are the coordinates of the cell where the % command has been issued. The third argument is the list of the options. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_Cdots:nnn #1 #2 #3 { \@@_adjust_to_submatrix:nn { #1 } { #2 } \cs_if_free:cT { @@ _ dotted _ #1 - #2 } { \@@_find_extremities_of_line:nnnn { #1 } { #2 } 0 1 % \end{macrocode} % The previous command may have changed the current environment by marking some % cells as ``dotted'', but, fortunately, it is outside the group for the options % of the line. % \begin{macrocode} \group_begin: \int_compare:nNnTF { #1 } = 0 { \color { nicematrix-first-row } } { % \end{macrocode} % We remind that, when there is a ``last row'' |\l_@@_last_row_int| will always % be (after the construction of the array) the number of that ``last row'' even % if the option |last-row| has been used without value. % \begin{macrocode} \int_compare:nNnT { #1 } = \l_@@_last_row_int { \color { nicematrix-last-row } } } \keys_set:nn { NiceMatrix / xdots } { #3 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Cdots: \group_end: } } % \end{macrocode} % % % \medskip % The command |\@@_actually_draw_Cdots:| has the following implicit arguments: % \begin{itemize} % \item |\l_@@_initial_i_int| % \item |\l_@@_initial_j_int| % \item |\l_@@_initial_open_bool| % \item |\l_@@_final_i_int| % \item |\l_@@_final_j_int| % \item |\l_@@_final_open_bool|. % \end{itemize} % % \begin{macrocode} \cs_new_protected:Npn \@@_actually_draw_Cdots: { \bool_if:NTF \l_@@_initial_open_bool { \@@_open_x_initial_dim: } { \@@_set_initial_coords_from_anchor:n { mid~east } } \bool_if:NTF \l_@@_final_open_bool { \@@_open_x_final_dim: } { \@@_set_final_coords_from_anchor:n { mid~west } } \bool_lazy_and:nnTF \l_@@_initial_open_bool \l_@@_final_open_bool { \@@_qpoint:n { row - \int_use:N \l_@@_initial_i_int } \dim_set_eq:NN \l_tmpa_dim \pgf@y \@@_qpoint:n { row - \@@_succ:n \l_@@_initial_i_int } \dim_set:Nn \l_@@_y_initial_dim { ( \l_tmpa_dim + \pgf@y ) / 2 } \dim_set_eq:NN \l_@@_y_final_dim \l_@@_y_initial_dim } { \bool_if:NT \l_@@_initial_open_bool { \dim_set_eq:NN \l_@@_y_initial_dim \l_@@_y_final_dim } \bool_if:NT \l_@@_final_open_bool { \dim_set_eq:NN \l_@@_y_final_dim \l_@@_y_initial_dim } } \@@_draw_line: } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_open_y_initial_dim: { \@@_qpoint:n { row - \int_use:N \l_@@_initial_i_int - base } \dim_set:Nn \l_@@_y_initial_dim { \pgf@y + ( \box_ht:N \strutbox + \extrarowheight ) * \arraystretch } \int_step_inline:nnn \l_@@_first_col_int \g_@@_col_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - \int_use:N \l_@@_initial_i_int - ##1 } { \pgfpointanchor { \@@_env: - \int_use:N \l_@@_initial_i_int - ##1 } { north } \dim_set:Nn \l_@@_y_initial_dim { \dim_max:nn \l_@@_y_initial_dim \pgf@y } } } } % \end{macrocode} % % % \begin{macrocode} \cs_new_protected:Npn \@@_open_y_final_dim: { \@@_qpoint:n { row - \int_use:N \l_@@_final_i_int - base } \dim_set:Nn \l_@@_y_final_dim { \pgf@y - ( \box_dp:N \strutbox ) * \arraystretch } \int_step_inline:nnn \l_@@_first_col_int \g_@@_col_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - \int_use:N \l_@@_final_i_int - ##1 } { \pgfpointanchor { \@@_env: - \int_use:N \l_@@_final_i_int - ##1 } { south } \dim_set:Nn \l_@@_y_final_dim { \dim_min:nn \l_@@_y_final_dim \pgf@y } } } } % \end{macrocode} % % The first and the second arguments are the coordinates of the cell where the % command has been issued. The third argument is the list of the options. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_Vdots:nnn #1 #2 #3 { \@@_adjust_to_submatrix:nn { #1 } { #2 } \cs_if_free:cT { @@ _ dotted _ #1 - #2 } { \@@_find_extremities_of_line:nnnn { #1 } { #2 } 1 0 % \end{macrocode} % The previous command may have changed the current environment by marking some % cells as ``dotted'', but, fortunately, it is outside the group for the options % of the line. % \begin{macrocode} \group_begin: \int_compare:nNnTF { #2 } = 0 { \color { nicematrix-first-col } } { \int_compare:nNnT { #2 } = \l_@@_last_col_int { \color { nicematrix-last-col } } } \keys_set:nn { NiceMatrix / xdots } { #3 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Vdots: \group_end: } } % \end{macrocode} % % \bigskip % The command |\@@_actually_draw_Vdots:| has the following implicit arguments: % \begin{itemize} % \item |\l_@@_initial_i_int| % \item |\l_@@_initial_j_int| % \item |\l_@@_initial_open_bool| % \item |\l_@@_final_i_int| % \item |\l_@@_final_j_int| % \item |\l_@@_final_open_bool|. % \end{itemize} % % The following function is also used by |\Vdotsfor|. % \begin{macrocode} \cs_new_protected:Npn \@@_actually_draw_Vdots: { % \end{macrocode} % The boolean |\l_tmpa_bool| indicates whether the column is of type |l| or may % be considered as if. % \begin{macrocode} \bool_set_false:N \l_tmpa_bool % \end{macrocode} % First the case when the line is closed on both ends. % \begin{macrocode} \bool_lazy_or:nnF \l_@@_initial_open_bool \l_@@_final_open_bool { \@@_set_initial_coords_from_anchor:n { south~west } \@@_set_final_coords_from_anchor:n { north~west } \bool_set:Nn \l_tmpa_bool { \dim_compare_p:nNn \l_@@_x_initial_dim = \l_@@_x_final_dim } } % \end{macrocode} % Now, we try to determine whether the column is of type |c| or may be % considered as if. % \begin{macrocode} \bool_if:NTF \l_@@_initial_open_bool \@@_open_y_initial_dim: { \@@_set_initial_coords_from_anchor:n { south } } \bool_if:NTF \l_@@_final_open_bool \@@_open_y_final_dim: { \@@_set_final_coords_from_anchor:n { north } } \bool_if:NTF \l_@@_initial_open_bool { \bool_if:NTF \l_@@_final_open_bool { \@@_qpoint:n { col - \int_use:N \l_@@_initial_j_int } \dim_set_eq:NN \l_tmpa_dim \pgf@x \@@_qpoint:n { col - \@@_succ:n \l_@@_initial_j_int } \dim_set:Nn \l_@@_x_initial_dim { ( \pgf@x + \l_tmpa_dim ) / 2 } \dim_set_eq:NN \l_@@_x_final_dim \l_@@_x_initial_dim % \end{macrocode} % We may think that the final user won't use a ``last column'' which contains % only a command |\Vdots|. However, if the |\Vdots| is in fact used to draw, not % a dotted line, but an arrow (to indicate the number of rows of the matrix), it % may be really encountered. % \begin{macrocode} \int_compare:nNnT \l_@@_last_col_int > { -2 } { \int_compare:nNnT \l_@@_initial_j_int = \g_@@_col_total_int { \dim_set_eq:NN \l_tmpa_dim \l_@@_right_margin_dim \dim_add:Nn \l_tmpa_dim \l_@@_extra_right_margin_dim \dim_add:Nn \l_@@_x_initial_dim \l_tmpa_dim \dim_add:Nn \l_@@_x_final_dim \l_tmpa_dim } } } { \dim_set_eq:NN \l_@@_x_initial_dim \l_@@_x_final_dim } } { \bool_if:NTF \l_@@_final_open_bool { \dim_set_eq:NN \l_@@_x_final_dim \l_@@_x_initial_dim } { % \end{macrocode} % Now the case where both extremities are closed. The first conditional tests % whether the column is of type |c| or may be considered as if. % \begin{macrocode} \dim_compare:nNnF \l_@@_x_initial_dim = \l_@@_x_final_dim { \dim_set:Nn \l_@@_x_initial_dim { \bool_if:NTF \l_tmpa_bool \dim_min:nn \dim_max:nn \l_@@_x_initial_dim \l_@@_x_final_dim } \dim_set_eq:NN \l_@@_x_final_dim \l_@@_x_initial_dim } } } \@@_draw_line: } % \end{macrocode} % % \interitem % For the diagonal lines, the situation is a bit more complicated because, by % default, we parallelize the diagonals lines. The first diagonal line is drawn % and then, all the other diagonal lines are drawn parallel to the first one. % % The first and the second arguments are the coordinates of the cell where the % command has been issued. The third argument is the list of the options. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_Ddots:nnn #1 #2 #3 { \@@_adjust_to_submatrix:nn { #1 } { #2 } \cs_if_free:cT { @@ _ dotted _ #1 - #2 } { \@@_find_extremities_of_line:nnnn { #1 } { #2 } 1 1 % \end{macrocode} % The previous command may have changed the current environment by marking some % cells as ``dotted'', but, fortunately, it is outside the group for the options % of the line. % \begin{macrocode} \group_begin: \keys_set:nn { NiceMatrix / xdots } { #3 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Ddots: \group_end: } } % \end{macrocode} % % \bigskip % The command |\@@_actually_draw_Ddots:| has the following implicit arguments: % \begin{itemize} % \item |\l_@@_initial_i_int| % \item |\l_@@_initial_j_int| % \item |\l_@@_initial_open_bool| % \item |\l_@@_final_i_int| % \item |\l_@@_final_j_int| % \item |\l_@@_final_open_bool|. % \end{itemize} % % \begin{macrocode} \cs_new_protected:Npn \@@_actually_draw_Ddots: { \bool_if:NTF \l_@@_initial_open_bool { \@@_open_y_initial_dim: % \@@_qpoint:n { col - \int_use:N \l_@@_initial_j_int } % \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x \@@_open_x_initial_dim: } { \@@_set_initial_coords_from_anchor:n { south~east } } \bool_if:NTF \l_@@_final_open_bool { % \@@_open_y_final_dim: % \@@_qpoint:n { col - \@@_succ:n \l_@@_final_j_int } \@@_open_x_final_dim: \dim_set_eq:NN \l_@@_x_final_dim \pgf@x } { \@@_set_final_coords_from_anchor:n { north~west } } % \end{macrocode} % We have retrieved the coordinates in the usual way (they are stored in % |\l_@@_x_initial_dim|, etc.). If the parallelization of the diagonals is set, % we will have (maybe) to adjust the fourth coordinate. % \begin{macrocode} \bool_if:NT \l_@@_parallelize_diags_bool { \int_gincr:N \g_@@_ddots_int % \end{macrocode} % We test if the diagonal line is the first one (the counter |\g_@@_ddots_int| % is created for this usage). % \begin{macrocode} \int_compare:nNnTF \g_@@_ddots_int = 1 % \end{macrocode} % If the diagonal line is the first one, we have no adjustment of the line to do % but we store the $\Delta_x$ and the $\Delta_y$ of the line because these % values will be used to draw the others diagonal lines parallels to the first % one. % \begin{macrocode} { \dim_gset:Nn \g_@@_delta_x_one_dim { \l_@@_x_final_dim - \l_@@_x_initial_dim } \dim_gset:Nn \g_@@_delta_y_one_dim { \l_@@_y_final_dim - \l_@@_y_initial_dim } } % \end{macrocode} % If the diagonal line is not the first one, we have to adjust the second % extremity of the line by modifying the coordinate |\l_@@_x_initial_dim|. % \begin{macrocode} { \dim_set:Nn \l_@@_y_final_dim { \l_@@_y_initial_dim + ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) * \dim_ratio:nn \g_@@_delta_y_one_dim \g_@@_delta_x_one_dim } } } \@@_draw_line: } % \end{macrocode} % % \bigskip % We draw the |\Iddots| diagonals in the same way. % % The first and the second arguments are the coordinates of the cell where the % command has been issued. The third argument is the list of the options. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_Iddots:nnn #1 #2 #3 { \@@_adjust_to_submatrix:nn { #1 } { #2 } \cs_if_free:cT { @@ _ dotted _ #1 - #2 } { \@@_find_extremities_of_line:nnnn { #1 } { #2 } 1 { -1 } % \end{macrocode} % The previous command may have changed the current environment by marking some % cells as ``dotted'', but, fortunately, it is outside the group for the options % of the line. % \begin{macrocode} \group_begin: \keys_set:nn { NiceMatrix / xdots } { #3 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Iddots: \group_end: } } % \end{macrocode} % % \bigskip % The command |\@@_actually_draw_Iddots:| has the following implicit arguments: % \begin{itemize} % \item |\l_@@_initial_i_int| % \item |\l_@@_initial_j_int| % \item |\l_@@_initial_open_bool| % \item |\l_@@_final_i_int| % \item |\l_@@_final_j_int| % \item |\l_@@_final_open_bool|. % \end{itemize} % % \begin{macrocode} \cs_new_protected:Npn \@@_actually_draw_Iddots: { \bool_if:NTF \l_@@_initial_open_bool { \@@_open_y_initial_dim: \@@_open_x_initial_dim: } { \@@_set_initial_coords_from_anchor:n { south~west } } \bool_if:NTF \l_@@_final_open_bool { \@@_open_y_final_dim: \@@_open_x_final_dim: } { \@@_set_final_coords_from_anchor:n { north~east } } \bool_if:NT \l_@@_parallelize_diags_bool { \int_gincr:N \g_@@_iddots_int \int_compare:nNnTF \g_@@_iddots_int = 1 { \dim_gset:Nn \g_@@_delta_x_two_dim { \l_@@_x_final_dim - \l_@@_x_initial_dim } \dim_gset:Nn \g_@@_delta_y_two_dim { \l_@@_y_final_dim - \l_@@_y_initial_dim } } { \dim_set:Nn \l_@@_y_final_dim { \l_@@_y_initial_dim + ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) * \dim_ratio:nn \g_@@_delta_y_two_dim \g_@@_delta_x_two_dim } } } \@@_draw_line: } % \end{macrocode} % % % \bigskip % \subsection*{The actual instructions for drawing the dotted lines with Tikz} % % The command |\@@_draw_line:| should be used in a |{pgfpicture}|. It has six % implicit arguments: % % \begin{itemize} % \item |\l_@@_x_initial_dim| % \item |\l_@@_y_initial_dim| % \item |\l_@@_x_final_dim| % \item |\l_@@_y_final_dim| % \item |\l_@@_initial_open_bool| % \item |\l_@@_final_open_bool| % \end{itemize} % % % % \begin{macrocode} \cs_new_protected:Npn \@@_draw_line: { \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \tl_if_eq:NNTF \l_@@_xdots_line_style_tl \c_@@_standard_tl \@@_draw_standard_dotted_line: \@@_draw_non_standard_dotted_line: } % \end{macrocode} % % \medskip % We have to do a special construction with |\exp_args:NV| to be able to put in % the list of options in the correct place in the Tikz instruction. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_non_standard_dotted_line: { \begin { scope } \exp_args:No \@@_draw_non_standard_dotted_line:n { \l_@@_xdots_line_style_tl , \l_@@_xdots_color_tl } } % \end{macrocode} % We have used the fact that, in \textsc{pgf}, un color name can be put directly % in a list of options (that's why we have put diredtly |\l_@@_xdots_color_tl|). % % \smallskip % The argument of |\@@_draw_non_standard_dotted_line:n| is, in fact, the list of options. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_non_standard_dotted_line:n #1 { \@@_draw_non_standard_dotted_line:nVV { #1 } \l_@@_xdots_up_tl \l_@@_xdots_down_tl } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_draw_non_standard_dotted_line:nnn #1 #2 #3 { \draw [ #1 , shorten~> = \l_@@_xdots_shorten_dim , shorten~< = \l_@@_xdots_shorten_dim , ] ( \l_@@_x_initial_dim , \l_@@_y_initial_dim ) % \end{macrocode} % Be careful: We can't put |\c_math_toggle_token| instead of |$| in the % following lines because we are in the contents of Tikz nodes (and they will be % \emph{rescanned} if the Tikz library \pkg{babel} is loaded). % \begin{macrocode} -- node [ sloped , above ] { $ \scriptstyle #2 $ } node [ sloped , below ] { $ \scriptstyle #3 $ } ( \l_@@_x_final_dim , \l_@@_y_final_dim ) ; \end { scope } } \cs_generate_variant:Nn \@@_draw_non_standard_dotted_line:nnn { n V V } % \end{macrocode} % % \bigskip % The command |\@@_draw_standard_dotted_line:| draws the line with our system of dots % (which gives a dotted line with real round dots). % \begin{macrocode} \cs_new_protected:Npn \@@_draw_standard_dotted_line: { \bool_lazy_and:nnF { \tl_if_empty_p:N \l_@@_xdots_up_tl } { \tl_if_empty_p:N \l_@@_xdots_down_tl } { \pgfscope \pgftransformshift { \pgfpointlineattime { 0.5 } { \pgfpoint \l_@@_x_initial_dim \l_@@_y_initial_dim } { \pgfpoint \l_@@_x_final_dim \l_@@_y_final_dim } } \pgftransformrotate { \fp_eval:n { atand ( \l_@@_y_final_dim - \l_@@_y_initial_dim , \l_@@_x_final_dim - \l_@@_x_initial_dim ) } } \pgfnode { rectangle } { south } { \c_math_toggle_token \scriptstyle \l_@@_xdots_up_tl \c_math_toggle_token } { } { \pgfusepath { } } \pgfnode { rectangle } { north } { \c_math_toggle_token \scriptstyle \l_@@_xdots_down_tl \c_math_toggle_token } { } { \pgfusepath { } } \endpgfscope } \group_begin: % \end{macrocode} % The dimension |\l_@@_l_dim| is the length $\ell$ of the line to draw. We use % the floating point reals of the L3 programming layer to compute this length. % \begin{macrocode} \dim_zero_new:N \l_@@_l_dim \dim_set:Nn \l_@@_l_dim { \fp_to_dim:n { sqrt ( ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) ^ 2 + ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) ^ 2 ) } } % \end{macrocode} % It seems that, during the first compilations, the value of |\l_@@_l_dim| may % be erroneous (equal to zero or very large). We must detect these cases % because they would cause errors during the drawing of the dotted line. Maybe % we should also write something in the |aux| file to say that one more % compilation should be done. % \begin{macrocode} \bool_lazy_or:nnF { \dim_compare_p:nNn { \dim_abs:n \l_@@_l_dim } > \c_@@_max_l_dim } { \dim_compare_p:nNn \l_@@_l_dim = \c_zero_dim } \@@_draw_standard_dotted_line_i: \group_end: } % \end{macrocode} % % \begin{macrocode} \dim_const:Nn \c_@@_max_l_dim { 50 cm } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_draw_standard_dotted_line_i: { % \end{macrocode} % The number of dots will be |\l_tmpa_int + 1|. % \begin{macrocode} \bool_if:NTF \l_@@_initial_open_bool { \bool_if:NTF \l_@@_final_open_bool { \int_set:Nn \l_tmpa_int { \dim_ratio:nn \l_@@_l_dim \l_@@_inter_dots_dim } } { \int_set:Nn \l_tmpa_int { \dim_ratio:nn { \l_@@_l_dim - \l_@@_xdots_shorten_dim } \l_@@_inter_dots_dim } } } { \bool_if:NTF \l_@@_final_open_bool { \int_set:Nn \l_tmpa_int { \dim_ratio:nn { \l_@@_l_dim - \l_@@_xdots_shorten_dim } \l_@@_inter_dots_dim } } { \int_set:Nn \l_tmpa_int { \dim_ratio:nn { \l_@@_l_dim - 2 \l_@@_xdots_shorten_dim } \l_@@_inter_dots_dim } } } % \end{macrocode} % % \medskip % The dimensions |\l_tmpa_dim| and |\l_tmpb_dim| are the coordinates of the % vector between two dots in the dotted line. % \begin{macrocode} \dim_set:Nn \l_tmpa_dim { ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) * \dim_ratio:nn \l_@@_inter_dots_dim \l_@@_l_dim } \dim_set:Nn \l_tmpb_dim { ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) * \dim_ratio:nn \l_@@_inter_dots_dim \l_@@_l_dim } % \end{macrocode} % % The length $\ell$ is the length of the dotted line. We note $\Delta$ the % length between two dots and $n$ the number of intervals between dots. We note % $\delta = \frac12(\ell - n \Delta)$. The distance between the initial % extremity of the line and the first dot will be equal to $k\cdot\delta$ where % $k=0$, $1$ or $2$. We first compute this number $k$ in |\l_tmpb_int|. % \begin{macrocode} \int_set:Nn \l_tmpb_int { \bool_if:NTF \l_@@_initial_open_bool { \bool_if:NTF \l_@@_final_open_bool 1 0 } { \bool_if:NTF \l_@@_final_open_bool 2 1 } } % \end{macrocode} % In the loop over the dots, the dimensions |\l_@@_x_initial_dim| and % |\l_@@_y_initial_dim| will be used for the coordinates of the dots. But, % before the loop, we must move until the first dot. % % \begin{macrocode} \dim_gadd:Nn \l_@@_x_initial_dim { ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) * \dim_ratio:nn { \l_@@_l_dim - \l_@@_inter_dots_dim * \l_tmpa_int } { 2 \l_@@_l_dim } * \l_tmpb_int } \dim_gadd:Nn \l_@@_y_initial_dim { ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) * \dim_ratio:nn { \l_@@_l_dim - \l_@@_inter_dots_dim * \l_tmpa_int } { 2 \l_@@_l_dim } * \l_tmpb_int } \pgf@relevantforpicturesizefalse \int_step_inline:nnn 0 \l_tmpa_int { \pgfpathcircle { \pgfpoint \l_@@_x_initial_dim \l_@@_y_initial_dim } { \l_@@_radius_dim } \dim_add:Nn \l_@@_x_initial_dim \l_tmpa_dim \dim_add:Nn \l_@@_y_initial_dim \l_tmpb_dim } \pgfusepathqfill } % \end{macrocode} % % \bigskip % \subsection*{User commands available in the new environments} % % % \interitem % The commands |\@@_Ldots|, |\@@_Cdots|, |\@@_Vdots|, |\@@_Ddots| and % |\@@_Iddots| will be linked to |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots| and % |\Iddots| in the environments |{NiceArray}| (the other environments of % \pkg{nicematrix} rely upon |{NiceArray}|). % % % \medskip % The syntax of these commands uses the character |_| as embellishment and % thats' why we have to insert a character |_| in the \emph{arg spec} of these % commands. However, we don't know the future catcode of |_| in the main % document (maybe the user will use \pkg{underscore}, and, in that case, the % catcode is $13$ because \pkg{underscore} activates |_|). That's why these % commands will be defined in a |\AtBeginDocument| and the \emph{arg spec} will % be rescanned. % % \begin{macrocode} \AtBeginDocument { \tl_set:Nn \l_@@_argspec_tl { O { } E { _ ^ } { { } { } } } \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl \exp_args:NNV \NewDocumentCommand \@@_Ldots \l_@@_argspec_tl { \int_compare:nNnTF \c@jCol = 0 { \@@_error:nn { in~first~col } \Ldots } { \int_compare:nNnTF \c@jCol = \l_@@_last_col_int { \@@_error:nn { in~last~col } \Ldots } { \@@_instruction_of_type:nnn \c_false_bool { Ldots } { #1 , down = #2 , up = #3 } } } \bool_if:NF \l_@@_nullify_dots_bool { \phantom { \ensuremath { \@@_old_ldots } } } \bool_gset_true:N \g_@@_empty_cell_bool } % \end{macrocode} % % \bigskip % \begin{macrocode} \exp_args:NNV \NewDocumentCommand \@@_Cdots \l_@@_argspec_tl { \int_compare:nNnTF \c@jCol = 0 { \@@_error:nn { in~first~col } \Cdots } { \int_compare:nNnTF \c@jCol = \l_@@_last_col_int { \@@_error:nn { in~last~col } \Cdots } { \@@_instruction_of_type:nnn \c_false_bool { Cdots } { #1 , down = #2 , up = #3 } } } \bool_if:NF \l_@@_nullify_dots_bool { \phantom { \ensuremath { \@@_old_cdots } } } \bool_gset_true:N \g_@@_empty_cell_bool } % \end{macrocode} % % \bigskip % \begin{macrocode} \exp_args:NNV \NewDocumentCommand \@@_Vdots \l_@@_argspec_tl { \int_compare:nNnTF \c@iRow = 0 { \@@_error:nn { in~first~row } \Vdots } { \int_compare:nNnTF \c@iRow = \l_@@_last_row_int { \@@_error:nn { in~last~row } \Vdots } { \@@_instruction_of_type:nnn \c_false_bool { Vdots } { #1 , down = #2 , up = #3 } } } \bool_if:NF \l_@@_nullify_dots_bool { \phantom { \ensuremath { \@@_old_vdots } } } \bool_gset_true:N \g_@@_empty_cell_bool } % \end{macrocode} % % % \bigskip % \begin{macrocode} \exp_args:NNV \NewDocumentCommand \@@_Ddots \l_@@_argspec_tl { \int_case:nnF \c@iRow { 0 { \@@_error:nn { in~first~row } \Ddots } \l_@@_last_row_int { \@@_error:nn { in~last~row } \Ddots } } { \int_case:nnF \c@jCol { 0 { \@@_error:nn { in~first~col } \Ddots } \l_@@_last_col_int { \@@_error:nn { in~last~col } \Ddots } } { \keys_set_known:nn { NiceMatrix / Ddots } { #1 } \@@_instruction_of_type:nnn \l_@@_draw_first_bool { Ddots } { #1 , down = #2 , up = #3 } } } \bool_if:NF \l_@@_nullify_dots_bool { \phantom { \ensuremath { \@@_old_ddots } } } \bool_gset_true:N \g_@@_empty_cell_bool } % \end{macrocode} % % \bigskip % \begin{macrocode} \exp_args:NNV \NewDocumentCommand \@@_Iddots \l_@@_argspec_tl { \int_case:nnF \c@iRow { 0 { \@@_error:nn { in~first~row } \Iddots } \l_@@_last_row_int { \@@_error:nn { in~last~row } \Iddots } } { \int_case:nnF \c@jCol { 0 { \@@_error:nn { in~first~col } \Iddots } \l_@@_last_col_int { \@@_error:nn { in~last~col } \Iddots } } { \keys_set_known:nn { NiceMatrix / Ddots } { #1 } \@@_instruction_of_type:nnn \l_@@_draw_first_bool { Iddots } { #1 , down = #2 , up = #3 } } } \bool_if:NF \l_@@_nullify_dots_bool { \phantom { \ensuremath { \@@_old_iddots } } } \bool_gset_true:N \g_@@_empty_cell_bool } } % \end{macrocode} % End of the |\AtBeginDocument|. % % % \bigskip % Despite its name, the following set of keys will be used for |\Ddots| but also % for |\Iddots|. % \begin{macrocode} \keys_define:nn { NiceMatrix / Ddots } { draw-first .bool_set:N = \l_@@_draw_first_bool , draw-first .default:n = true , draw-first .value_forbidden:n = true } % \end{macrocode} % % \bigskip % The command |\@@_Hspace:| will be linked to |\hspace| in |{NiceArray}|. % \begin{macrocode} \cs_new_protected:Npn \@@_Hspace: { \bool_gset_true:N \g_@@_empty_cell_bool \hspace } % \end{macrocode} % % \bigskip % In the environments of |nicematrix|, the command |\multicolumn| is redefined. % We will patch the environment |{tabular}| to go back to the previous value of % |\multicolumn|. % \begin{macrocode} \cs_set_eq:NN \@@_old_multicolumn \multicolumn % \end{macrocode} % % % % \bigskip % The command |\@@_Hdotsfor| will be linked to |\Hdotsfor| in % |{NiceArrayWithDelims}|. Tikz nodes are created also in the implicit cells of % the |\Hdotsfor| (maybe we should modify that point). % % \medskip % This command must \emph{not} be protected since it begins with |\multicolumn|. % \begin{macrocode} \cs_new:Npn \@@_Hdotsfor: { \bool_lazy_and:nnTF { \int_compare_p:nNn \c@jCol = 0 } { \int_compare_p:nNn \l_@@_first_col_int = 0 } { \bool_if:NTF \g_@@_after_col_zero_bool { \multicolumn { 1 } { c } { } \@@_Hdotsfor_i } { \@@_fatal:n { Hdotsfor~in~col~0 } } } { \multicolumn { 1 } { c } { } \@@_Hdotsfor_i } } % \end{macrocode} % % % The command |\@@_Hdotsfor_i| is defined with |\NewDocumentCommand| because it % has an optional argument. Note that such a command defined by % |\NewDocumentCommand| is protected and that's why we have put the % |\multicolumn| before (in the definition of |\@@_Hdotsfor:|). % \begin{macrocode} \AtBeginDocument { \tl_set:Nn \l_@@_argspec_tl { O { } m O { } E { _ ^ } { { } { } } } \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl % \end{macrocode} % We don't put |!| before the last optionnal argument for homogeneity with % |\Cdots|, etc. which have only one optional argument. % \begin{macrocode} \exp_args:NNV \NewDocumentCommand \@@_Hdotsfor_i \l_@@_argspec_tl { \tl_gput_right:Nx \g_@@_HVdotsfor_lines_tl { \@@_Hdotsfor:nnnn { \int_use:N \c@iRow } { \int_use:N \c@jCol } { #2 } { #1 , #3 , down = \exp_not:n { #4 } , up = \exp_not:n { #5 } } } \prg_replicate:nn { #2 - 1 } { & \multicolumn { 1 } { c } { } } } } % \end{macrocode} % Enf of |\AtBeginDocument|. % % \medskip % \begin{macrocode} \cs_new_protected:Npn \@@_Hdotsfor:nnnn #1 #2 #3 #4 { \bool_set_false:N \l_@@_initial_open_bool \bool_set_false:N \l_@@_final_open_bool % \end{macrocode} % For the row, it's easy. % \begin{macrocode} \int_set:Nn \l_@@_initial_i_int { #1 } \int_set_eq:NN \l_@@_final_i_int \l_@@_initial_i_int % \end{macrocode} % For the column, it's a bit more complicated. % \begin{macrocode} \int_compare:nNnTF { #2 } = 1 { \int_set:Nn \l_@@_initial_j_int 1 \bool_set_true:N \l_@@_initial_open_bool } { \cs_if_exist:cTF { pgf @ sh @ ns @ \@@_env: - \int_use:N \l_@@_initial_i_int - \int_eval:n { #2 - 1 } } { \int_set:Nn \l_@@_initial_j_int { #2 - 1 } } { \int_set:Nn \l_@@_initial_j_int { #2 } \bool_set_true:N \l_@@_initial_open_bool } } \int_compare:nNnTF { #2 + #3 -1 } = \c@jCol { \int_set:Nn \l_@@_final_j_int { #2 + #3 - 1 } \bool_set_true:N \l_@@_final_open_bool } { \cs_if_exist:cTF { pgf @ sh @ ns @ \@@_env: - \int_use:N \l_@@_final_i_int - \int_eval:n { #2 + #3 } } { \int_set:Nn \l_@@_final_j_int { #2 + #3 } } { \int_set:Nn \l_@@_final_j_int { #2 + #3 - 1 } \bool_set_true:N \l_@@_final_open_bool } } % \end{macrocode} % % \begin{macrocode} \group_begin: \int_compare:nNnTF { #1 } = 0 { \color { nicematrix-first-row } } { \int_compare:nNnT { #1 } = \g_@@_row_total_int { \color { nicematrix-last-row } } } \keys_set:nn { NiceMatrix / xdots } { #4 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Ldots: \group_end: % \end{macrocode} % % \medskip % We declare all the cells concerned by the |\Hdotsfor| as ``dotted'' (for the % dotted lines created by |\Cdots|, |\Ldots|, etc., this job is done by % |\@@_find_extremities_of_line:nnnn|). This declaration is done by defining a % special control sequence (to nil). % \begin{macrocode} \int_step_inline:nnn { #2 } { #2 + #3 - 1 } { \cs_set:cpn { @@ _ dotted _ #1 - ##1 } { } } } % \end{macrocode} % % \bigskip % \begin{macrocode} \AtBeginDocument { \tl_set:Nn \l_@@_argspec_tl { O { } m O { } E { _ ^ } { { } { } } } \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl \exp_args:NNV \NewDocumentCommand \@@_Vdotsfor: \l_@@_argspec_tl { \tl_gput_right:Nx \g_@@_HVdotsfor_lines_tl { \@@_Vdotsfor:nnnn { \int_use:N \c@iRow } { \int_use:N \c@jCol } { #2 } { #1 , #3 , down = \exp_not:n { #4 } , up = \exp_not:n { #5 } } } } } % \end{macrocode} % Enf of |\AtBeginDocument|. % % \begin{macrocode} \cs_new_protected:Npn \@@_Vdotsfor:nnnn #1 #2 #3 #4 { \bool_set_false:N \l_@@_initial_open_bool \bool_set_false:N \l_@@_final_open_bool % \end{macrocode} % For the column, it's easy. % \begin{macrocode} \int_set:Nn \l_@@_initial_j_int { #2 } \int_set_eq:NN \l_@@_final_j_int \l_@@_initial_j_int % \end{macrocode} % For the row, it's a bit more complicated. % \begin{macrocode} \int_compare:nNnTF #1 = 1 { \int_set:Nn \l_@@_initial_i_int 1 \bool_set_true:N \l_@@_initial_open_bool } { \cs_if_exist:cTF { pgf @ sh @ ns @ \@@_env: - \int_eval:n { #1 - 1 } - \int_use:N \l_@@_initial_j_int } { \int_set:Nn \l_@@_initial_i_int { #1 - 1 } } { \int_set:Nn \l_@@_initial_i_int { #1 } \bool_set_true:N \l_@@_initial_open_bool } } \int_compare:nNnTF { #1 + #3 -1 } = \c@iRow { \int_set:Nn \l_@@_final_i_int { #1 + #3 - 1 } \bool_set_true:N \l_@@_final_open_bool } { \cs_if_exist:cTF { pgf @ sh @ ns @ \@@_env: - \int_eval:n { #1 + #3 } - \int_use:N \l_@@_final_j_int } { \int_set:Nn \l_@@_final_i_int { #1 + #3 } } { \int_set:Nn \l_@@_final_i_int { #1 + #3 - 1 } \bool_set_true:N \l_@@_final_open_bool } } % \end{macrocode} % % \begin{macrocode} \group_begin: \int_compare:nNnTF { #2 } = 0 { \color { nicematrix-first-col } } { \int_compare:nNnT { #2 } = \g_@@_col_total_int { \color { nicematrix-last-col } } } \keys_set:nn { NiceMatrix / xdots } { #4 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \@@_actually_draw_Vdots: \group_end: % \end{macrocode} % % \medskip % We declare all the cells concerned by the |\Vdotsfor| as ``dotted'' (for the % dotted lines created by |\Cdots|, |\Ldots|, etc., this job is done by % |\@@_find_extremities_of_line:nnnn|). This declaration is done by defining a % special control sequence (to nil). % \begin{macrocode} \int_step_inline:nnn { #1 } { #1 + #3 - 1 } { \cs_set:cpn { @@ _ dotted _ ##1 - #2 } { } } } % \end{macrocode} % % % \vspace{1cm} % The command |\@@_rotate:| will be linked to |\rotate| in % |{NiceArrayWithDelims}|. % \begin{macrocode} \cs_new_protected:Npn \@@_rotate: { \bool_gset_true:N \g_@@_rotate_bool } % \end{macrocode} % % \bigskip % \subsection*{The command \textbackslash line accessible in code-after} % % In the |\CodeAfter|, the command |\@@_line:nn| will be linked to |\line|. This % command takes two arguments which are the specifications of two cells in the % array (in the format $i$-$j$) and draws a dotted line between these cells. % % \medskip % First, we write a command with an argument of the format $i$-$j$ and applies % the command |\int_eval:n| to $i$ and~$j$ ; this must \emph{not} be protected % (and is, of course fully expandable).\footnote{Indeed, we want that the user % may use the command |\line| in |\CodeAfter| with LaTeX counters in the % arguments --- with the command |\value|.} % \begin{macrocode} \cs_new:Npn \@@_double_int_eval:n #1-#2 \q_stop { \int_eval:n { #1 } - \int_eval:n { #2 } } % \end{macrocode} % % % \medskip % With the following construction, the command |\@@_double_int_eval:n| is % applied to both arguments before the application of |\@@_line_i:nn| (the % construction uses the fact the |\@@_line_i:nn| is protected and that % |\@@_double_int_eval:n| is fully expandable). % \begin{macrocode} \AtBeginDocument { \tl_set:Nn \l_@@_argspec_tl { O { } m m ! O { } E { _ ^ } { { } { } } } \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl \exp_args:NNV \NewDocumentCommand \@@_line \l_@@_argspec_tl { \group_begin: \keys_set:nn { NiceMatrix / xdots } { #1 , #4 , down = #5 , up = #6 } \tl_if_empty:VF \l_@@_xdots_color_tl { \color { \l_@@_xdots_color_tl } } \use:e { \@@_line_i:nn { \@@_double_int_eval:n #2 \q_stop } { \@@_double_int_eval:n #3 \q_stop } } \group_end: } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_line_i:nn #1 #2 { \bool_set_false:N \l_@@_initial_open_bool \bool_set_false:N \l_@@_final_open_bool \bool_if:nTF { \cs_if_free_p:c { pgf @ sh @ ns @ \@@_env: - #1 } || \cs_if_free_p:c { pgf @ sh @ ns @ \@@_env: - #2 } } { \@@_error:nnn { unknown~cell~for~line~in~CodeAfter } { #1 } { #2 } } { \@@_draw_line_ii:nn { #1 } { #2 } } } % \end{macrocode} % % \begin{macrocode} \AtBeginDocument { \cs_new_protected:Npx \@@_draw_line_ii:nn #1 #2 { % \end{macrocode} % We recall that, when externalization is used, |\tikzpicture| and % |\endtikzpicture| (or |\pgfpicture| and |\endpgfpicture|) must be directly % ``visible'' and that why we do this static construction of the command % |\@@_draw_line_ii:|. % \begin{macrocode} \c_@@_pgfortikzpicture_tl \@@_draw_line_iii:nn { #1 } { #2 } \c_@@_endpgfortikzpicture_tl } } % \end{macrocode} % % \bigskip % The following command \emph{must} be protected (it's used in the % construction of |\@@_draw_line_ii:nn|). % \begin{macrocode} \cs_new_protected:Npn \@@_draw_line_iii:nn #1 #2 { \pgfrememberpicturepositiononpagetrue \pgfpointshapeborder { \@@_env: - #1 } { \@@_qpoint:n { #2 } } \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y \pgfpointshapeborder { \@@_env: - #2 } { \@@_qpoint:n { #1 } } \dim_set_eq:NN \l_@@_x_final_dim \pgf@x \dim_set_eq:NN \l_@@_y_final_dim \pgf@y \@@_draw_line: } % \end{macrocode} % % % The commands |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, and |\Iddots| don't use % this command because they have to do other settings (for example, the diagonal % lines must be parallelized). % % \bigskip % \subsection*{Colors of cells, rows and columns} % % We want to avoid the thin white lines that are shown in some \textsc{pdf} % viewers (eg: with the engine MuPDF used by SumatraPDF). That's why we try to % draw rectangles of the same color in the same instruction |\pgfusepath { fill }| % (and they will be in the same instruction |fill|---coded |f|---in the % resulting \textsc{pdf}). % % The commands |\@@_rowcolor|, |\@@_columncolor|, |\@@_rectanglecolor| and % |\@@_rowlistcolors| don't directly draw the corresponding rectangles. Instead, % they store their instructions color by color: % \begin{itemize} % \item A sequence |\g_@@_colors_seq| will be built containing all the colors % used by at least one of these instructions. Each \emph{color} may be prefixed % by its color model (eg: |[gray]{0.5}|). % \item For the color whose index in |\g_@@_colors_seq| is equal to~$i$, a list of % instructions which use that color will be constructed in the token list % |\g_@@_color_|$i$|_tl|. In that token list, the instructions will be written % using |\@@_cartesian_color:nn| and |\@@_rectanglecolor:nn|. % \end{itemize} % % % \bigskip % |#1| is the color and |#2| is an instruction using that color. Despite its % name, the command |\@@_add_to_colors_seq:nn| doesn't only add a color to % |\g_@@_colors_seq|: it also updates the corresponding token list % |\g_@@_color_|$i$|_tl|. We add in a global way because the final user may use % the instructions such as |\cellcolor| in a loop of \pkg{pgffor} in the % |\CodeBefore| (and we recall that a loop of \pkg{pgffor} is encapsulated in a % group). % \begin{macrocode} \cs_new_protected:Npn \@@_add_to_colors_seq:nn #1 #2 { % \end{macrocode} % Firt, we look for the number of the color and, if it's found, we store it in % |\l_tmpa_int|. If the color is not present in |\l_@@_colors_seq|, % |\l_tmpa_int| will remain equal to $0$. % \begin{macrocode} \int_zero:N \l_tmpa_int \seq_map_indexed_inline:Nn \g_@@_colors_seq { \tl_if_eq:nnT { #1 } { ##2 } { \int_set:Nn \l_tmpa_int { ##1 } } } \int_compare:nNnTF \l_tmpa_int = \c_zero_int % \end{macrocode} % First, the case where the color is a \emph{new} color (not in the sequence). % \begin{macrocode} { \seq_gput_right:Nn \g_@@_colors_seq { #1 } \tl_gset:cx { g_@@_color _ \seq_count:N \g_@@_colors_seq _ tl } { #2 } } % \end{macrocode} % Now, the case where the color is \emph{not} a new color (the color is in the % sequence at the position |\l_tmpa_int|). % \begin{macrocode} { \tl_gput_right:cx { g_@@_color _ \int_use:N \l_tmpa_int _tl } { #2 } } } % \end{macrocode} % % \begin{macrocode} \cs_generate_variant:Nn \@@_add_to_colors_seq:nn { x n } \cs_generate_variant:Nn \@@_add_to_colors_seq:nn { x x } % \end{macrocode} % % \bigskip % The macro |\@@_actually_color:| will actually fill all the rectangles, color by % color (using the sequence |\l_@@_colors_seq| and all the token lists of the % form |\l_@@_color_|$i$|_tl|). % \begin{macrocode} \cs_new_protected:Npn \@@_actually_color: { \pgfpicture \pgf@relevantforpicturesizefalse \seq_map_indexed_inline:Nn \g_@@_colors_seq { \color ##2 \use:c { g_@@_color _ ##1 _tl } \tl_gclear:c { g_@@_color _ ##1 _tl } \pgfusepath { fill } } \endpgfpicture } % \end{macrocode} % % \begin{macrocode} \cs_set_protected:Npn \@@_cut_on_hyphen:w #1-#2\q_stop { \tl_set:Nn \l_tmpa_tl { #1 } \tl_set:Nn \l_tmpb_tl { #2 } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_cartesian_color:nn #1 #2 { \tl_set:Nn \l_@@_rows_tl { #1 } \tl_set:Nn \l_@@_cols_tl { #2 } \@@_cartesian_path: } % \end{macrocode} % % \bigskip % Here is an example : |\@@_rowcolor {red!15} {1,3,5-7,10-}| % \begin{macrocode} \NewDocumentCommand \@@_rowcolor { O { } m m } { \tl_if_blank:nF { #2 } { \@@_add_to_colors_seq:xn { \tl_if_blank:nF { #1 } { [ #1 ] } { #2 } } { \@@_cartesian_color:nn { #3 } { - } } } } % \end{macrocode} % % \bigskip % Here an example : |\@@_columncolor:nn {red!15} {1,3,5-7,10-}| % \begin{macrocode} \NewDocumentCommand \@@_columncolor { O { } m m } { \tl_if_blank:nF { #2 } { \@@_add_to_colors_seq:xn { \tl_if_blank:nF { #1 } { [ #1 ] } { #2 } } { \@@_cartesian_color:nn { - } { #3 } } } } % \end{macrocode} % % \bigskip % Here is an example : |\@@_rectanglecolor{red!15}{2-3}{5-6}| % \begin{macrocode} \NewDocumentCommand \@@_rectanglecolor { O { } m m m } { \tl_if_blank:nF { #2 } { \@@_add_to_colors_seq:xn { \tl_if_blank:nF { #1 } { [ #1 ] } { #2 } } { \@@_rectanglecolor:nnn { #3 } { #4 } { 0 pt } } } } % \end{macrocode} % % \bigskip % The last argument is the radius of the corners of the rectangle. % \begin{macrocode} \NewDocumentCommand \@@_roundedrectanglecolor { O { } m m m m } { \tl_if_blank:nF { #2 } { \@@_add_to_colors_seq:xn { \tl_if_blank:nF { #1 } { [ #1 ] } { #2 } } { \@@_rectanglecolor:nnn { #3 } { #4 } { #5 } } } } % \end{macrocode} % % \bigskip % The last argument is the radius of the corners of the rectangle. % \begin{macrocode} \cs_new_protected:Npn \@@_rectanglecolor:nnn #1 #2 #3 { \@@_cut_on_hyphen:w #1 \q_stop \tl_clear_new:N \l_tmpc_tl \tl_clear_new:N \l_tmpd_tl \tl_set_eq:NN \l_tmpc_tl \l_tmpa_tl \tl_set_eq:NN \l_tmpd_tl \l_tmpb_tl \@@_cut_on_hyphen:w #2 \q_stop \tl_set:Nx \l_@@_rows_tl { \l_tmpc_tl - \l_tmpa_tl } \tl_set:Nx \l_@@_cols_tl { \l_tmpd_tl - \l_tmpb_tl } % \end{macrocode} % The command |\@@_cartesian_path:n| takes in two implicit arguments: % |\l_@@_cols_tl| and |\l_@@_rows_tl|. % \begin{macrocode} \@@_cartesian_path:n { #3 } } % \end{macrocode} % % % \bigskip % Here is an example : |\@@_cellcolor[rgb]{0.5,0.5,0}{2-3,3-4,4-5,5-6}| % \begin{macrocode} \NewDocumentCommand \@@_cellcolor { O { } m m } { \clist_map_inline:nn { #3 } { \@@_rectanglecolor [ #1 ] { #2 } { ##1 } { ##1 } } } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_chessboardcolors { O { } m m } { \int_step_inline:nn { \int_use:N \c@iRow } { \int_step_inline:nn { \int_use:N \c@jCol } { \int_if_even:nTF { ####1 + ##1 } { \@@_cellcolor [ #1 ] { #2 } } { \@@_cellcolor [ #1 ] { #3 } } { ##1 - ####1 } } } } % \end{macrocode} % % \bigskip % \begin{macrocode} \keys_define:nn { NiceMatrix / arraycolor } { except-corners .code:n = \@@_error:n { key except-corners } } % \end{macrocode} % % \bigskip % The command |\@@_arraycolor| (linked to |\arraycolor| at the beginning of % the |\CodeBefore|) will color the whole tabular (excepted the potential % exterior rows and columns). The third argument is a optional argument which a % list of pairs key-value. % \begin{macrocode} \NewDocumentCommand \@@_arraycolor { O { } m O { } } { \keys_set:nn { NiceMatrix / arraycolor } { #3 } \@@_rectanglecolor [ #1 ] { #2 } { 1 - 1 } { \int_use:N \c@iRow - \int_use:N \c@jCol } } % \end{macrocode} % % \bigskip % \begin{macrocode} \keys_define:nn { NiceMatrix / rowcolors } { respect-blocks .bool_set:N = \l_@@_respect_blocks_bool , respect-blocks .default:n = true , cols .tl_set:N = \l_@@_cols_tl , restart .bool_set:N = \l_@@_rowcolors_restart_bool , restart .default:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~rowcolors } } % \end{macrocode} % % \medskip % The command |\rowcolors| (accessible in the |code-before|) is inspired by the % command |\rowcolors| of the package \pkg{xcolor} (with the option |table|). % However, the command |\rowcolors| of \pkg{nicematrix} has \emph{not} the % optional argument of the command |\rowcolors| of \pkg{xcolor}. Here is an % example: |\rowcolors{1}{blue!10}{}[respect-blocks]|. % % |#1| (optional) is the color space ; % |#2| is a list of intervals of rows ; % |#3| is the list of colors ; % |#4| is for the optional list of pairs key-value. % \begin{macrocode} \NewDocumentCommand \@@_rowlistcolors { O { } m m O { } } { % \end{macrocode} % The group is for the options. |\l_@@_colors_seq| will be the list of colors. % \begin{macrocode} \group_begin: \seq_clear_new:N \l_@@_colors_seq \seq_set_split:Nnn \l_@@_colors_seq { , } { #3 } \tl_clear_new:N \l_@@_cols_tl \tl_set:Nn \l_@@_cols_tl { - } \keys_set:nn { NiceMatrix / rowcolors } { #4 } % \end{macrocode} % The counter |\l_@@_color_int| will be the rank of the current color in the list of % colors (modulo the length of the list). % \begin{macrocode} \int_zero_new:N \l_@@_color_int \int_set:Nn \l_@@_color_int 1 \bool_if:NT \l_@@_respect_blocks_bool { % \end{macrocode} % We don't want to take into account a block which is completely in the ``first % column'' of (number $0$) or in the ``last column'' and that's why we filter % the sequence of the blocks (in a the sequence |\l_tmpa_seq|). % \begin{macrocode} \seq_set_eq:NN \l_tmpb_seq \g_@@_pos_of_blocks_seq \seq_set_filter:NNn \l_tmpa_seq \l_tmpb_seq { \@@_not_in_exterior_p:nnnn ##1 } } \pgfpicture \pgf@relevantforpicturesizefalse % \end{macrocode} % |#2| is the list of intervals of rows. % \begin{macrocode} \clist_map_inline:nn { #2 } { \tl_set:Nn \l_tmpa_tl { ##1 } \tl_if_in:NnTF \l_tmpa_tl { - } { \@@_cut_on_hyphen:w ##1 \q_stop } { \tl_set:Nx \l_tmpb_tl { \int_use:N \c@iRow } } % \end{macrocode} % Now, |l_tmpa_tl| and |l_tmpb_tl| are the first row and the last row of the % interval of rows that we have to treat. The counter |\l_tmpa_int| will be the % index of the loop over the rows. % \begin{macrocode} \int_set:Nn \l_tmpa_int \l_tmpa_tl \bool_if:NTF \l_@@_rowcolors_restart_bool { \int_set:Nn \l_@@_color_int 1 } { \int_set:Nn \l_@@_color_int \l_tmpa_tl } \int_zero_new:N \l_tmpc_int \int_set:Nn \l_tmpc_int \l_tmpb_tl \int_do_until:nNnn \l_tmpa_int > \l_tmpc_int { % \end{macrocode} % We will compute in |\l_tmpb_int| the last row of the ``block''. % \begin{macrocode} \int_set_eq:NN \l_tmpb_int \l_tmpa_int % \end{macrocode} % If the key |respect-blocks| is in force, we have to adjust that value (of % course). % \begin{macrocode} \bool_if:NT \l_@@_respect_blocks_bool { \seq_set_filter:NNn \l_tmpb_seq \l_tmpa_seq { \@@_intersect_our_row_p:nnnn ####1 } \seq_map_inline:Nn \l_tmpb_seq { \@@_rowcolors_i:nnnn ####1 } % \end{macrocode} % Now, the last row of the block is computed in |\l_tmpb_int|. % \begin{macrocode} } \tl_set:Nx \l_@@_rows_tl { \int_use:N \l_tmpa_int - \int_use:N \l_tmpb_int } % \end{macrocode} % |\l_tmpc_tl| will be the color that we will use. % \begin{macrocode} \tl_clear_new:N \l_@@_color_tl \tl_set:Nx \l_@@_color_tl { \@@_color_index:n { \int_mod:nn { \l_@@_color_int - 1 } { \seq_count:N \l_@@_colors_seq } + 1 } } \tl_if_empty:NF \l_@@_color_tl { \@@_add_to_colors_seq:xx { \tl_if_blank:nF { #1 } { [ #1 ] } { \l_@@_color_tl } } { \@@_cartesian_color:nn { \l_@@_rows_tl } { \l_@@_cols_tl } } } \int_incr:N \l_@@_color_int \int_set:Nn \l_tmpa_int { \l_tmpb_int + 1 } } } \endpgfpicture \group_end: } % \end{macrocode} % % \medskip % The command |\@@_color_index:n| peeks in |\l_@@_colors_seq| the color at the % index |#1|. However, if that color is the symbol |=|, the previous one is % poken. This macro is recursive. % \begin{macrocode} \cs_new:Npn \@@_color_index:n #1 { \str_if_eq:eeTF { \seq_item:Nn \l_@@_colors_seq { #1 } } { = } { \@@_color_index:n { #1 - 1 } } { \seq_item:Nn \l_@@_colors_seq { #1 } } } % \end{macrocode} % % \bigskip % The command |\rowcolors| (available in the |\CodeBefore|) is a specialisation % of the most general command |\rowlistcolors|. % \begin{macrocode} \NewDocumentCommand \@@_rowcolors { O { } m m m O { } } { \@@_rowlistcolors [ #1 ] { #2 } { { #3 } , { #4 } } [ #5 ] } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_rowcolors_i:nnnn #1 #2 #3 #4 { \int_compare:nNnT { #3 } > \l_tmpb_int { \int_set:Nn \l_tmpb_int { #3 } } } % \end{macrocode} % % % \bigskip % \begin{macrocode} \prg_new_conditional:Nnn \@@_not_in_exterior:nnnn p { \bool_lazy_or:nnTF { \int_compare_p:nNn { #4 } = \c_zero_int } { \int_compare_p:nNn { #2 } = { \@@_succ:n { \c@jCol } } } \prg_return_false: \prg_return_true: } % \end{macrocode} % % \bigskip % The following command return |true| when the block intersects the row % |\l_tmpa_int|. % \begin{macrocode} \prg_new_conditional:Nnn \@@_intersect_our_row:nnnn p { \bool_if:nTF { \int_compare_p:n { #1 <= \l_tmpa_int } && \int_compare_p:n { \l_tmpa_int <= #3 } } \prg_return_true: \prg_return_false: } % \end{macrocode} % % \bigskip % The following command uses two implicit arguments: |\l_@@_rows_tl| and % |\l_@@_cols_tl| which are specifications for a set of rows and a set of % columns. It creates a path but does \emph{not} fill it. It must be filled by % another command after. The argument is the radius of the corners. We define % below a command |\@@_cartesian_path:| which corresponds to a value $0$~pt for % the radius of the corners. % % This command is in particular used in |\@@_rectanglecolor:nnn| (used in % |\@@_rectanglecolor|, itself used in |\@@_cellcolor|). % \begin{macrocode} \cs_new_protected:Npn \@@_cartesian_path:n #1 { \bool_lazy_and:nnT { ! \seq_if_empty_p:N \l_@@_corners_cells_seq } { \dim_compare_p:nNn { #1 } = \c_zero_dim } { \@@_expand_clist:NN \l_@@_cols_tl \c@jCol \@@_expand_clist:NN \l_@@_rows_tl \c@iRow } % \end{macrocode} % We begin the loop over the columns. % \begin{macrocode} \clist_map_inline:Nn \l_@@_cols_tl { \tl_set:Nn \l_tmpa_tl { ##1 } \tl_if_in:NnTF \l_tmpa_tl { - } { \@@_cut_on_hyphen:w ##1 \q_stop } { \@@_cut_on_hyphen:w ##1 - ##1 \q_stop } \bool_lazy_or:nnT { \tl_if_blank_p:V \l_tmpa_tl } { \str_if_eq_p:Vn \l_tmpa_tl { * } } { \tl_set:Nn \l_tmpa_tl { 1 } } \bool_lazy_or:nnT { \tl_if_blank_p:V \l_tmpb_tl } { \str_if_eq_p:Vn \l_tmpb_tl { * } } { \tl_set:Nx \l_tmpb_tl { \int_use:N \c@jCol } } \int_compare:nNnT \l_tmpb_tl > \c@jCol { \tl_set:Nx \l_tmpb_tl { \int_use:N \c@jCol } } % \end{macrocode} % |\l_tmpc_tl| will contain the number of column. % \begin{macrocode} \tl_set_eq:NN \l_tmpc_tl \l_tmpa_tl % \end{macrocode} % If we decide to provide the commands |\cellcolor|, |\rectanglecolor|, % |\rowcolor|, |\columncolor|, |\rowcolors| and |\chessboardcolors| in the % |code-before| of a |\SubMatrix|, we will have to modify the following line, by % adding a kind of offset. We will have also some other lines to modify. % \begin{macrocode} \@@_qpoint:n { col - \l_tmpa_tl } \int_compare:nNnTF \l_@@_first_col_int = \l_tmpa_tl { \dim_set:Nn \l_tmpc_dim { \pgf@x - 0.5 \arrayrulewidth } } { \dim_set:Nn \l_tmpc_dim { \pgf@x + 0.5 \arrayrulewidth } } \@@_qpoint:n { col - \@@_succ:n \l_tmpb_tl } \dim_set:Nn \l_tmpa_dim { \pgf@x + 0.5 \arrayrulewidth } % \end{macrocode} % We begin the loop over the rows. % \begin{macrocode} \clist_map_inline:Nn \l_@@_rows_tl { \tl_set:Nn \l_tmpa_tl { ####1 } \tl_if_in:NnTF \l_tmpa_tl { - } { \@@_cut_on_hyphen:w ####1 \q_stop } { \@@_cut_on_hyphen:w ####1 - ####1 \q_stop } \tl_if_empty:NT \l_tmpa_tl { \tl_set:Nn \l_tmpa_tl { 1 } } \tl_if_empty:NT \l_tmpb_tl { \tl_set:Nx \l_tmpb_tl { \int_use:N \c@iRow } } \int_compare:nNnT \l_tmpb_tl > \c@iRow { \tl_set:Nx \l_tmpb_tl { \int_use:N \c@iRow } } % \end{macrocode} % Now, the numbers of both rows are in |\l_tmpa_tl| and |\l_tmpb_tl|. % \begin{macrocode} \seq_if_in:NxF \l_@@_corners_cells_seq { \l_tmpa_tl - \l_tmpc_tl } { \@@_qpoint:n { row - \@@_succ:n \l_tmpb_tl } \dim_set:Nn \l_tmpb_dim { \pgf@y + 0.5 \arrayrulewidth } \@@_qpoint:n { row - \l_tmpa_tl } \dim_set:Nn \l_tmpd_dim { \pgf@y + 0.5 \arrayrulewidth } \pgfsetcornersarced { \pgfpoint { #1 } { #1 } } \pgfpathrectanglecorners { \pgfpoint \l_tmpc_dim \l_tmpd_dim } { \pgfpoint \l_tmpa_dim \l_tmpb_dim } } } } } % \end{macrocode} % % \bigskip % The following command corresponds to a radius of the corners equal to $0$~pt. % This command is used by the commands |\@@_rowcolors|, |\@@_columncolor| and % |\@@_rowcolor:n| (used in |\@@_rowcolor|). % \begin{macrocode} \cs_new_protected:Npn \@@_cartesian_path: { \@@_cartesian_path:n { 0 pt } } % \end{macrocode} % % % \bigskip % The following command will be used only with |\l_@@_cols_tl| and |\c@jCol| (first % case) or with |\l_@@_rows_tl| and |\c@iRow| (second case). For instance, with % |\l_@@_cols_tl| equal to |2,4-6,8-*| and |\c@jCol| equal to |10|, the clist % |\l_@@_cols_tl| will be replaced by |2,4,5,6,8,9,10|. % \begin{macrocode} \cs_new_protected:Npn \@@_expand_clist:NN #1 #2 { \clist_set_eq:NN \l_tmpa_clist #1 \clist_clear:N #1 \clist_map_inline:Nn \l_tmpa_clist { \tl_set:Nn \l_tmpa_tl { ##1 } \tl_if_in:NnTF \l_tmpa_tl { - } { \@@_cut_on_hyphen:w ##1 \q_stop } { \@@_cut_on_hyphen:w ##1 - ##1 \q_stop } \bool_lazy_or:nnT { \tl_if_blank_p:V \l_tmpa_tl } { \str_if_eq_p:Vn \l_tmpa_tl { * } } { \tl_set:Nn \l_tmpa_tl { 1 } } \bool_lazy_or:nnT { \tl_if_blank_p:V \l_tmpb_tl } { \str_if_eq_p:Vn \l_tmpb_tl { * } } { \tl_set:Nx \l_tmpb_tl { \int_use:N #2 } } \int_compare:nNnT \l_tmpb_tl > #2 { \tl_set:Nx \l_tmpb_tl { \int_use:N #2 } } \int_step_inline:nnn \l_tmpa_tl \l_tmpb_tl { \clist_put_right:Nn #1 { ####1 } } } } % \end{macrocode} % % \bigskip % When the user uses the key |colortbl-like|, the following command will % be linked to |\cellcolor| in the tabular. % \begin{macrocode} \NewDocumentCommand \@@_cellcolor_tabular { O { } m } { \peek_remove_spaces:n { \tl_gput_right:Nx \g_nicematrix_code_before_tl { % \end{macrocode} % We must not expand the color (|#2|) because the color may contain the token % |!| which may be activated by some packages (ex.: \pkg{babel} with the option % |french| on latex and pdflatex). % \begin{macrocode} \cellcolor [ #1 ] { \exp_not:n { #2 } } { \int_use:N \c@iRow - \int_use:N \c@jCol } } } } % \end{macrocode} % % \bigskip % When the user uses the key |colortbl-like|, the following command will % be linked to |\rowcolor| in the tabular. % \begin{macrocode} \NewDocumentCommand \@@_rowcolor_tabular { O { } m } { \peek_remove_spaces:n { \tl_gput_right:Nx \g_nicematrix_code_before_tl { \exp_not:N \rectanglecolor [ #1 ] { \exp_not:n { #2 } } { \int_use:N \c@iRow - \int_use:N \c@jCol } { \int_use:N \c@iRow - \exp_not:n { \int_use:N \c@jCol } } } } } % \end{macrocode} % % % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_columncolor_preamble { O { } m } { % \end{macrocode} % With the following line, we test whether the cell is the first one we % encounter in its column (don't forget that some rows may be incomplete). % \begin{macrocode} \int_compare:nNnT \c@jCol > \g_@@_col_total_int { % \end{macrocode} % You use |gput_left| because we want the specification of colors for the % columns drawn before the specifications of color for the rows (and the cells). % Be careful: maybe this is not effective since we have an analyze of the % instructions in the |\CodeBefore| in order to fill color by color (to avoid % the thin white lines). % \begin{macrocode} \tl_gput_left:Nx \g_nicematrix_code_before_tl { \exp_not:N \columncolor [ #1 ] { \exp_not:n { #2 } } { \int_use:N \c@jCol } } } } % \end{macrocode} % % % % % \bigskip % \subsection*{The vertical rules} % % We give to the user the possibility to define new types of columns (with % |\newcolumntype| of \pkg{array}) for special vertical rules (\emph{e.g.} rules % thicker than the standard ones) which will not extend in the potential % exterior rows of the array. % % We provide the command |\OnlyMainNiceMatrix| in that goal. However, that % command must be no-op outside the environments of \pkg{nicematrix} (and so the % user will be allowed to use the same new type of column in the environments % of \pkg{nicematrix} and in the standard environments of \pkg{array}). % % That's why we provide first a global definition of |\OnlyMainNiceMatrix|. % \begin{macrocode} \cs_set_eq:NN \OnlyMainNiceMatrix \use:n % \end{macrocode} % % \medskip % Another definition of |\OnlyMainNiceMatrix| will be linked to the command in % the environments of \pkg{nicematrix}. Here is that definition, called % |\@@_OnlyMainNiceMatrix:n|. % % \begin{macrocode} \cs_new_protected:Npn \@@_OnlyMainNiceMatrix:n #1 { \int_compare:nNnTF \l_@@_first_col_int = 0 { \@@_OnlyMainNiceMatrix_i:n { #1 } } { \int_compare:nNnTF \c@jCol = 0 { \int_compare:nNnF \c@iRow = { -1 } { \int_compare:nNnF \c@iRow = { \l_@@_last_row_int - 1 } { #1 } } } { \@@_OnlyMainNiceMatrix_i:n { #1 } } } } % \end{macrocode} % This definition may seem complicated but we must remind that the number of row % |\c@iRow| is incremented in the first cell of the row, \emph{after} a % potential vertical rule on the left side of the first cell. % % \smallskip % The command |\@@_OnlyMainNiceMatrix_i:n| is only a short-cut which is used % twice in the above command. This command must \emph{not} be protected. % % \begin{macrocode} \cs_new_protected:Npn \@@_OnlyMainNiceMatrix_i:n #1 { \int_compare:nNnF \c@iRow = 0 { \int_compare:nNnF \c@iRow = \l_@@_last_row_int { #1 } } } % \end{macrocode} % Remember that |\c@iRow| is not always inferior to |\l_@@_last_row_int| because % |\l_@@_last_row_int| may be equal to $-2$ or $-1$ (we can't write % |\int_compare:nNnT \c@iRow < \l_@@_last_row_int|). % % % \bigskip % The following command will be executed in the |internal-code-after|. The rule % will be drawn \emph{before} the column |#1| (that is to say on the left side). % |#2| is the number of consecutive occurrences of \verb+|+. |#3| and |#4| are % numbers of rows that define the delimitation of the horizontal rule that we % have to draw. If |#4| is empty, that means that the rule extends until the % last row. % \begin{macrocode} \cs_new_protected:Npn \@@_vline:nnnn #1 #2 #3 #4 { % \end{macrocode} % The following test is for the case where the user does not use all the columns % specified in the preamble of the environment (for instance, a preamble of % \verb+|c|c|c|+ but only two columns used). % \begin{macrocode} \int_compare:nNnT { #1 } < { \c@jCol + 2 } { \pgfpicture \@@_vline_i:nnnn { #1 } { #2 } { #3 } { #4 } \endpgfpicture } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_vline_i:nnnn #1 #2 #3 #4 { % \end{macrocode} % |\l_tmpa_tl| is the number of row and |\l_tmpb_tl| the number of column. When % we have found a row corresponding to a rule to draw, we note its number in % |\l_tmpc_tl|. % \begin{macrocode} \tl_set:Nx \l_tmpb_tl { #1 } \tl_clear_new:N \l_tmpc_tl \int_step_variable:nnNn { #3 } { \tl_if_blank:nTF { #4 } { \int_use:N \c@iRow } { #4 } } \l_tmpa_tl { % \end{macrocode} % The boolean |\g_tmpa_bool| indicates whether the small vertical rule will be % drawn. If we find that it is in a block (a real block, created by |\Block| or % a virtual block corresponding to a dotted line, created by |\Cdots|, |\Vdots|, % etc.), we will set |\g_tmpa_bool| to |false| and the small vertical rule won't % be drawn. % \begin{macrocode} \bool_gset_true:N \g_tmpa_bool \seq_map_inline:Nn \g_@@_pos_of_blocks_seq { \@@_test_vline_in_block:nnnn ##1 } \seq_map_inline:Nn \g_@@_pos_of_xdots_seq { \@@_test_vline_in_block:nnnn ##1 } \seq_map_inline:Nn \g_@@_pos_of_stroken_blocks_seq { \@@_test_vline_in_stroken_block:nnnn ##1 } \clist_if_empty:NF \l_@@_corners_clist \@@_test_in_corner_v: \bool_if:NTF \g_tmpa_bool { \tl_if_empty:NT \l_tmpc_tl % \end{macrocode} % We keep in memory that we have a rule to draw. % \begin{macrocode} { \tl_set_eq:NN \l_tmpc_tl \l_tmpa_tl } } { \tl_if_empty:NF \l_tmpc_tl { \@@_vline_ii:nnnn { #1 } { #2 } \l_tmpc_tl { \int_eval:n { \l_tmpa_tl - 1 } } \tl_clear:N \l_tmpc_tl } } } \tl_if_empty:NF \l_tmpc_tl { \@@_vline_ii:nnnn { #1 } { #2 } \l_tmpc_tl { \tl_if_blank:nTF { #4 } { \int_use:N \c@iRow } { #4 } } \tl_clear:N \l_tmpc_tl } } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_test_in_corner_v: { \int_compare:nNnTF \l_tmpb_tl = { \@@_succ:n \c@jCol } { \seq_if_in:NxT \l_@@_corners_cells_seq { \l_tmpa_tl - \@@_pred:n \l_tmpb_tl } { \bool_set_false:N \g_tmpa_bool } } { \seq_if_in:NxT \l_@@_corners_cells_seq { \l_tmpa_tl - \l_tmpb_tl } { \int_compare:nNnTF \l_tmpb_tl = 1 { \bool_set_false:N \g_tmpa_bool } { \seq_if_in:NxT \l_@@_corners_cells_seq { \l_tmpa_tl - \@@_pred:n \l_tmpb_tl } { \bool_set_false:N \g_tmpa_bool } } } } } % \end{macrocode} % % \bigskip % |#1| is the number of the column; |#2| is the number of vertical rules to % draw (with potentially a color between); |#3| and |#4| are the numbers of the % rows between which the rule has to be drawn. % \begin{macrocode} \cs_new_protected:Npn \@@_vline_ii:nnnn #1 #2 #3 #4 { \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \@@_qpoint:n { row - #3 } \dim_set_eq:NN \l_tmpa_dim \pgf@y \@@_qpoint:n { col - #1 } \dim_set_eq:NN \l_tmpb_dim \pgf@x \@@_qpoint:n { row - \@@_succ:n { #4 } } \dim_set_eq:NN \l_tmpc_dim \pgf@y \bool_lazy_all:nT { { \int_compare_p:nNn { #2 } > 1 } { \cs_if_exist_p:N \CT@drsc@ } % condition added in version 5.18a { ! \tl_if_blank_p:V \CT@drsc@ } } { \group_begin: \CT@drsc@ \dim_add:Nn \l_tmpa_dim { 0.5 \arrayrulewidth } \dim_sub:Nn \l_tmpc_dim { 0.5 \arrayrulewidth } \dim_set:Nn \l_tmpd_dim { \l_tmpb_dim - ( \doublerulesep + \arrayrulewidth ) * ( #2 - 1 ) } \pgfpathrectanglecorners { \pgfpoint \l_tmpb_dim \l_tmpa_dim } { \pgfpoint \l_tmpd_dim \l_tmpc_dim } \pgfusepath { fill } \group_end: } \pgfpathmoveto { \pgfpoint \l_tmpb_dim \l_tmpa_dim } \pgfpathlineto { \pgfpoint \l_tmpb_dim \l_tmpc_dim } \prg_replicate:nn { #2 - 1 } { \dim_sub:Nn \l_tmpb_dim \arrayrulewidth \dim_sub:Nn \l_tmpb_dim \doublerulesep \pgfpathmoveto { \pgfpoint \l_tmpb_dim \l_tmpa_dim } \pgfpathlineto { \pgfpoint \l_tmpb_dim \l_tmpc_dim } } \CT@arc@ \pgfsetlinewidth { 1.1 \arrayrulewidth } \pgfsetrectcap \pgfusepathqstroke } % \end{macrocode} % % \bigskip % The following command draws a complete vertical rule in the column |#1| (|#2| % is the number of consecutive rules specified by the number of \verb+|+ in the % preamble). This command will be used if there is no block in the array (and % the key |corners| is not used). % \begin{macrocode} \cs_new_protected:Npn \@@_vline_i_complete:nn #1 #2 { \@@_vline_ii:nnnn { #1 } { #2 } 1 { \int_use:N \c@iRow } } % \end{macrocode} % % \bigskip % The command |\@@_draw_vlines:| draws all the vertical rules excepted in the % blocks, in the virtual blocks (determined by a command such as |\Cdots|) and in % the corners (if the key |corners| is used). % \begin{macrocode} \cs_new_protected:Npn \@@_draw_vlines: { \int_step_inline:nnn { \bool_if:nTF { \l_@@_NiceArray_bool && ! \l_@@_except_borders_bool } 1 2 } { \bool_if:nTF { \l_@@_NiceArray_bool && ! \l_@@_except_borders_bool } { \@@_succ:n \c@jCol } \c@jCol } { \tl_if_eq:NnF \l_@@_vlines_clist { all } { \clist_if_in:NnT \l_@@_vlines_clist { ##1 } } { \@@_vline:nnnn { ##1 } 1 1 { } } } } % \end{macrocode} % % % % \subsection*{The horizontal rules} % % \bigskip % The following command will be executed in the |internal-code-after|. The rule % will be drawn \emph{before} the row |#1|. |#2| is the number of consecutive % occurrences of |\Hline|. |#3| and |#4| are numbers of columns that define the % delimitation of the horizontal rule that we have to draw. If |#4| is empty, % that means that the rule extends until the last column. % \begin{macrocode} \cs_new_protected:Npn \@@_hline:nnnn #1 #2 #3 #4 { \pgfpicture \@@_hline_i:nnnn { #1 } { #2 } { #3 } { #4 } \endpgfpicture } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_hline_i:nnnn #1 #2 #3 #4 { % \end{macrocode} % |\l_tmpa_tl| is the number of row and |\l_tmpb_tl| the number of column. When % we have found a column corresponding to a rule to draw, we note its number in % |\l_tmpc_tl|. % \begin{macrocode} \tl_set:Nn \l_tmpa_tl { #1 } \tl_clear_new:N \l_tmpc_tl \int_step_variable:nnNn { #3 } { \tl_if_blank:nTF { #4 } { \int_use:N \c@jCol } { #4 } } \l_tmpb_tl { % \end{macrocode} % The boolean |\g_tmpa_bool| indicates whether the small horizontal rule will be % drawn. If we find that it is in a block (a real block, created by |\Block| or % a virtual block corresponding to a dotted line, created by |\Cdots|, |\Vdots|, % etc.), we will set |\g_tmpa_bool| to |false| and the small horizontal rule won't % be drawn. % \begin{macrocode} \bool_gset_true:N \g_tmpa_bool \seq_map_inline:Nn \g_@@_pos_of_blocks_seq { \@@_test_hline_in_block:nnnn ##1 } \seq_map_inline:Nn \g_@@_pos_of_xdots_seq { \@@_test_hline_in_block:nnnn ##1 } \seq_map_inline:Nn \g_@@_pos_of_stroken_blocks_seq { \@@_test_hline_in_stroken_block:nnnn ##1 } \clist_if_empty:NF \l_@@_corners_clist \@@_test_in_corner_h: \bool_if:NTF \g_tmpa_bool { \tl_if_empty:NT \l_tmpc_tl % \end{macrocode} % We keep in memory that we have a rule to draw. % \begin{macrocode} { \tl_set_eq:NN \l_tmpc_tl \l_tmpb_tl } } { \tl_if_empty:NF \l_tmpc_tl { \@@_hline_ii:nnnn { #1 } { #2 } \l_tmpc_tl { \int_eval:n { \l_tmpb_tl - 1 } } \tl_clear:N \l_tmpc_tl } } } \tl_if_empty:NF \l_tmpc_tl { \@@_hline_ii:nnnn { #1 } { #2 } \l_tmpc_tl { \tl_if_blank:nTF { #4 } { \int_use:N \c@jCol } { #4 } } \tl_clear:N \l_tmpc_tl } } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_test_in_corner_h: { \int_compare:nNnTF \l_tmpa_tl = { \@@_succ:n \c@iRow } { \seq_if_in:NxT \l_@@_corners_cells_seq { \@@_pred:n \l_tmpa_tl - \l_tmpb_tl } { \bool_set_false:N \g_tmpa_bool } } { \seq_if_in:NxT \l_@@_corners_cells_seq { \l_tmpa_tl - \l_tmpb_tl } { \int_compare:nNnTF \l_tmpa_tl = 1 { \bool_set_false:N \g_tmpa_bool } { \seq_if_in:NxT \l_@@_corners_cells_seq { \@@_pred:n \l_tmpa_tl - \l_tmpb_tl } { \bool_set_false:N \g_tmpa_bool } } } } } % \end{macrocode} % % \bigskip % |#1| is the number of the row; |#2| is the number of horizontal rules to % draw (with potentially a color between); |#3| and |#4| are the number of the % columns between which the rule has to be drawn. % \begin{macrocode} \cs_new_protected:Npn \@@_hline_ii:nnnn #1 #2 #3 #4 { \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \@@_qpoint:n { col - #3 } \dim_set_eq:NN \l_tmpa_dim \pgf@x \@@_qpoint:n { row - #1 } \dim_set_eq:NN \l_tmpb_dim \pgf@y \@@_qpoint:n { col - \@@_succ:n { #4 } } \dim_set_eq:NN \l_tmpc_dim \pgf@x \bool_lazy_all:nT { { \int_compare_p:nNn { #2 } > 1 } { \cs_if_exist_p:N \CT@drsc@ } % condition added in version 6.0 { ! \tl_if_blank_p:V \CT@drsc@ } } { \group_begin: \CT@drsc@ \dim_set:Nn \l_tmpd_dim { \l_tmpb_dim - ( \doublerulesep + \arrayrulewidth ) * ( #2 - 1 ) } \pgfpathrectanglecorners { \pgfpoint \l_tmpa_dim \l_tmpb_dim } { \pgfpoint \l_tmpc_dim \l_tmpd_dim } \pgfusepathqfill \group_end: } \pgfpathmoveto { \pgfpoint \l_tmpa_dim \l_tmpb_dim } \pgfpathlineto { \pgfpoint \l_tmpc_dim \l_tmpb_dim } \prg_replicate:nn { #2 - 1 } { \dim_sub:Nn \l_tmpb_dim \arrayrulewidth \dim_sub:Nn \l_tmpb_dim \doublerulesep \pgfpathmoveto { \pgfpoint \l_tmpa_dim \l_tmpb_dim } \pgfpathlineto { \pgfpoint \l_tmpc_dim \l_tmpb_dim } } \CT@arc@ \pgfsetlinewidth { 1.1 \arrayrulewidth } \pgfsetrectcap \pgfusepathqstroke } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_hline_i_complete:nn #1 #2 { \@@_hline_ii:nnnn { #1 } { #2 } 1 { \int_use:N \c@jCol } } % \end{macrocode} % % \bigskip % The command |\@@_draw_hlines:| draws all the horizontal rules excepted in the % blocks (even the virtual drawn determined by commands such as |\Cdots| and in % the corners (if the key |corners| is used). % \begin{macrocode} \cs_new_protected:Npn \@@_draw_hlines: { \int_step_inline:nnn { \bool_if:nTF { \l_@@_NiceArray_bool && ! \l_@@_except_borders_bool } 1 2 } { \bool_if:nTF { \l_@@_NiceArray_bool && ! \l_@@_except_borders_bool } { \@@_succ:n \c@iRow } \c@iRow } { \tl_if_eq:NnF \l_@@_hlines_clist { all } { \clist_if_in:NnT \l_@@_hlines_clist { ##1 } } { \@@_hline:nnnn { ##1 } 1 1 { } } } } % \end{macrocode} % % % \medskip % The command |\@@_Hline:| will be linked to |\Hline| in the environments of \pkg{nicematrix}. % \begin{macrocode} \cs_set:Npn \@@_Hline: { \noalign { \ifnum 0 = `} \fi \@@_Hline_i:n { 1 } } % \end{macrocode} % % \medskip % The argument of the command |\@@_Hline_i:n| is the number of successive % |\Hline| found. % \begin{macrocode} \cs_set:Npn \@@_Hline_i:n #1 { \peek_meaning_ignore_spaces:NTF \Hline { \@@_Hline_ii:nn { #1 + 1 } } { \@@_Hline_iii:n { #1 } } } % \end{macrocode} % % \begin{macrocode} \cs_set:Npn \@@_Hline_ii:nn #1 #2 { \@@_Hline_i:n { #1 } } % \end{macrocode} % % \begin{macrocode} \cs_set:Npn \@@_Hline_iii:n #1 { \skip_vertical:n { \arrayrulewidth * ( #1 ) + \doublerulesep * ( \int_max:nn 0 { #1 - 1 } ) } \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_hline:nnnn { \@@_succ:n { \c@iRow } } { #1 } 1 { } } \ifnum 0 = `{ \fi } } % \end{macrocode} % % \subsection*{The key hvlines} % % The following command tests whether the current position in the array (given by % |\l_tmpa_tl| for the row and |\l_tmpb_tl| for the column) would provide an % horizontal rule towards the right in the block delimited by the four arguments % |#1|, |#2|, |#3| and |#4|. If this rule would be in the block (it must not be % drawn), the boolean |\l_tmpa_bool| is set to |false|. % \begin{macrocode} \cs_new_protected:Npn \@@_test_hline_in_block:nnnn #1 #2 #3 #4 { \bool_lazy_all:nT { { \int_compare_p:nNn \l_tmpa_tl > { #1 } } { \int_compare_p:nNn \l_tmpa_tl < { #3 + 1 } } { \int_compare_p:nNn \l_tmpb_tl > { #2 - 1 } } { \int_compare_p:nNn \l_tmpb_tl < { #4 + 1 } } } { \bool_gset_false:N \g_tmpa_bool } } % \end{macrocode} % % The same for vertical rules. % \begin{macrocode} \cs_new_protected:Npn \@@_test_vline_in_block:nnnn #1 #2 #3 #4 { \bool_lazy_all:nT { { \int_compare_p:nNn \l_tmpa_tl > { #1 - 1 } } { \int_compare_p:nNn \l_tmpa_tl < { #3 + 1 } } { \int_compare_p:nNn \l_tmpb_tl > { #2 } } { \int_compare_p:nNn \l_tmpb_tl < { #4 + 1 } } } { \bool_gset_false:N \g_tmpa_bool } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_test_hline_in_stroken_block:nnnn #1 #2 #3 #4 { \bool_lazy_all:nT { { \int_compare_p:nNn \l_tmpa_tl > { #1 - 1 } } { \int_compare_p:nNn \l_tmpa_tl < { #3 + 2 } } { \int_compare_p:nNn \l_tmpb_tl > { #2 - 1 } } { \int_compare_p:nNn \l_tmpb_tl < { #4 + 1 } } } { \bool_gset_false:N \g_tmpa_bool } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_test_vline_in_stroken_block:nnnn #1 #2 #3 #4 { \bool_lazy_all:nT { { \int_compare_p:nNn \l_tmpa_tl > { #1 - 1 } } { \int_compare_p:nNn \l_tmpa_tl < { #3 + 1 } } { \int_compare_p:nNn \l_tmpb_tl > { #2 - 1 } } { \int_compare_p:nNn \l_tmpb_tl < { #4 + 2 } } } { \bool_gset_false:N \g_tmpa_bool } } % \end{macrocode} % % \bigskip % \subsection*{The key corners} % % When the key |corners| is raised, the rules are not drawn in the % corners. Of course, we have to compute the corners before we begin to draw the % rules. % % \begin{macrocode} \cs_new_protected:Npn \@@_compute_corners: { % \end{macrocode} % The sequence |\l_@@_corners_cells_seq| will be the sequence of all the % empty cells (and not in a block) considered in the corners of the array. % \begin{macrocode} \seq_clear_new:N \l_@@_corners_cells_seq \clist_map_inline:Nn \l_@@_corners_clist { \str_case:nnF { ##1 } { { NW } { \@@_compute_a_corner:nnnnnn 1 1 1 1 \c@iRow \c@jCol } { NE } { \@@_compute_a_corner:nnnnnn 1 \c@jCol 1 { -1 } \c@iRow 1 } { SW } { \@@_compute_a_corner:nnnnnn \c@iRow 1 { -1 } 1 1 \c@jCol } { SE } { \@@_compute_a_corner:nnnnnn \c@iRow \c@jCol { -1 } { -1 } 1 1 } } { \@@_error:nn { bad~corner } { ##1 } } } % \end{macrocode} % Even if the user has used the key |corners| (or the key % |hvlines-except-corners|), the list of cells in the corners may be empty. % \begin{macrocode} \seq_if_empty:NF \l_@@_corners_cells_seq { % \end{macrocode} % You write on the |aux| file the list of the cells which are in the (empty) % corners because you need that information in the |\CodeBefore| since the % commands which color the |rows|, |columns| and |cells| must not color the % cells in the corners. % \begin{macrocode} \tl_gput_right:Nx \g_@@_aux_tl { \seq_set_from_clist:Nn \exp_not:N \l_@@_corners_cells_seq { \seq_use:Nnnn \l_@@_corners_cells_seq , , , } } } } % \end{macrocode} % % % \bigskip % ``Computing a corner'' is determining all the empty cells (which are not in a % block) that belong to that corner. These cells will be added to the sequence % |\l_@@_corners_cells_seq|. % % \medskip % The six arguments of |\@@_compute_a_corner:nnnnnn| are as follow: % \begin{itemize} % \item |#1| and |#2| are the number of row and column of the cell which is % actually in the corner; % \item |#3| and |#4| are the steps in rows and the step in columns when moving % from the corner; % \item |#5| is the number of the final row when scanning the rows from the % corner; % \item |#6| is the number of the final column when scanning the columns from % the corner. % \end{itemize} % \begin{macrocode} \cs_new_protected:Npn \@@_compute_a_corner:nnnnnn #1 #2 #3 #4 #5 #6 { % \end{macrocode} % For the explanations and the name of the variables, we consider that we are % computing the left-upper corner. % % First, we try to determine which is the last empty cell (and not in a block: % we won't add that precision any longer) in the column of number~$1$. The flag % |\l_tmpa_bool| will be raised when a non-empty cell is found. % \begin{macrocode} \bool_set_false:N \l_tmpa_bool \int_zero_new:N \l_@@_last_empty_row_int \int_set:Nn \l_@@_last_empty_row_int { #1 } \int_step_inline:nnnn { #1 } { #3 } { #5 } { \@@_test_if_cell_in_a_block:nn { ##1 } { \int_eval:n { #2 } } \bool_lazy_or:nnTF { \cs_if_exist_p:c { pgf @ sh @ ns @ \@@_env: - ##1 - \int_eval:n { #2 } } } \l_tmpb_bool { \bool_set_true:N \l_tmpa_bool } { \bool_if:NF \l_tmpa_bool { \int_set:Nn \l_@@_last_empty_row_int { ##1 } } } } % \end{macrocode} % Now, you determine the last empty cell in the row of number~$1$. % \begin{macrocode} \bool_set_false:N \l_tmpa_bool \int_zero_new:N \l_@@_last_empty_column_int \int_set:Nn \l_@@_last_empty_column_int { #2 } \int_step_inline:nnnn { #2 } { #4 } { #6 } { \@@_test_if_cell_in_a_block:nn { \int_eval:n { #1 } } { ##1 } \bool_lazy_or:nnTF \l_tmpb_bool { \cs_if_exist_p:c { pgf @ sh @ ns @ \@@_env: - \int_eval:n { #1 } - ##1 } } { \bool_set_true:N \l_tmpa_bool } { \bool_if:NF \l_tmpa_bool { \int_set:Nn \l_@@_last_empty_column_int { ##1 } } } } % \end{macrocode} % Now, we loop over the rows. % \begin{macrocode} \int_step_inline:nnnn { #1 } { #3 } \l_@@_last_empty_row_int { % \end{macrocode} % We treat the row number |##1| with another loop. % \begin{macrocode} \bool_set_false:N \l_tmpa_bool \int_step_inline:nnnn { #2 } { #4 } \l_@@_last_empty_column_int { \@@_test_if_cell_in_a_block:nn { ##1 } { ####1 } \bool_lazy_or:nnTF \l_tmpb_bool { \cs_if_exist_p:c { pgf @ sh @ ns @ \@@_env: - ##1 - ####1 } } { \bool_set_true:N \l_tmpa_bool } { \bool_if:NF \l_tmpa_bool { \int_set:Nn \l_@@_last_empty_column_int { ####1 } \seq_put_right:Nn \l_@@_corners_cells_seq { ##1 - ####1 } } } } } } % \end{macrocode} % % \bigskip % The following macro tests whether a cell is in (at least) one of % the blocks of the array (or in a cell with a |\diagbox|). % % The flag |\l_tmpb_bool| will be raised if the cell |#1|-|#2| is in a block (or % in a cell with a |\diagbox|). % \begin{macrocode} \cs_new_protected:Npn \@@_test_if_cell_in_a_block:nn #1 #2 { \int_set:Nn \l_tmpa_int { #1 } \int_set:Nn \l_tmpb_int { #2 } \bool_set_false:N \l_tmpb_bool \seq_map_inline:Nn \g_@@_pos_of_blocks_seq { \@@_test_if_cell_in_block:nnnnnnn \l_tmpa_int \l_tmpb_int ##1 } } % \end{macrocode} % % % \begin{macrocode} \cs_new_protected:Npn \@@_test_if_cell_in_block:nnnnnnn #1 #2 #3 #4 #5 #6 { \int_compare:nNnT { #3 } < { \@@_succ:n { #1 } } { \int_compare:nNnT { #1 } < { \@@_succ:n { #5 } } { \int_compare:nNnT { #4 } < { \@@_succ:n { #2 } } { \int_compare:nNnT { #2 } < { \@@_succ:n { #6 } } { \bool_set_true:N \l_tmpb_bool } } } } } % \end{macrocode} % % % \bigskip % \subsection*{The commands to draw dotted lines to separate columns and rows} % % These commands don't use the normal nodes, the medium nor the large nodes. % They only use the |col| nodes and the |row| nodes. % % \textbf{Horizontal dotted lines}\par\nobreak % % \medskip % The following command must \emph{not} be protected because it's meant to be % expanded in a |\noalign|. % \begin{macrocode} \cs_new:Npn \@@_hdottedline: { \noalign { \skip_vertical:N 2\l_@@_radius_dim } \@@_hdottedline_i: } % \end{macrocode} % % \medskip % On the other side, the following command should be protected. % \begin{macrocode} \cs_new_protected:Npn \@@_hdottedline_i: { % \end{macrocode} % We write in the code-after the instruction that will actually draw the % dotted line. It's not possible to draw this dotted line now because we don't % know the length of the line (we don't even know the number of columns). % \begin{macrocode} \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_hdottedline:n { \int_use:N \c@iRow } } } % \end{macrocode} % % % \medskip % The command |\@@_hdottedline:n| is the command written in the |\CodeAfter| % that will actually draw the dotted line. Its argument is the number of the row % \emph{before} which we will draw the row. % \begin{macrocode} \AtBeginDocument { % \end{macrocode} % We recall that, when externalization is used, |\tikzpicture| and % |\endtikzpicture| (or |\pgfpicture| and |\endpgfpicture|) must be directly % ``visible''. That's why we construct now a version of |\@@_hdottedline:n| with % the right environment (|\begin{pgfpicture}\end{pgfpicture}| or % |\begin{tikzpiture}...\end{tikzpicture}|). % \begin{macrocode} \cs_new_protected:Npx \@@_hdottedline:n #1 { \bool_set_true:N \exp_not:N \l_@@_initial_open_bool \bool_set_true:N \exp_not:N \l_@@_final_open_bool \c_@@_pgfortikzpicture_tl \@@_hdottedline_i:n { #1 } \c_@@_endpgfortikzpicture_tl } } % \end{macrocode} % % The following command \emph{must} be protected since it is used in the % construction of |\@@_hdottedline:n|. % \begin{macrocode} \cs_new_protected:Npn \@@_hdottedline_i:n #1 { \pgfrememberpicturepositiononpagetrue \@@_qpoint:n { row - #1 } % \end{macrocode} % We do a translation par |-\l_@@_radius_dim| because we want the dotted line to % have exactly the same position as a vertical rule drawn by ``"|"'' % (considering the rule having a width equal to the diameter of the dots). % \begin{macrocode} \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y \dim_sub:Nn \l_@@_y_initial_dim \l_@@_radius_dim \dim_set_eq:NN \l_@@_y_final_dim \l_@@_y_initial_dim % \end{macrocode} % % \medskip % The dotted line will be extended if the user uses |margin| (or |left-margin| % and |right-margin|). % % \smallskip % The aim is that, by standard the dotted line fits between square brackets % (|\hline| doesn't). % % \smallskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix} % 1 & 2 & 3 & 4 \\ % \hline % 1 & 2 & 3 & 4 \\ % \hdottedline % 1 & 2 & 3 & 4 % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix} % 1 & 2 & 3 & 4 \\ % \hline % 1 & 2 & 3 & 4 \\ % \hdottedline % 1 & 2 & 3 & 4 % \end{bNiceMatrix}$ % % \smallskip % But, if the user uses |margin|, the dotted line extends to have the same width % as a |\hline|. % % \smallskip % \begin{BVerbatim}[baseline=c,boxwidth=10cm] % \begin{bNiceMatrix}[margin] % 1 & 2 & 3 & 4 \\ % \hline % 1 & 2 & 3 & 4 \\ % \hdottedline % 1 & 2 & 3 & 4 % \end{bNiceMatrix} % \end{BVerbatim} % $\begin{bNiceMatrix}[margin] % 1 & 2 & 3 & 4 \\ % \hline % 1 & 2 & 3 & 4 \\ % \hdottedline % 1 & 2 & 3 & 4 % \end{bNiceMatrix}$ % % \medskip % \begin{macrocode} \@@_qpoint:n { col - 1 } \dim_set:Nn \l_@@_x_initial_dim { \pgf@x + % \end{macrocode} % We do a reduction by |\arraycolsep| for the environments with delimiters (and % not for the other). % \begin{macrocode} \bool_if:NTF \l_@@_NiceArray_bool \c_zero_dim \arraycolsep - \l_@@_left_margin_dim } \@@_qpoint:n { col - \@@_succ:n \c@jCol } \dim_set:Nn \l_@@_x_final_dim { \pgf@x - \bool_if:NTF \l_@@_NiceArray_bool \c_zero_dim \arraycolsep + \l_@@_right_margin_dim } % \end{macrocode} % For reasons purely aesthetic, we do an adjustment in the case of a rounded % bracket. The correction by |0.5 \l_@@_inter_dots_dim| is \emph{ad hoc} for a % better result. % \begin{macrocode} \tl_if_eq:NnF \g_@@_left_delim_tl ( { \dim_gadd:Nn \l_@@_x_initial_dim { 0.5 \l_@@_inter_dots_dim } } \tl_if_eq:NnF \g_@@_right_delim_tl ) { \dim_gsub:Nn \l_@@_x_final_dim { 0.5 \l_@@_inter_dots_dim } } % \end{macrocode} % % \medskip % Up to now, we have no option to control the style of the lines drawn by % |\hdottedline| and the specifier ``|:|'' in the preamble. That's why we impose % the style |standard|. % \begin{macrocode} \tl_set_eq:NN \l_@@_xdots_line_style_tl \c_@@_standard_tl \@@_draw_line: } % \end{macrocode} % % % % \bigskip % \textbf{Vertical dotted lines}\par\nobreak % % \medskip % \begin{macrocode} \cs_new_protected:Npn \@@_vdottedline:n #1 { \bool_set_true:N \l_@@_initial_open_bool \bool_set_true:N \l_@@_final_open_bool % \end{macrocode} % We recall that, when externalization is used, |\tikzpicture| and % |\endtikzpicture| (or |\pgfpicture| and |\endpgfpicture|) must be directly % ``visible''. % \begin{macrocode} \bool_if:NTF \c_@@_tikz_loaded_bool { \tikzpicture \@@_vdottedline_i:n { #1 } \endtikzpicture } { \pgfpicture \@@_vdottedline_i:n { #1 } \endpgfpicture } } % \end{macrocode} % % \medskip % \begin{macrocode} \cs_new_protected:Npn \@@_vdottedline_i:n #1 { % \end{macrocode} % The command |\CT@arc@| is a command of \pkg{colortbl} which sets the color of % the rules in the array. The package \pkg{nicematrix} uses it even if \pkg{colortbl} is not % loaded. % \begin{macrocode} \CT@arc@ \pgfrememberpicturepositiononpagetrue \@@_qpoint:n { col - \int_eval:n { #1 + 1 } } % \end{macrocode} % We do a translation par |-\l_@@_radius_dim| because we want the dotted line to % have exactly the same position as a vertical rule drawn by ``"|"'' % (considering the rule having a width equal to the diameter of the dots). % \begin{macrocode} \dim_set:Nn \l_@@_x_initial_dim { \pgf@x - \l_@@_radius_dim } \dim_set:Nn \l_@@_x_final_dim { \pgf@x - \l_@@_radius_dim } \@@_qpoint:n { row - 1 } % \end{macrocode} % We arbitrary decrease the height of the dotted line by a quantity equal to % |\l_@@_inter_dots_dim| in order to improve the visual impact. % \begin{macrocode} \dim_set:Nn \l_@@_y_initial_dim { \pgf@y - 0.5 \l_@@_inter_dots_dim } \@@_qpoint:n { row - \@@_succ:n \c@iRow } \dim_set:Nn \l_@@_y_final_dim { \pgf@y + 0.5 \l_@@_inter_dots_dim } % \end{macrocode} % Up to now, we have no option to control the style of the lines drawn by % |\hdottedline| and the specifier ``|:|'' in the preamble. That's why we impose % the style |standard|. % \begin{macrocode} \tl_set_eq:NN \l_@@_xdots_line_style_tl \c_@@_standard_tl \@@_draw_line: } % \end{macrocode} % % % % \bigskip % \subsection*{The environment \{NiceMatrixBlock\}} % % The following flag will be raised when all the columns of the environments of % the block must have the same width in ``auto'' mode. % \begin{macrocode} \bool_new:N \l_@@_block_auto_columns_width_bool % \end{macrocode} % % \bigskip % Up to now, there is only one option available for the environment % |{NiceMatrixBlock}|. % \begin{macrocode} \keys_define:nn { NiceMatrix / NiceMatrixBlock } { auto-columns-width .code:n = { \bool_set_true:N \l_@@_block_auto_columns_width_bool \dim_gzero_new:N \g_@@_max_cell_width_dim \bool_set_true:N \l_@@_auto_columns_width_bool } } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentEnvironment { NiceMatrixBlock } { ! O { } } { \int_gincr:N \g_@@_NiceMatrixBlock_int \dim_zero:N \l_@@_columns_width_dim \keys_set:nn { NiceMatrix / NiceMatrixBlock } { #1 } \bool_if:NT \l_@@_block_auto_columns_width_bool { \cs_if_exist:cT { @@_max_cell_width_ \int_use:N \g_@@_NiceMatrixBlock_int } { \exp_args:NNc \dim_set:Nn \l_@@_columns_width_dim { @@_max_cell_width _ \int_use:N \g_@@_NiceMatrixBlock_int } } } } % \end{macrocode} % % \medskip % At the end of the environment |{NiceMatrixBlock}|, we write in the main |aux| % file instructions for the column width of all the environments of the block % (that's why we have stored the number of the first environment of the block in % the counter |\l_@@_first_env_block_int|). % \begin{macrocode} { \bool_if:NT \l_@@_block_auto_columns_width_bool { \iow_shipout:Nn \@mainaux \ExplSyntaxOn \iow_shipout:Nx \@mainaux { \cs_gset:cpn { @@ _ max _ cell _ width _ \int_use:N \g_@@_NiceMatrixBlock_int } % \end{macrocode} % For technical reasons, we have to include the width of a potential rule on the % right side of the cells. % \begin{macrocode} { \dim_eval:n { \g_@@_max_cell_width_dim + \arrayrulewidth } } } \iow_shipout:Nn \@mainaux \ExplSyntaxOff } } % \end{macrocode} % % % % \subsection*{The extra nodes} % % First, two variants of the functions |\dim_min:nn| and |\dim_max:nn|. % \begin{macrocode} \cs_generate_variant:Nn \dim_min:nn { v n } \cs_generate_variant:Nn \dim_max:nn { v n } % \end{macrocode} % % % \bigskip % The following command is called in |\@@_use_arraybox_with_notes_c:| just % before the construction of the blocks (if the creation of medium nodes is % required, medium nodes are also created for the blocks and that construction % uses the standard medium nodes). % \begin{macrocode} \cs_new_protected:Npn \@@_create_extra_nodes: { \bool_if:nTF \l_@@_medium_nodes_bool { \bool_if:NTF \l_@@_large_nodes_bool \@@_create_medium_and_large_nodes: \@@_create_medium_nodes: } { \bool_if:NT \l_@@_large_nodes_bool \@@_create_large_nodes: } } % \end{macrocode} % % % \bigskip % We have three macros of creation of nodes: |\@@_create_medium_nodes:|, % |\@@_create_large_nodes:| and |\@@_create_medium_and_large_nodes:|. % % % \bigskip % We have to compute the mathematical coordinates of the ``medium nodes''. These % mathematical coordinates are also used to compute the mathematical coordinates % of the ``large nodes''. That's why we write a command % |\@@_computations_for_medium_nodes:| to do these computations. % % \bigskip % The command |\@@_computations_for_medium_nodes:| must be used in a % |{pgfpicture}|. % % \medskip % For each row $i$, we compute two dimensions % \texttt{l_@@_row_\textsl{i}_min_dim} and \texttt{l_@@_row_\textsl{i}_max_dim}. % The dimension \texttt{l_@@_row_\textsl{i}_min_dim} is the minimal % $y$-value of all the cells of the row~$i$. The dimension % \texttt{l_@@_row_\textsl{i}_max_dim} is the maximal $y$-value of all the cells % of the row~$i$. % % Similarly, for each column $j$, we compute two dimensions % \texttt{l_@@_column_\textsl{j}_min_dim} and % \texttt{l_@@_column_\textsl{j}_max_dim}. The dimension % \texttt{l_@@_column_\textsl{j}_min_dim} is the minimal $x$-value of all the % cells of the column~$j$. The dimension \texttt{l_@@_column_\textsl{j}_max_dim} % is the maximal $x$-value of all the cells of the column~$j$. % % Since these dimensions will be computed as maximum or minimum, we initialize % them to |\c_max_dim| or |-\c_max_dim|. % \begin{macrocode} \cs_new_protected:Npn \@@_computations_for_medium_nodes: { \int_step_variable:nnNn \l_@@_first_row_int \g_@@_row_total_int \@@_i: { \dim_zero_new:c { l_@@_row_\@@_i: _min_dim } \dim_set_eq:cN { l_@@_row_\@@_i: _min_dim } \c_max_dim \dim_zero_new:c { l_@@_row_\@@_i: _max_dim } \dim_set:cn { l_@@_row_\@@_i: _max_dim } { - \c_max_dim } } \int_step_variable:nnNn \l_@@_first_col_int \g_@@_col_total_int \@@_j: { \dim_zero_new:c { l_@@_column_\@@_j: _min_dim } \dim_set_eq:cN { l_@@_column_\@@_j: _min_dim } \c_max_dim \dim_zero_new:c { l_@@_column_\@@_j: _max_dim } \dim_set:cn { l_@@_column_\@@_j: _max_dim } { - \c_max_dim } } % \end{macrocode} % We begin the two nested loops over the rows and the columns of the array. % \begin{macrocode} \int_step_variable:nnNn \l_@@_first_row_int \g_@@_row_total_int \@@_i: { \int_step_variable:nnNn \l_@@_first_col_int \g_@@_col_total_int \@@_j: % \end{macrocode} % If the cell ($i$-$j$) is empty or an implicit cell (that is to say a cell % after implicit ampersands |&|) we don't update the dimensions we want to % compute. % \begin{macrocode} { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - \@@_i: - \@@_j: } % \end{macrocode} % We retrieve the coordinates of the anchor |south west| of the (normal) node of % the cell ($i$-$j$). They will be stored in |\pgf@x| and |\pgf@y|. % \begin{macrocode} { \pgfpointanchor { \@@_env: - \@@_i: - \@@_j: } { south~west } \dim_set:cn { l_@@_row_\@@_i: _min_dim} { \dim_min:vn { l_@@_row _ \@@_i: _min_dim } \pgf@y } \seq_if_in:NxF \g_@@_multicolumn_cells_seq { \@@_i: - \@@_j: } { \dim_set:cn { l_@@_column _ \@@_j: _min_dim} { \dim_min:vn { l_@@_column _ \@@_j: _min_dim } \pgf@x } } % \end{macrocode} % We retrieve the coordinates of the anchor |north east| of the (normal) node of % the cell ($i$-$j$). They will be stored in |\pgf@x| and |\pgf@y|. % \begin{macrocode} \pgfpointanchor { \@@_env: - \@@_i: - \@@_j: } { north~east } \dim_set:cn { l_@@_row _ \@@_i: _ max_dim } { \dim_max:vn { l_@@_row _ \@@_i: _ max_dim } \pgf@y } \seq_if_in:NxF \g_@@_multicolumn_cells_seq { \@@_i: - \@@_j: } { \dim_set:cn { l_@@_column _ \@@_j: _ max_dim } { \dim_max:vn { l_@@_column _ \@@_j: _max_dim } \pgf@x } } } } } % \end{macrocode} % Now, we have to deal with empty rows or empty columns since we don't have % created nodes in such rows and columns. % \begin{macrocode} \int_step_variable:nnNn \l_@@_first_row_int \g_@@_row_total_int \@@_i: { \dim_compare:nNnT { \dim_use:c { l_@@_row _ \@@_i: _ min _ dim } } = \c_max_dim { \@@_qpoint:n { row - \@@_i: - base } \dim_set:cn { l_@@_row _ \@@_i: _ max _ dim } \pgf@y \dim_set:cn { l_@@_row _ \@@_i: _ min _ dim } \pgf@y } } \int_step_variable:nnNn \l_@@_first_col_int \g_@@_col_total_int \@@_j: { \dim_compare:nNnT { \dim_use:c { l_@@_column _ \@@_j: _ min _ dim } } = \c_max_dim { \@@_qpoint:n { col - \@@_j: } \dim_set:cn { l_@@_column _ \@@_j: _ max _ dim } \pgf@y \dim_set:cn { l_@@_column _ \@@_j: _ min _ dim } \pgf@y } } } % \end{macrocode} % % % \bigskip % Here is the command |\@@_create_medium_nodes:|. When this command is used, the % ``medium nodes'' are created. % % \begin{macrocode} \cs_new_protected:Npn \@@_create_medium_nodes: { \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \@@_computations_for_medium_nodes: % \end{macrocode} % Now, we can create the ``medium nodes''. We use a command |\@@_create_nodes:| % because this command will also be used for the creation of the ``large nodes''. % \begin{macrocode} \tl_set:Nn \l_@@_suffix_tl { -medium } \@@_create_nodes: \endpgfpicture } % \end{macrocode} % % % \medskip % The command |\@@_create_large_nodes:| must be used when we want to create only % the ``large nodes'' and not the medium ones\footnote{If we want to create % both, we have to use |\@@_create_medium_and_large_nodes:|}. However, the % computation of the mathematical coordinates of the ``large nodes'' needs the % computation of the mathematical coordinates of the ``medium nodes''. Hence, we % use first |\@@_computations_for_medium_nodes:| and then the command % |\@@_computations_for_large_nodes:|. % \begin{macrocode} \cs_new_protected:Npn \@@_create_large_nodes: { \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \@@_computations_for_medium_nodes: \@@_computations_for_large_nodes: \tl_set:Nn \l_@@_suffix_tl { - large } \@@_create_nodes: \endpgfpicture } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_create_medium_and_large_nodes: { \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \@@_computations_for_medium_nodes: % \end{macrocode} % Now, we can create the ``medium nodes''. We use a command |\@@_create_nodes:| % because this command will also be used for the creation of the ``large nodes''. % \begin{macrocode} \tl_set:Nn \l_@@_suffix_tl { - medium } \@@_create_nodes: \@@_computations_for_large_nodes: \tl_set:Nn \l_@@_suffix_tl { - large } \@@_create_nodes: \endpgfpicture } % \end{macrocode} % % % \bigskip % For ``large nodes'', the exterior rows and columns don't interfer. That's why % the loop over the columns will start at 1 and stop at $|\c@jCol|$ (and not % |\g_@@_col_total_int|). Idem for the rows. % \begin{macrocode} \cs_new_protected:Npn \@@_computations_for_large_nodes: { \int_set:Nn \l_@@_first_row_int 1 \int_set:Nn \l_@@_first_col_int 1 % \end{macrocode} % We have to change the values of all the dimensions % \texttt{l_@@_row_\textsl{i}_min_dim}, \texttt{l_@@_row_\textsl{i}_max_dim}, % \texttt{l_@@_column_\textsl{j}_min_dim} and % \texttt{l_@@_column_\textsl{j}_max_dim}. % \begin{macrocode} \int_step_variable:nNn { \c@iRow - 1 } \@@_i: { \dim_set:cn { l_@@_row _ \@@_i: _ min _ dim } { ( \dim_use:c { l_@@_row _ \@@_i: _ min _ dim } + \dim_use:c { l_@@_row _ \@@_succ:n \@@_i: _ max _ dim } ) / 2 } \dim_set_eq:cc { l_@@_row _ \@@_succ:n \@@_i: _ max _ dim } { l_@@_row_\@@_i: _min_dim } } \int_step_variable:nNn { \c@jCol - 1 } \@@_j: { \dim_set:cn { l_@@_column _ \@@_j: _ max _ dim } { ( \dim_use:c { l_@@_column _ \@@_j: _ max _ dim } + \dim_use:c { l_@@_column _ \@@_succ:n \@@_j: _ min _ dim } ) / 2 } \dim_set_eq:cc { l_@@_column _ \@@_succ:n \@@_j: _ min _ dim } { l_@@_column _ \@@_j: _ max _ dim } } % \end{macrocode} % Here, we have to use |\dim_sub:cn| because of the number 1 in the name. % \begin{macrocode} \dim_sub:cn { l_@@_column _ 1 _ min _ dim } \l_@@_left_margin_dim \dim_add:cn { l_@@_column _ \int_use:N \c@jCol _ max _ dim } \l_@@_right_margin_dim } % \end{macrocode} % % % % \bigskip % The command |\@@_create_nodes:| is used twice: for the construction % of the ``medium nodes'' and for the construction of the ``large nodes''. The % nodes are constructed with the value of all the dimensions % \texttt{l_@@_row_\textsl{i}_min_dim}, \texttt{l_@@_row_\textsl{i}_max_dim}, % \texttt{l_@@_column_\textsl{j}_min_dim} and % \texttt{l_@@_column_\textsl{j}_max_dim}. Between the construction of the % ``medium nodes'' and the ``large nodes'', the values of these dimensions are % changed. % % The function also uses |\l_@@_suffix_tl| (|-medium| or |-large|). % \begin{macrocode} \cs_new_protected:Npn \@@_create_nodes: { \int_step_variable:nnNn \l_@@_first_row_int \g_@@_row_total_int \@@_i: { \int_step_variable:nnNn \l_@@_first_col_int \g_@@_col_total_int \@@_j: { % \end{macrocode} % We draw the rectangular node for the cell (|\@@_i|-|\@@_j|). % \begin{macrocode} \@@_pgf_rect_node:nnnnn { \@@_env: - \@@_i: - \@@_j: \l_@@_suffix_tl } { \dim_use:c { l_@@_column_ \@@_j: _min_dim } } { \dim_use:c { l_@@_row_ \@@_i: _min_dim } } { \dim_use:c { l_@@_column_ \@@_j: _max_dim } } { \dim_use:c { l_@@_row_ \@@_i: _max_dim } } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - \@@_i: - \@@_j: \l_@@_suffix_tl } { \@@_env: - \@@_i: - \@@_j: \l_@@_suffix_tl } } } } % \end{macrocode} % Now, we create the nodes for the cells of the |\multicolumn|. We recall that % we have stored in |\g_@@_multicolumn_cells_seq| the list of the cells where a % |\multicolumn{|$n$|}{...}{...}| with $n$>1 was issued and in % |\g_@@_multicolumn_sizes_seq| the correspondant values of $n$. % \begin{macrocode} \seq_mapthread_function:NNN \g_@@_multicolumn_cells_seq \g_@@_multicolumn_sizes_seq \@@_node_for_multicolumn:nn } % \end{macrocode} % % % \bigskip % \begin{macrocode} \cs_new_protected:Npn \@@_extract_coords_values: #1 - #2 \q_stop { \cs_set_nopar:Npn \@@_i: { #1 } \cs_set_nopar:Npn \@@_j: { #2 } } % \end{macrocode} % % The command |\@@_node_for_multicolumn:nn| takes two arguments. The first is % the position of the cell where the command |\multicolumn{|$n$|}{...}{...}| was % issued in the format $i$|-|$j$ and the second is the value of~$n$ (the length % of the ``multi-cell''). % \begin{macrocode} \cs_new_protected:Npn \@@_node_for_multicolumn:nn #1 #2 { \@@_extract_coords_values: #1 \q_stop \@@_pgf_rect_node:nnnnn { \@@_env: - \@@_i: - \@@_j: \l_@@_suffix_tl } { \dim_use:c { l_@@_column _ \@@_j: _ min _ dim } } { \dim_use:c { l_@@_row _ \@@_i: _ min _ dim } } { \dim_use:c { l_@@_column _ \int_eval:n { \@@_j: +#2-1 } _ max _ dim } } { \dim_use:c { l_@@_row _ \@@_i: _ max _ dim } } \str_if_empty:NF \l_@@_name_str { \pgfnodealias { \l_@@_name_str - \@@_i: - \@@_j: \l_@@_suffix_tl } { \int_use:N \g_@@_env_int - \@@_i: - \@@_j: \l_@@_suffix_tl} } } % \end{macrocode} % % \bigskip % \subsection*{The blocks} % % The code deals with the command |\Block|. This command has no direct link with % the environment |{NiceMatrixBlock}|. % % \bigskip % The options of the command |\Block| will be analyzed first in the cell of the % array (and once again when the block will be put in the array). % Here is the set of keys for the first pass. % \begin{macrocode} \keys_define:nn { NiceMatrix / Block / FirstPass } { l .code:n = \str_set:Nn \l_@@_hpos_block_str l , l .value_forbidden:n = true , r .code:n = \str_set:Nn \l_@@_hpos_block_str r , r .value_forbidden:n = true , c .code:n = \str_set:Nn \l_@@_hpos_block_str c , c .value_forbidden:n = true , L .code:n = \str_set:Nn \l_@@_hpos_block_str l , L .value_forbidden:n = true , R .code:n = \str_set:Nn \l_@@_hpos_block_str r , R .value_forbidden:n = true , C .code:n = \str_set:Nn \l_@@_hpos_block_str c , C .value_forbidden:n = true , t .code:n = \str_set:Nn \l_@@_vpos_of_block_tl t , t .value_forbidden:n = true , b .code:n = \str_set:Nn \l_@@_vpos_of_block_tl b , b .value_forbidden:n = true , color .tl_set:N = \l_@@_color_tl , color .value_required:n = true } % \end{macrocode} % % % The following command |\@@_Block:| will be linked to |\Block| in the % environments of \pkg{nicematrix}. We define it with % |\NewExpandableDocumentCommand| because it has an optional argument between % |<| and |>|. It's mandatory to use an expandable command. % % \begin{macrocode} \NewExpandableDocumentCommand \@@_Block: { O { } m D < > { } m } { % \end{macrocode} % If the first mandatory argument of the command (which is the size of the block % with the syntax $i$|-|$j$) has not be provided by the user, you use |1-1| % (that is to say a block of only one cell). % \begin{macrocode} \peek_remove_spaces:n { \tl_if_blank:nTF { #2 } { \@@_Block_i 1-1 \q_stop } { \@@_Block_i #2 \q_stop } { #1 } { #3 } { #4 } } } % \end{macrocode} % % \medskip % With the following construction, we extract the values of $i$ and $j$ in the % first mandatory argument of the command. % \begin{macrocode} \cs_new:Npn \@@_Block_i #1-#2 \q_stop { \@@_Block_ii:nnnnn { #1 } { #2 } } % \end{macrocode} % % \medskip % Now, the arguments have been extracted: |#1| is $i$ (the number of rows of the % block), |#2| is $j$ (the number of columns of the block), |#3| is the list of % key-values, |#4| are the tokens to put before the math mode and the beginning % of the small array of the block and |#5| is the label of the block. % \begin{macrocode} \cs_new_protected:Npn \@@_Block_ii:nnnnn #1 #2 #3 #4 #5 { % \end{macrocode} % % \medskip % We recall that |#1| and |#2| have been extracted from the first mandatory % argument of |\Block| (which is of the syntax $i$|-|$j$). However, the user is % allowed to omit $i$ or $j$ (or both). We detect that situation by replacing a % missing value by 100 (it's a convention: when the block will actually be drawn % these values will be detected and interpreted as \emph{maximal possible % value} according to the actual size of the array). % \begin{macrocode} \bool_lazy_or:nnTF { \tl_if_blank_p:n { #1 } } { \str_if_eq_p:nn { #1 } { * } } { \int_set:Nn \l_tmpa_int { 100 } } { \int_set:Nn \l_tmpa_int { #1 } } \bool_lazy_or:nnTF { \tl_if_blank_p:n { #2 } } { \str_if_eq_p:nn { #2 } { * } } { \int_set:Nn \l_tmpb_int { 100 } } { \int_set:Nn \l_tmpb_int { #2 } } % \end{macrocode} % % \medskip % If the block is mono-column. % \begin{macrocode} \int_compare:nNnTF \l_tmpb_int = 1 { \str_if_empty:NTF \l_@@_hpos_cell_str { \str_set:Nn \l_@@_hpos_block_str c } { \str_set_eq:NN \l_@@_hpos_block_str \l_@@_hpos_cell_str } } { \str_set:Nn \l_@@_hpos_block_str c } % \end{macrocode} % The value of |\l_@@_hpos_block_str| may be modified by the keys of the % command |\Block| that we will analyze now. % % \medskip % \begin{macrocode} \keys_set_known:nn { NiceMatrix / Block / FirstPass } { #3 } % \end{macrocode} % % \begin{macrocode} \tl_set:Nx \l_tmpa_tl { { \int_use:N \c@iRow } { \int_use:N \c@jCol } { \int_eval:n { \c@iRow + \l_tmpa_int - 1 } } { \int_eval:n { \c@jCol + \l_tmpb_int - 1 } } } % \end{macrocode} % Now, |\l_tmpa_tl| contains an ``object'' corresponding to the position of the % block with four components, each of them surrounded by curly brackets: % % |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}|. % % % \medskip % If the block is mono-column or mono-row, we have a special treatment. That's % why we have two macros: |\@@_Block_iv:nnnnn| and |\@@_Block_v:nnnnn| (the five % arguments of those macros are provided by curryfication). % \begin{macrocode} \bool_if:nTF { ( \int_compare_p:nNn { \l_tmpa_int } = 1 || \int_compare_p:nNn { \l_tmpb_int } = 1 ) && ! \tl_if_empty_p:n { #5 } % \end{macrocode} % For the blocks mono-column, we will compose right now in a box in order to % compute its width and take that width into account for the width of the % column. However, if the column is a |X| column, we should not do that since % the width is determined by another way. This should be the same for the |p|, % |m| and |b| columns and we should modify that point. However, for the |X| % column, it's imperative. Otherwise, the process for the determination of the % widths of the columns will be wrong. % \begin{macrocode} && ! \l_@@_X_column_bool } { \exp_args:Nxx \@@_Block_iv:nnnnn } { \exp_args:Nxx \@@_Block_v:nnnnn } { \l_tmpa_int } { \l_tmpb_int } { #3 } { #4 } { #5 } } % \end{macrocode} % % % \bigskip % The following macro is for the case of a |\Block| which is mono-row or % mono-column (or both). In that case, the content of the block is composed % right now in a box (because we have to take into account the dimensions of % that box for the width of the current column or the height and the depth of the % current row). However, that box will be put in the array \emph{after the % construction of the array} (by using \textsc{pgf}). % \begin{macrocode} \cs_new_protected:Npn \@@_Block_iv:nnnnn #1 #2 #3 #4 #5 { \int_gincr:N \g_@@_block_box_int \cs_set_protected_nopar:Npn \diagbox ##1 ##2 { \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_actually_diagbox:nnnnnn { \int_use:N \c@iRow } { \int_use:N \c@jCol } { \int_eval:n { \c@iRow + #1 - 1 } } { \int_eval:n { \c@jCol + #2 - 1 } } { \exp_not:n { ##1 } } { \exp_not:n { ##2 } } } } \box_gclear_new:c { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } \hbox_gset:cn { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } { % \end{macrocode} % For a mono-column block, if the user has specified a color for the column in % the preamble of the array, we want to fix that color in the box we construct. % We do that with |\set@color| and not |\color_ensure_current:| (in order to use % |\color_ensure_current:| safely, you should load \pkg{l3backend} before the % |\documentclass| with |\RequirePackage{expl3}|). % \begin{macrocode} \tl_if_empty:NTF \l_@@_color_tl { \int_compare:nNnT { #2 } = 1 \set@color } { \color { \l_@@_color_tl } } % \end{macrocode} % If the block is mono-row, we use |\g_@@_row_style_tl| even if it has yet been % used in the beginning of the cell where the command |\Block| has been issued % because we want to be able to take into account a potential instruction of % color of the font in |\g_@@_row_style_tl|. % \begin{macrocode} \int_compare:nNnT { #1 } = 1 \g_@@_row_style_tl \group_begin: \cs_set:Npn \arraystretch { 1 } \dim_set_eq:NN \extrarowheight \c_zero_dim #4 % \end{macrocode} % If the box is rotated (the key |\rotate| may be in the previous |#4|), the % tabular used for the content of the cell will be constructed with a format % |c|. In the other cases, the tabular will be constructed with a format equal % to the key of position of the box. In other words: the alignement internal to % the tabular is the same as the external alignment of the tabular (that is to % say the position of the block in its zone of merged cells). % \begin{macrocode} \bool_if:NT \g_@@_rotate_bool { \str_set:Nn \l_@@_hpos_block_str c } \bool_if:NTF \l_@@_NiceTabular_bool { \bool_lazy_and:nnTF { \int_compare_p:nNn { #2 } = 1 } { \dim_compare_p:n { \l_@@_col_width_dim >= \c_zero_dim } } % \end{macrocode} % When the block is mono-column in a column with a fixed width (eg |p{3cm}|). % \begin{macrocode} { \begin { minipage } [ l_@@_vpos_of_block_tl ] { \l_@@_col_width_dim } \str_case:Vn \l_@@_hpos_block_str { c \centering r \raggedleft l \raggedright } #5 \end { minipage } } { \use:x { \exp_not:N \begin { tabular } [ \l_@@_vpos_of_block_tl ] { @ { } \l_@@_hpos_block_str @ { } } } #5 \end { tabular } } } { \c_math_toggle_token \use:x { \exp_not:N \begin { array } [ \l_@@_vpos_of_block_tl ] { @ { } \l_@@_hpos_block_str @ { } } } #5 \end { array } \c_math_toggle_token } \group_end: } \bool_if:NT \g_@@_rotate_bool { \box_grotate:cn { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } { 90 } \bool_gset_false:N \g_@@_rotate_bool } % \end{macrocode} % If we are in a mono-column block, we take into account the width of that block % for the width of the column. % \begin{macrocode} \int_compare:nNnT { #2 } = 1 { \dim_gset:Nn \g_@@_blocks_wd_dim { \dim_max:nn \g_@@_blocks_wd_dim { \box_wd:c { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } } } } % \end{macrocode} % If we are in a mono-row block, we take into account the height and the % depth of that block for the height and the depth of the row. % \begin{macrocode} \int_compare:nNnT { #1 } = 1 { \dim_gset:Nn \g_@@_blocks_ht_dim { \dim_max:nn \g_@@_blocks_ht_dim { \box_ht:c { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } } } \dim_gset:Nn \g_@@_blocks_dp_dim { \dim_max:nn \g_@@_blocks_dp_dim { \box_dp:c { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } } } } \seq_gput_right:Nx \g_@@_blocks_seq { \l_tmpa_tl % \end{macrocode} % In the list of options |#3|, maybe there is a key for the horizontal alignment % (|l|, |r| or |c|). In that case, that key has been read and stored in % |\l_@@_hpos_block_str|. However, maybe there were no key of the horizontal % alignement and that's why we put a key corresponding to the value of % |\l_@@_hpos_block_str|, which is fixed by the type of current column. % \begin{macrocode} { \exp_not:n { #3 } , \l_@@_hpos_block_str } { \box_use_drop:c { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } } } } % \end{macrocode} % % \bigskip % The following macro is for the standard case, where the block is not mono-row % and not mono-column. In that case, the content of the block is \emph{not} % composed right now in a box. The composition in a box will be done further, % just after the construction of the array. % \begin{macrocode} \cs_new_protected:Npn \@@_Block_v:nnnnn #1 #2 #3 #4 #5 { \seq_gput_right:Nx \g_@@_blocks_seq { \l_tmpa_tl { \exp_not:n { #3 } } \exp_not:n { { \bool_if:NTF \l_@@_NiceTabular_bool { \group_begin: \cs_set:Npn \arraystretch { 1 } \dim_set_eq:NN \extrarowheight \c_zero_dim #4 % \end{macrocode} % If the box is rotated (the key |\rotate| may be in the previous |#4|), the % tabular used for the content of the cell will be constructed with a format % |c|. In the other cases, the tabular will be constructed with a format equal % to the key of position of the box. In other words: the alignement internal to % the tabular is the same as the external alignment of the tabular (that is to % say the position of the block in its zone of merged cells). % \begin{macrocode} \bool_if:NT \g_@@_rotate_bool { \str_set:Nn \l_@@_hpos_block_str c } \use:x { \exp_not:N \begin { tabular } [ \l_@@_vpos_of_block_tl ] { @ { } \l_@@_hpos_block_str @ { } } } #5 \end { tabular } \group_end: } { \group_begin: \cs_set:Npn \arraystretch { 1 } \dim_set_eq:NN \extrarowheight \c_zero_dim #4 \bool_if:NT \g_@@_rotate_bool { \str_set:Nn \l_@@_hpos_block_str c } \c_math_toggle_token \use:x { \exp_not:N \begin { array } [ \l_@@_vpos_of_block_tl ] { @ { } \l_@@_hpos_block_str @ { } } } #5 \end { array } \c_math_toggle_token \group_end: } } } } } % \end{macrocode} % % \bigskip % We recall that the options of the command |\Block| are analyzed twice: first % in the cell of the array and once again when the block will be put in the % array \emph{after the construction of the array} (by using \textsc{pgf}). % % \medskip % \begin{macrocode} \keys_define:nn { NiceMatrix / Block / SecondPass } { tikz .code:n = \bool_if:NTF \c_@@_tikz_loaded_bool { \seq_put_right:Nn \l_@@_tikz_seq { { #1 } } } { \@@_error:n { tikz~key~without~tikz } } , tikz .value_required:n = true , fill .tl_set:N = \l_@@_fill_tl , fill .value_required:n = true , draw .tl_set:N = \l_@@_draw_tl , draw .default:n = default , rounded-corners .dim_set:N = \l_@@_rounded_corners_dim , rounded-corners .default:n = 4 pt , color .code:n = \color { #1 } \tl_set:Nn \l_@@_draw_tl { #1 } , color .value_required:n = true , borders .clist_set:N = \l_@@_borders_clist , borders .value_required:n = true , hvlines .bool_set:N = \l_@@_hvlines_block_bool , hvlines .default:n = true , line-width .dim_set:N = \l_@@_line_width_dim , line-width .value_required:n = true , l .code:n = \str_set:Nn \l_@@_hpos_block_str l , l .value_forbidden:n = true , r .code:n = \str_set:Nn \l_@@_hpos_block_str r , r .value_forbidden:n = true , c .code:n = \str_set:Nn \l_@@_hpos_block_str c , c .value_forbidden:n = true , L .code:n = \str_set:Nn \l_@@_hpos_block_str l \bool_set_true:N \l_@@_hpos_of_block_cap_bool , L .value_forbidden:n = true , R .code:n = \str_set:Nn \l_@@_hpos_block_str r \bool_set_true:N \l_@@_hpos_of_block_cap_bool , R .value_forbidden:n = true , C .code:n = \str_set:Nn \l_@@_hpos_block_str c \bool_set_true:N \l_@@_hpos_of_block_cap_bool , C .value_forbidden:n = true , t .code:n = \str_set:Nn \l_@@_vpos_of_block_tl t , t .value_forbidden:n = true , b .code:n = \str_set:Nn \l_@@_vpos_of_block_tl b , b .value_forbidden:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~Block } } % \end{macrocode} % % \bigskip % The command |\@@_draw_blocks:| will draw all the blocks. This command is used % after the construction of the array. We have to revert to a clean version of % |\ialign| because there may be tabulars in the |\Block| instructions that will % be composed now. % \begin{macrocode} \cs_new_protected:Npn \@@_draw_blocks: { \cs_set_eq:NN \ialign \@@_old_ialign: \seq_map_inline:Nn \g_@@_blocks_seq { \@@_Block_iv:nnnnnn ##1 } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_Block_iv:nnnnnn #1 #2 #3 #4 #5 #6 { % \end{macrocode} % The integer |\l_@@_last_row_int| will be the last row of the block and % |\l_@@_last_col_int| its last column. % \begin{macrocode} \int_zero_new:N \l_@@_last_row_int \int_zero_new:N \l_@@_last_col_int % \end{macrocode} % % We remind that the first mandatory argument of the command |\Block| is the % size of the block with the special format $i$|-|$j$. However, the user is % allowed to omit $i$ or $j$ (or both). This will be interpreted as: the last % row (resp. column) of the block will be the last row (resp. column) of the % block (without the potential exterior row---resp. column---of the array). By % convention, this is stored in |\g_@@_blocks_seq| as a number of rows (resp. % columns) for the block equal to 100. That's what we detect now. % \begin{macrocode} \int_compare:nNnTF { #3 } > { 99 } { \int_set_eq:NN \l_@@_last_row_int \c@iRow } { \int_set:Nn \l_@@_last_row_int { #3 } } \int_compare:nNnTF { #4 } > { 99 } { \int_set_eq:NN \l_@@_last_col_int \c@jCol } { \int_set:Nn \l_@@_last_col_int { #4 } } \int_compare:nNnTF \l_@@_last_col_int > \g_@@_col_total_int { \int_compare:nTF { \l_@@_last_col_int <= \g_@@_static_num_of_col_int } { \msg_error:nnnn { nicematrix } { Block~too~large~2 } { #1 } { #2 } \@@_msg_redirect_name:nn { Block~too~large~2 } { none } \group_begin: \globaldefs = 1 \@@_msg_redirect_name:nn { columns~not~used } { none } \group_end: } { \msg_error:nnnn { nicematrix } { Block~too~large~1 } { #1 } { #2 } } } { \int_compare:nNnTF \l_@@_last_row_int > \g_@@_row_total_int { \msg_error:nnnn { nicematrix } { Block~too~large~1 } { #1 } { #2 } } { \@@_Block_v:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } } } } % \end{macrocode} % % \begin{macrocode} \cs_new_protected:Npn \@@_Block_v:nnnnnn #1 #2 #3 #4 #5 #6 { % \end{macrocode} % The group is for the keys. % \begin{macrocode} \group_begin: \keys_set:nn { NiceMatrix / Block / SecondPass } { #5 } % \end{macrocode} % % \begin{macrocode} \bool_if:NTF \l_@@_hvlines_block_bool { \tl_gput_right:Nx \g_nicematrix_code_after_tl { \@@_hvlines_block:nnn { \exp_not:n { #5 } } { #1 - #2 } { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } } } { % \end{macrocode} % The sequence of the positions of the blocks (excepted the blocks with the key % |hvlines|) will be used when drawing the rules (in fact, there is also the % |\multicolumn| and the |\diagbox| in that sequence). % \begin{macrocode} \seq_gput_left:Nn \g_@@_pos_of_blocks_seq { { #1 } { #2 } { #3 } { #4 } } } % \end{macrocode} % % \begin{macrocode} \tl_if_empty:NF \l_@@_draw_tl { \tl_gput_right:Nx \g_nicematrix_code_after_tl { \@@_stroke_block:nnn { \exp_not:n { #5 } } { #1 - #2 } { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } } \seq_gput_right:Nn \g_@@_pos_of_stroken_blocks_seq { { #1 } { #2 } { #3 } { #4 } } } % \end{macrocode} % % \begin{macrocode} \clist_if_empty:NF \l_@@_borders_clist { \tl_gput_right:Nx \g_nicematrix_code_after_tl { \@@_stroke_borders_block:nnn { \exp_not:n { #5 } } { #1 - #2 } { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } } } % \end{macrocode} % % \begin{macrocode} \tl_if_empty:NF \l_@@_fill_tl { % \end{macrocode} % The command |\@@_extract_brackets| will extract the potential specification of % color space at the beginning of |\l_@@_fill_tl| and store it in |\l_tmpa_tl| % and store the color itself in |\l_tmpb_tl|. % \begin{macrocode} \exp_last_unbraced:NV \@@_extract_brackets \l_@@_fill_tl \q_stop \tl_gput_right:Nx \g_nicematrix_code_before_tl { \exp_not:N \roundedrectanglecolor [ \l_tmpa_tl ] { \exp_not:V \l_tmpb_tl } { #1 - #2 } { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } { \dim_use:N \l_@@_rounded_corners_dim } } } % \end{macrocode} % % \begin{macrocode} \seq_if_empty:NF \l_@@_tikz_seq { \tl_gput_right:Nx \g_nicematrix_code_before_tl { \@@_block_tikz:nnnnn { #1 } { #2 } { \int_use:N \l_@@_last_row_int } { \int_use:N \l_@@_last_col_int } { \seq_use:Nn \l_@@_tikz_seq { , } } } } % \end{macrocode} % % \medskip % \begin{macrocode} \cs_set_protected_nopar:Npn \diagbox ##1 ##2 { \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_actually_diagbox:nnnnnn { #1 } { #2 } { \int_use:N \l_@@_last_row_int } { \int_use:N \l_@@_last_col_int } { \exp_not:n { ##1 } } { \exp_not:n { ##2 } } } } % \end{macrocode} % % \medskip % \begin{macrocode} \hbox_set:Nn \l_@@_cell_box { \set@color #6 } \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: % \end{macrocode} % % \bigskip % Let's consider the following |{NiceTabular}|. Because of the instruction % |!{\hspace{1cm}}| in the preamble which increases the space between the % columns (by adding, in fact, that space to the previous column, that is to say % the second column of the tabular), we will create \emph{two} nodes relative to % the block: the node |1-1-block| and the node |1-1-block-short|. % % \begin{Verbatim} % \begin{NiceTabular}{cc!{\hspace{1cm}}c} % \Block{2-2}{our block} & & one \\ % & & two \\ % three & four & five \\ % six & seven & eight \\ % \end{NiceTabular} % \end{Verbatim} % % \tikzset{highlight/.style={rectangle, % fill=red!15, % blend mode = multiply, % rounded corners = 0pt, % inner sep=0pt, % fit = #1}} % % \begin{tabular}{c!{\hspace{1cm}}c} % We highlight the node |1-1-block| % & We highlight the node |1-1-block-short| \\[2mm] % \begin{NiceTabular}{cc!{\hspace{1cm}}c} % \Block{2-2}{our block} & & one \\ % & & two \\ % three & four & five \\ % six & seven & eight \\ % \CodeAfter % \tikz \node [highlight = (1-1-block)] { } ; % \end{NiceTabular} % & % \begin{NiceTabular}{cc!{\hspace{1cm}}c} % \Block{2-2}{our block} & & one \\ % & & two \\ % three & four & five \\ % six & seven & eight \\ % \CodeAfter % \tikz \node [highlight = (1-1-block-short)] { } ; % \end{NiceTabular} % \end{tabular} % % % \bigskip % The construction of the node corresponding to the merged cells. % \begin{macrocode} \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \@@_qpoint:n { row - #1 } \dim_set_eq:NN \l_tmpa_dim \pgf@y \@@_qpoint:n { col - #2 } \dim_set_eq:NN \l_tmpb_dim \pgf@x \@@_qpoint:n { row - \@@_succ:n { \l_@@_last_row_int } } \dim_set_eq:NN \l_tmpc_dim \pgf@y \@@_qpoint:n { col - \@@_succ:n { \l_@@_last_col_int } } \dim_set_eq:NN \l_tmpd_dim \pgf@x % \end{macrocode} % % We construct the node for the block with the name |(#1-#2-block)|. % % The function |\@@_pgf_rect_node:nnnnn| takes in as arguments the name of the node % and the four coordinates of two opposite corner points of the rectangle. % \begin{macrocode} \begin { pgfscope } \@@_pgf_rect_node:nnnnn { \@@_env: - #1 - #2 - block } \l_tmpb_dim \l_tmpa_dim \l_tmpd_dim \l_tmpc_dim \end { pgfscope } % \end{macrocode} % % \medskip % Now, we create the ``short node'' which, in general, will be used to put the % label (that is to say the content of the node). However, if one the keys |L|, |C| or % |R| is used (that information is provided by the boolean % |\l_@@_hpos_of_block_cap_bool|), we don't need to create that node since the % normal node is used to put the label. % % \begin{macrocode} \bool_if:NF \l_@@_hpos_of_block_cap_bool { \dim_set_eq:NN \l_tmpb_dim \c_max_dim % \end{macrocode} % The short node is constructed by taking into account the \emph{contents} of % the columns involved in at least one cell of the block. That's why we have to % do a loop over the rows of the array. % \begin{macrocode} \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { % \end{macrocode} % We recall that, when a cell is empty, no (normal) node is created in that % cell. That's why we test the existence of the node before using it. % \begin{macrocode} \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - #2 } { \seq_if_in:NnF \g_@@_multicolumn_cells_seq { ##1 - #2 } { \pgfpointanchor { \@@_env: - ##1 - #2 } { west } \dim_set:Nn \l_tmpb_dim { \dim_min:nn \l_tmpb_dim \pgf@x } } } } % \end{macrocode} % If all the cells of the column were empty, |\l_tmpb_dim| has still the same % value |\c_max_dim|. In that case, you use for |\l_tmpb_dim| the value of the % position of the vertical rule. % \begin{macrocode} \dim_compare:nNnT \l_tmpb_dim = \c_max_dim { \@@_qpoint:n { col - #2 } \dim_set_eq:NN \l_tmpb_dim \pgf@x } \dim_set:Nn \l_tmpd_dim { - \c_max_dim } \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - \int_use:N \l_@@_last_col_int } { \seq_if_in:NnF \g_@@_multicolumn_cells_seq { ##1 - #2 } { \pgfpointanchor { \@@_env: - ##1 - \int_use:N \l_@@_last_col_int } { east } \dim_set:Nn \l_tmpd_dim { \dim_max:nn \l_tmpd_dim \pgf@x } } } } \dim_compare:nNnT \l_tmpd_dim = { - \c_max_dim } { \@@_qpoint:n { col - \@@_succ:n { \l_@@_last_col_int } } \dim_set_eq:NN \l_tmpd_dim \pgf@x } \@@_pgf_rect_node:nnnnn { \@@_env: - #1 - #2 - block - short } \l_tmpb_dim \l_tmpa_dim \l_tmpd_dim \l_tmpc_dim } % \end{macrocode} % % \medskip % If the creation of the ``medium nodes'' is required, we create a ``medium % node'' for the block. The function |\@@_pgf_rect_node:nnn| takes in as % arguments the name of the node and two \textsc{pgf} points. % \begin{macrocode} \bool_if:NT \l_@@_medium_nodes_bool { \@@_pgf_rect_node:nnn { \@@_env: - #1 - #2 - block - medium } { \pgfpointanchor { \@@_env: - #1 - #2 - medium } { north~west } } { \pgfpointanchor { \@@_env: - \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int - medium } { south~east } } } % \end{macrocode} % \medskip % Now, we will put the label of the block beginning with the case of a |\Block| % of one row. % \begin{macrocode} \int_compare:nNnTF { #1 } = { #3 } { % \end{macrocode} % We take into account the case of a block of one row in the ``first row'' or % the ``last row''. % \begin{macrocode} \int_compare:nNnTF { #1 } = 0 { \l_@@_code_for_first_row_tl } { \int_compare:nNnT { #1 } = \l_@@_last_row_int \l_@@_code_for_last_row_tl } % \end{macrocode} % If the block has only one row, we want the label of the block perfectly % aligned on the baseline of the row. That's why we have constructed a % |\pgfcoordinate| on the baseline of the row, in the first column of the array. % Now, we retrieve the $y$-value of that node and we store it in |\l_tmpa_dim|. % \begin{macrocode} \pgfextracty \l_tmpa_dim { \@@_qpoint:n { row - #1 - base } } % \end{macrocode} % We retrieve (in |\pgf@x|) the $x$-value of the center of the block. % \begin{macrocode} \pgfpointanchor { \@@_env: - #1 - #2 - block \bool_if:NF \l_@@_hpos_of_block_cap_bool { - short } } { \str_case:Vn \l_@@_hpos_block_str { c { center } l { west } r { east } } } % \end{macrocode} % We put the label of the block which has been composed in |\l_@@_cell_box|. % \begin{macrocode} \pgftransformshift { \pgfpoint \pgf@x \l_tmpa_dim } \pgfset { inner~sep = \c_zero_dim } \pgfnode { rectangle } { \str_case:Vn \l_@@_hpos_block_str { c { base } l { base~west } r { base~east } } } { \box_use_drop:N \l_@@_cell_box } { } { } } % \end{macrocode} % % \medskip % If the number of rows is different of $1$, we will put the label of the block % by using the short node (the label of the block has been composed in % |\l_@@_cell_box|). % \begin{macrocode} { % \end{macrocode} % If we are in the first column, we must put the block as if it was with the key~|r|. % \begin{macrocode} \int_compare:nNnT { #2 } = 0 { \str_set:Nn \l_@@_hpos_block_str r } \bool_if:nT \g_@@_last_col_found_bool { \int_compare:nNnT { #2 } = \g_@@_col_total_int { \str_set:Nn \l_@@_hpos_block_str l } } \pgftransformshift { \pgfpointanchor { \@@_env: - #1 - #2 - block \bool_if:NF \l_@@_hpos_of_block_cap_bool { - short } } { \str_case:Vn \l_@@_hpos_block_str { c { center } l { west } r { east } } } } \pgfset { inner~sep = \c_zero_dim } \pgfnode { rectangle } { \str_case:Vn \l_@@_hpos_block_str { c { center } l { west } r { east } } } { \box_use_drop:N \l_@@_cell_box } { } { } } \endpgfpicture \group_end: } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_extract_brackets { O { } } { \tl_set:Nn \l_tmpa_tl { #1 } \@@_store_in_tmpb_tl } \cs_new_protected:Npn \@@_store_in_tmpb_tl #1 \q_stop { \tl_set:Nn \l_tmpb_tl { #1 } } % \end{macrocode} % % % \bigskip % The first argument of |\@@_stroke_block:nnn| is a list of options for the % rectangle that you will stroke. The second argument is the upper-left cell of % the block (with, as usual, the syntax $i$|-|$j$) and the third is the last % cell of the block (with the same syntax). % \begin{macrocode} \cs_new_protected:Npn \@@_stroke_block:nnn #1 #2 #3 { \group_begin: \tl_clear:N \l_@@_draw_tl \dim_set_eq:NN \l_@@_line_width_dim \arrayrulewidth \keys_set_known:nn { NiceMatrix / BlockStroke } { #1 } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \tl_if_empty:NF \l_@@_draw_tl { % \end{macrocode} % If the user has used the key |color| of the command |\Block| without value, % the color fixed by |\arrayrulecolor| is used. % \begin{macrocode} \str_if_eq:VnTF \l_@@_draw_tl { default } { \CT@arc@ } { \exp_args:NV \pgfsetstrokecolor \l_@@_draw_tl } } \pgfsetcornersarced { \pgfpoint { \dim_use:N \l_@@_rounded_corners_dim } { \dim_use:N \l_@@_rounded_corners_dim } } \@@_cut_on_hyphen:w #2 \q_stop \bool_lazy_and:nnT { \int_compare_p:n { \l_tmpa_tl <= \c@iRow } } { \int_compare_p:n { \l_tmpb_tl <= \c@jCol } } { \@@_qpoint:n { row - \l_tmpa_tl } \dim_set:Nn \l_tmpb_dim { \pgf@y } \@@_qpoint:n { col - \l_tmpb_tl } \dim_set:Nn \l_tmpc_dim { \pgf@x } \@@_cut_on_hyphen:w #3 \q_stop \int_compare:nNnT \l_tmpa_tl > \c@iRow { \tl_set:Nx \l_tmpa_tl { \int_use:N \c@iRow } } \int_compare:nNnT \l_tmpb_tl > \c@jCol { \tl_set:Nx \l_tmpb_tl { \int_use:N \c@jCol } } \@@_qpoint:n { row - \@@_succ:n \l_tmpa_tl } \dim_set:Nn \l_tmpa_dim { \pgf@y } \@@_qpoint:n { col - \@@_succ:n \l_tmpb_tl } \dim_set:Nn \l_tmpd_dim { \pgf@x } \pgfpathrectanglecorners { \pgfpoint \l_tmpc_dim \l_tmpb_dim } { \pgfpoint \l_tmpd_dim \l_tmpa_dim } \pgfsetlinewidth { 1.1 \l_@@_line_width_dim } % \end{macrocode} % We can't use |\pgfusepathqstroke| because of the key |rounded-corners|. % \begin{macrocode} \pgfusepath { stroke } } \endpgfpicture \group_end: } % \end{macrocode} % % Here is the set of keys for the command |\@@_stroke_block:nnn|. % \begin{macrocode} \keys_define:nn { NiceMatrix / BlockStroke } { color .tl_set:N = \l_@@_draw_tl , draw .tl_set:N = \l_@@_draw_tl , draw .default:n = default , line-width .dim_set:N = \l_@@_line_width_dim , rounded-corners .dim_set:N = \l_@@_rounded_corners_dim , rounded-corners .default:n = 4 pt } % \end{macrocode} % % % \bigskip % The first argument of |\@@_hvlines_block:nnn| is a list of options for the % rules that we will draw. The second argument is the upper-left cell of the % block (with, as usual, the syntax $i$|-|$j$) and the third is the last cell of % the block (with the same syntax). % \begin{macrocode} \cs_new_protected:Npn \@@_hvlines_block:nnn #1 #2 #3 { \dim_set_eq:NN \l_@@_line_width_dim \arrayrulewidth \keys_set_known:nn { NiceMatrix / BlockBorders } { #1 } \@@_cut_on_hyphen:w #2 \q_stop \tl_set_eq:NN \l_tmpc_tl \l_tmpa_tl \tl_set_eq:NN \l_tmpd_tl \l_tmpb_tl \@@_cut_on_hyphen:w #3 \q_stop \tl_set:Nx \l_tmpa_tl { \int_eval:n { \l_tmpa_tl + 1 } } \tl_set:Nx \l_tmpb_tl { \int_eval:n { \l_tmpb_tl + 1 } } \int_step_inline:nnn \l_tmpd_tl \l_tmpb_tl { \use:x { \@@_vline:nnnn { ##1 } 1 { \l_tmpc_tl } { \@@_pred:n \l_tmpa_tl } } } \int_step_inline:nnn \l_tmpc_tl \l_tmpa_tl { \use:x { \@@_hline:nnnn { ##1 } 1 { \l_tmpd_tl } { \@@_pred:n \l_tmpb_tl } } } } % \end{macrocode} % % \bigskip % The first argument of |\@@_stroke_borders_block:nnn| is a list of options for % the borders that you will stroke. The second argument is the upper-left cell % of the block (with, as usual, the syntax $i$|-|$j$) and the third is the last % cell of the block (with the same syntax). % \begin{macrocode} \cs_new_protected:Npn \@@_stroke_borders_block:nnn #1 #2 #3 { \dim_set_eq:NN \l_@@_line_width_dim \arrayrulewidth \keys_set_known:nn { NiceMatrix / BlockBorders } { #1 } \dim_compare:nNnTF \l_@@_rounded_corners_dim > \c_zero_dim { \@@_error:n { borders~forbidden } } { \clist_map_inline:Nn \l_@@_borders_clist { \clist_if_in:nnF { top , bottom , left , right } { ##1 } { \@@_error:nn { bad~border } { ##1 } } } \@@_cut_on_hyphen:w #2 \q_stop \tl_set_eq:NN \l_tmpc_tl \l_tmpa_tl \tl_set_eq:NN \l_tmpd_tl \l_tmpb_tl \@@_cut_on_hyphen:w #3 \q_stop \tl_set:Nx \l_tmpa_tl { \int_eval:n { \l_tmpa_tl + 1 } } \tl_set:Nx \l_tmpb_tl { \int_eval:n { \l_tmpb_tl + 1 } } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \CT@arc@ \pgfsetlinewidth { 1.1 \l_@@_line_width_dim } \clist_if_in:NnT \l_@@_borders_clist { right } { \@@_stroke_vertical:n \l_tmpb_tl } \clist_if_in:NnT \l_@@_borders_clist { left } { \@@_stroke_vertical:n \l_tmpd_tl } \clist_if_in:NnT \l_@@_borders_clist { bottom } { \@@_stroke_horizontal:n \l_tmpa_tl } \clist_if_in:NnT \l_@@_borders_clist { top } { \@@_stroke_horizontal:n \l_tmpc_tl } \endpgfpicture } } % \end{macrocode} % % \medskip % The following command is used to stroke the left border and the right border. % The argument |#1| is the number of column (in the sense of the |col| node). % \begin{macrocode} \cs_new_protected:Npn \@@_stroke_vertical:n #1 { \@@_qpoint:n \l_tmpc_tl \dim_set:Nn \l_tmpb_dim { \pgf@y + 0.5 \l_@@_line_width_dim } \@@_qpoint:n \l_tmpa_tl \dim_set:Nn \l_tmpc_dim { \pgf@y + 0.5 \l_@@_line_width_dim } \@@_qpoint:n { #1 } \pgfpathmoveto { \pgfpoint \pgf@x \l_tmpb_dim } \pgfpathlineto { \pgfpoint \pgf@x \l_tmpc_dim } \pgfusepathqstroke } % \end{macrocode} % % \medskip % The following command is used to stroke the top border and the bottom border. % The argument |#1| is the number of row (in the sense of the |row| node). % \begin{macrocode} \cs_new_protected:Npn \@@_stroke_horizontal:n #1 { \@@_qpoint:n \l_tmpd_tl \clist_if_in:NnTF \l_@@_borders_clist { left } { \dim_set:Nn \l_tmpa_dim { \pgf@x - 0.5 \l_@@_line_width_dim } } { \dim_set:Nn \l_tmpa_dim { \pgf@x + 0.5 \l_@@_line_width_dim } } \@@_qpoint:n \l_tmpb_tl \dim_set:Nn \l_tmpb_dim { \pgf@x + 0.5 \l_@@_line_width_dim } \@@_qpoint:n { #1 } \pgfpathmoveto { \pgfpoint \l_tmpa_dim \pgf@y } \pgfpathlineto { \pgfpoint \l_tmpb_dim \pgf@y } \pgfusepathqstroke } % \end{macrocode} % % \bigskip % Here is the set of keys for the command |\@@_stroke_borders_block:nnn|. % \begin{macrocode} \keys_define:nn { NiceMatrix / BlockBorders } { borders .clist_set:N = \l_@@_borders_clist , rounded-corners .dim_set:N = \l_@@_rounded_corners_dim , rounded-corners .default:n = 4 pt , line-width .dim_set:N = \l_@@_line_width_dim } % \end{macrocode} % % \bigskip % The following command will be used if the key |tikz| has been used for the % command |\Block|. The arguments |#1| and |#2| are the coordinates of the first % cell and |#3| and |#4| the coordinates of the last cell of the block. |#5| is % a comma-separated list of the Tikz keys used with the path. % \begin{macrocode} \cs_new_protected:Npn \@@_block_tikz:nnnnn #1 #2 #3 #4 #5 { \begin { tikzpicture } \clist_map_inline:nn { #5 } { \path [ ##1 ] ( #1 -| #2 ) rectangle ( \@@_succ:n { #3 } -| \@@_succ:n { #4 } ) ; } \end { tikzpicture } } % \end{macrocode} % % % \subsection*{How to draw the dotted lines transparently} % \begin{macrocode} \cs_set_protected:Npn \@@_renew_matrix: { \RenewDocumentEnvironment { pmatrix } { } { \pNiceMatrix } { \endpNiceMatrix } \RenewDocumentEnvironment { vmatrix } { } { \vNiceMatrix } { \endvNiceMatrix } \RenewDocumentEnvironment { Vmatrix } { } { \VNiceMatrix } { \endVNiceMatrix } \RenewDocumentEnvironment { bmatrix } { } { \bNiceMatrix } { \endbNiceMatrix } \RenewDocumentEnvironment { Bmatrix } { } { \BNiceMatrix } { \endBNiceMatrix } } % \end{macrocode} % % % \bigskip % \subsection*{Automatic arrays} % % % \begin{macrocode} \cs_new_protected:Npn \@@_set_size:n #1-#2 \q_stop { \int_set:Nn \l_@@_nb_rows_int { #1 } \int_set:Nn \l_@@_nb_cols_int { #2 } } % \end{macrocode} % % % \bigskip % We will extract the potential keys |l|, |r| and |c| and pass the other keys to % the environment |{NiceArrayWithDelims}|. % \begin{macrocode} \keys_define:nn { NiceMatrix / Auto } { l .code:n = \tl_set:Nn \l_@@_type_of_col_tl l , r .code:n = \tl_set:Nn \l_@@_type_of_col_tl r , c .code:n = \tl_set:Nn \l_@@_type_of_col_tl c } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \AutoNiceMatrixWithDelims { m m O { } m O { } m ! O { } } { \int_zero_new:N \l_@@_nb_rows_int \int_zero_new:N \l_@@_nb_cols_int \@@_set_size:n #4 \q_stop % \end{macrocode} % The group is for the protection of |\l_@@_type_of_col_tl|. % \begin{macrocode} \group_begin: \tl_set:Nn \l_@@_type_of_col_tl c \keys_set_known:nnN { NiceMatrix / Auto } { #3, #5, #7 } \l_tmpa_tl \use:x { \exp_not:N \begin { NiceArrayWithDelims } { #1 } { #2 } { * { \int_use:N \l_@@_nb_cols_int } { \l_@@_type_of_col_tl } } [ \exp_not:V \l_tmpa_tl ] } \int_compare:nNnT \l_@@_first_row_int = 0 { \int_compare:nNnT \l_@@_first_col_int = 0 { & } \prg_replicate:nn { \l_@@_nb_cols_int - 1 } { & } \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\ } \prg_replicate:nn \l_@@_nb_rows_int { \int_compare:nNnT \l_@@_first_col_int = 0 { & } % \end{macrocode} % We put |{ }| before |#6| to avoid a hasty expansion of a potential % |\arabic{iRow}| at the beginning of the row which would result in an incorrect % value of that |iRow| (since |iRow| is incremented in the first cell of the row % of the |\halign|). % \begin{macrocode} \prg_replicate:nn { \l_@@_nb_cols_int - 1 } { { } #6 & } #6 \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\ } \int_compare:nNnT \l_@@_last_row_int > { -2 } { \int_compare:nNnT \l_@@_first_col_int = 0 { & } \prg_replicate:nn { \l_@@_nb_cols_int - 1 } { & } \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\ } \end { NiceArrayWithDelims } \group_end: } % \end{macrocode} % % \begin{macrocode} \cs_set_protected:Npn \@@_define_com:nnn #1 #2 #3 { \cs_set_protected:cpn { #1 AutoNiceMatrix } { \str_gset:Nx \g_@@_name_env_str { #1 AutoNiceMatrix } \AutoNiceMatrixWithDelims { #2 } { #3 } } } % \end{macrocode} % % \begin{macrocode} \@@_define_com:nnn p ( ) \@@_define_com:nnn b [ ] \@@_define_com:nnn v | | \@@_define_com:nnn V \| \| \@@_define_com:nnn B \{ \} % \end{macrocode} % % \bigskip % We define also a command |\AutoNiceMatrix| similar to the environment |{NiceMatrix}|. % \begin{macrocode} \NewDocumentCommand \AutoNiceMatrix { O { } m O { } m ! O { } } { \group_begin: \bool_set_true:N \l_@@_NiceArray_bool \AutoNiceMatrixWithDelims . . { #2 } { #4 } [ #1 , #3 , #5 ] \group_end: } % \end{macrocode} % % % \bigskip % \subsection*{The redefinition of the command \textbackslash dotfill } % % \begin{macrocode} \cs_set_eq:NN \@@_old_dotfill \dotfill \cs_new_protected:Npn \@@_dotfill: { % \end{macrocode} % First, we insert |\@@_dotfill| (which is the saved version of |\dotfill|) in % case of use of |\dotfill| ``internally'' in the cell (e.g. |\hbox to 1cm {\dotfill}|). % \begin{macrocode} \@@_old_dotfill \bool_if:NT \l_@@_NiceTabular_bool { \group_insert_after:N \@@_dotfill_ii: } { \group_insert_after:N \@@_dotfill_i: } } \cs_new_protected:Npn \@@_dotfill_i: { \group_insert_after:N \@@_dotfill_ii: } \cs_new_protected:Npn \@@_dotfill_ii: { \group_insert_after:N \@@_dotfill_iii: } % \end{macrocode} % Now, if the box if not empty (unfornately, we can't actually test whether the % box is empty and that's why we only consider it's width), we insert % |\@@_dotfill| (which is the saved version of |\dotfill|) in the cell of the % array, and it will extend, since it is no longer in |\l_@@_cell_box|. % \begin{macrocode} \cs_new_protected:Npn \@@_dotfill_iii: { \dim_compare:nNnT { \box_wd:N \l_@@_cell_box } = \c_zero_dim \@@_old_dotfill } % \end{macrocode} % % \bigskip % \subsection*{The command \textbackslash diagbox} % % The command |\diagbox| will be linked to |\diagbox:nn| in the environments of % \pkg{nicematrix}. However, there are also redefinitions of |\diagbox| in other % circonstancies. % % \begin{macrocode} \cs_new_protected:Npn \@@_diagbox:nn #1 #2 { \tl_gput_right:Nx \g_@@_internal_code_after_tl { \@@_actually_diagbox:nnnnnn { \int_use:N \c@iRow } { \int_use:N \c@jCol } { \int_use:N \c@iRow } { \int_use:N \c@jCol } { \exp_not:n { #1 } } { \exp_not:n { #2 } } } % \end{macrocode} % We put the cell with |\diagbox| in the sequence |\g_@@_pos_of_blocks_seq| % because a cell with |\diagbox| must be considered as non empty by the key % |corners|. % \begin{macrocode} \seq_gput_right:Nx \g_@@_pos_of_blocks_seq { { \int_use:N \c@iRow } { \int_use:N \c@jCol } { \int_use:N \c@iRow } { \int_use:N \c@jCol } } } % \end{macrocode} % % \medskip % The command |\diagbox| is also redefined locally when we draw a block. % % \medskip % The first four arguments of |\@@_actually_diagbox:nnnnnn| correspond to the % rectangle (=block) to slash (we recall that it's possible to use |\diagbox| in % a |\Block|). The two other are the elements to draw below and above the % diagonal line. % \begin{macrocode} \cs_new_protected:Npn \@@_actually_diagbox:nnnnnn #1 #2 #3 #4 #5 #6 { \pgfpicture \pgf@relevantforpicturesizefalse \pgfrememberpicturepositiononpagetrue \@@_qpoint:n { row - #1 } \dim_set_eq:NN \l_tmpa_dim \pgf@y \@@_qpoint:n { col - #2 } \dim_set_eq:NN \l_tmpb_dim \pgf@x \pgfpathmoveto { \pgfpoint \l_tmpb_dim \l_tmpa_dim } \@@_qpoint:n { row - \@@_succ:n { #3 } } \dim_set_eq:NN \l_tmpc_dim \pgf@y \@@_qpoint:n { col - \@@_succ:n { #4 } } \dim_set_eq:NN \l_tmpd_dim \pgf@x \pgfpathlineto { \pgfpoint \l_tmpd_dim \l_tmpc_dim } { % \end{macrocode} % The command |\CT@arc@| is a command of \pkg{colortbl} which sets the color of % the rules in the array. The package \pkg{nicematrix} uses it even if \pkg{colortbl} is not % loaded. % \begin{macrocode} \CT@arc@ \pgfsetroundcap \pgfusepathqstroke } \pgfset { inner~sep = 1 pt } \pgfscope \pgftransformshift { \pgfpoint \l_tmpb_dim \l_tmpc_dim } \pgfnode { rectangle } { south~west } { \@@_math_toggle_token: #5 \@@_math_toggle_token: } { } { } \endpgfscope \pgftransformshift { \pgfpoint \l_tmpd_dim \l_tmpa_dim } \pgfnode { rectangle } { north~east } { \@@_math_toggle_token: #6 \@@_math_toggle_token: } { } { } \endpgfpicture } % \end{macrocode} % % % % % \bigskip % \subsection*{The keyword \textbackslash CodeAfter} % % % The |\CodeAfter| (inserted with the key |code-after| or after the keyword % |\CodeAfter|) may always begin with a list of pairs \emph{key-value} between % square brackets. Here is the corresponding set of keys. % \begin{macrocode} \keys_define:nn { NiceMatrix } { CodeAfter / rules .inherit:n = NiceMatrix / rules , CodeAfter / sub-matrix .inherit:n = NiceMatrix / sub-matrix } \keys_define:nn { NiceMatrix / CodeAfter } { sub-matrix .code:n = \keys_set:nn { NiceMatrix / sub-matrix } { #1 } , sub-matrix .value_required:n = true , delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , delimiters / color .value_required:n = true , rules .code:n = \keys_set:nn { NiceMatrix / rules } { #1 } , rules .value_required:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~CodeAfter } } % \end{macrocode} % % \medskip % In fact, in this subsection, we define the user command |\CodeAfter| for the % case of the ``normal syntax''. For the case of ``light-syntax'', see the % definition of the environment |{@@-light-syntax}| on % p.~\pageref{code-light-syntax}. % % % \medskip % In the environments of \pkg{nicematrix}, |\CodeAfter| will be linked to % |\@@_CodeAfter:|. That macro must \emph{not} be protected since it begins with % |\omit|. % \begin{macrocode} \cs_new:Npn \@@_CodeAfter: { \omit \@@_CodeAfter_i:n } % \end{macrocode} % % \medskip % However, in each cell of the environment, the command |\CodeAfter| will be % linked to the following command |\@@_CodeAfter_i:n| which do \emph{not} begin % with |\omit| (and thus, the user will be able to use |\CodeAfter| without % error and without the need to prefix by |\omit|. % % \smallskip % We have to catch everything until the end of the current environment (of % \pkg{nicematrix}). First, we go until the next command |\end|. % \begin{macrocode} \cs_new_protected:Npn \@@_CodeAfter_i:n #1 \end { \tl_gput_right:Nn \g_nicematrix_code_after_tl { #1 } \@@_CodeAfter_ii:n } % \end{macrocode} % % We catch the argument of the command |\end| (in |#1|). % \begin{macrocode} \cs_new_protected:Npn \@@_CodeAfter_ii:n #1 { % \end{macrocode} % If this is really the end of the current environment (of \pkg{nicematrix}), we % put back the command |\end| and its argument in the TeX flow. % \begin{macrocode} \str_if_eq:eeTF \@currenvir { #1 } { \end { #1 } } % \end{macrocode} % If this is not the |\end| we are looking for, we put those tokens in % |\g_nicematrix_code_after_tl| and we go on searching for the next command % |\end| with a recursive call to the command |\@@_CodeAfter:n|. % \begin{macrocode} { \tl_gput_right:Nn \g_nicematrix_code_after_tl { \end { #1 } } \@@_CodeAfter_i:n } } % \end{macrocode} % % % \subsection*{The delimiters in the preamble} % % The command |\@@_delimiter:nnn| will be used to draw delimiters inside the % matrix when delimiters are specified in the preamble of the array. It does % \emph{not} concern the exterior delimiters added by |{NiceArrayWithDelims}| % (and |{pNiceArray}|, |{pNiceMatrix}|, etc.). % % A delimiter in the preamble of the array will write an instruction % |\@@_delimiter:nnn| in the |\g_@@_internal_code_after_tl| (and also % potentially add instructions in the preamble provided to |\array| in order to % add space between columns). % % \smallskip % The first argument is the type of delimiter (|(|, |[|, |\{|, |)|, |]| or % |\}|). The second argument is the number of colummn. The third argument is a % boolean equal to |\c_true_bool| (resp. |\c_false_true|) when the delimiter % must be put on the left (resp. right) side. % % \begin{macrocode} \cs_new_protected:Npn \@@_delimiter:nnn #1 #2 #3 { \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse % \end{macrocode} % % \medskip % |\l_@@_y_initial_dim| and |\l_@@_y_final_dim| will be the $y$-values of the % extremities of the delimiter we will have to construct. % \begin{macrocode} \@@_qpoint:n { row - 1 } \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y \@@_qpoint:n { row - \@@_succ:n \c@iRow } \dim_set_eq:NN \l_@@_y_final_dim \pgf@y % \end{macrocode} % % \medskip % We will compute in |\l_tmpa_dim| the $x$-value where we will have to put our % delimiter (on the left side or on the right side). % \begin{macrocode} \bool_if:nTF { #3 } { \dim_set_eq:NN \l_tmpa_dim \c_max_dim } { \dim_set:Nn \l_tmpa_dim { - \c_max_dim } } \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - #2 } { \pgfpointanchor { \@@_env: - ##1 - #2 } { \bool_if:nTF { #3 } { west } { east } } \dim_set:Nn \l_tmpa_dim { \bool_if:nTF { #3 } \dim_min:nn \dim_max:nn \l_tmpa_dim \pgf@x } } } % \end{macrocode} % % % Now we can put the delimiter with a node of \textsc{pgf}. % \begin{macrocode} \pgfset { inner~sep = \c_zero_dim } \dim_zero:N \nulldelimiterspace \pgftransformshift { \pgfpoint { \l_tmpa_dim } { ( \l_@@_y_initial_dim + \l_@@_y_final_dim + \arrayrulewidth ) / 2 } } \pgfnode { rectangle } { \bool_if:nTF { #3 } { east } { west } } { % \end{macrocode} % Here is the content of the \textsc{pgf} node, that is to say the delimiter, % constructed with its right size. % \begin{macrocode} \nullfont \c_math_toggle_token \tl_if_empty:NF \l_@@_delimiters_color_tl { \color { \l_@@_delimiters_color_tl } } \bool_if:nTF { #3 } { \left #1 } { \left . } \vcenter { \nullfont \hrule \@height \dim_eval:n { \l_@@_y_initial_dim - \l_@@_y_final_dim } \@depth \c_zero_dim \@width \c_zero_dim } \bool_if:nTF { #3 } { \right . } { \right #1 } \c_math_toggle_token } { } { } \endpgfpicture } % \end{macrocode} % % \subsection*{The command \textbackslash SubMatrix} % % % \begin{macrocode} \keys_define:nn { NiceMatrix / sub-matrix } { extra-height .dim_set:N = \l_@@_submatrix_extra_height_dim , extra-height .value_required:n = true , left-xshift .dim_set:N = \l_@@_submatrix_left_xshift_dim , left-xshift .value_required:n = true , right-xshift .dim_set:N = \l_@@_submatrix_right_xshift_dim , right-xshift .value_required:n = true , xshift .meta:n = { left-xshift = #1, right-xshift = #1 } , xshift .value_required:n = true , delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , delimiters / color .value_required:n = true , slim .bool_set:N = \l_@@_submatrix_slim_bool , slim .default:n = true , hlines .clist_set:N = \l_@@_submatrix_hlines_clist , hlines .default:n = all , vlines .clist_set:N = \l_@@_submatrix_vlines_clist , vlines .default:n = all , hvlines .meta:n = { hlines, vlines } , hvlines .value_forbidden:n = true , } \keys_define:nn { NiceMatrix } { SubMatrix .inherit:n = NiceMatrix / sub-matrix , CodeAfter / sub-matrix .inherit:n = NiceMatrix / sub-matrix , NiceMatrix / sub-matrix .inherit:n = NiceMatrix / sub-matrix , NiceArray / sub-matrix .inherit:n = NiceMatrix / sub-matrix , pNiceArray / sub-matrix .inherit:n = NiceMatrix / sub-matrix , NiceMatrixOptions / sub-matrix .inherit:n = NiceMatrix / sub-matrix , } % \end{macrocode} % % \medskip % The following keys set is for the command |\SubMatrix| itself (not the tuning % of |\SubMatrix| that can be done elsewhere). % \begin{macrocode} \keys_define:nn { NiceMatrix / SubMatrix } { hlines .clist_set:N = \l_@@_submatrix_hlines_clist , hlines .default:n = all , vlines .clist_set:N = \l_@@_submatrix_vlines_clist , vlines .default:n = all , hvlines .meta:n = { hlines, vlines } , hvlines .value_forbidden:n = true , name .code:n = \tl_if_empty:nTF { #1 } { \@@_error:n { Invalid~name~format } } { \regex_match:nnTF { \A[A-Za-z][A-Za-z0-9]*\Z } { #1 } { \seq_if_in:NnTF \g_@@_submatrix_names_seq { #1 } { \@@_error:nn { Duplicate~name~for~SubMatrix } { #1 } } { \str_set:Nn \l_@@_submatrix_name_str { #1 } \seq_gput_right:Nn \g_@@_submatrix_names_seq { #1 } } } { \@@_error:n { Invalid~name~format } } } , rules .code:n = \keys_set:nn { NiceMatrix / rules } { #1 } , rules .value_required:n = true , code .tl_set:N = \l_@@_code_tl , code .value_required:n = true , name .value_required:n = true , unknown .code:n = \@@_error:n { Unknown~key~for~SubMatrix } } % \end{macrocode} % % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_SubMatrix_in_code_before { m m m m ! O { } } { \peek_remove_spaces:n { \@@_cut_on_hyphen:w #3 \q_stop \tl_clear_new:N \l_tmpc_tl \tl_clear_new:N \l_tmpd_tl \tl_set_eq:NN \l_tmpc_tl \l_tmpa_tl \tl_set_eq:NN \l_tmpd_tl \l_tmpb_tl \@@_cut_on_hyphen:w #2 \q_stop \seq_gput_right:Nx \g_@@_submatrix_seq { { \l_tmpa_tl } { \l_tmpb_tl } { \l_tmpc_tl } { \l_tmpd_tl } } \tl_gput_right:Nn \g_@@_internal_code_after_tl { \SubMatrix { #1 } { #2 } { #3 } { #4 } [ #5 ] } } } % \end{macrocode} % % \bigskip % In the internal |code-after| and in the |\CodeAfter| the following command % |\@@_SubMatrix| will be linked to |\SubMatrix|. % \begin{itemize} % \item |#1| is the left delimiter; % \item |#2| is the upper-left cell of the matrix with the format $i$-$j$; % \item |#3| is the lower-right cell of the matrix with the format $i$-$j$; % \item |#4| is the right delimiter; % \item |#5| is the list of options of the command; % \item |#6| is the potential subscript; % \item |#7| is the potential superscript. % \end{itemize} % For explanations about the construction with rescanning of the preamble, see % the documentation for the user command |\Cdots|. % \begin{macrocode} \AtBeginDocument { \tl_set:Nn \l_@@_argspec_tl { m m m m O { } E { _ ^ } { { } { } } } \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl \exp_args:NNV \NewDocumentCommand \@@_SubMatrix \l_@@_argspec_tl { \peek_remove_spaces:n { \@@_sub_matrix:nnnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } } } } % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn \@@_sub_matrix:nnnnnnn #1 #2 #3 #4 #5 #6 #7 { \group_begin: % \end{macrocode} % The four following token lists correspond to the position of the |\SubMatrix|. % \begin{macrocode} \tl_clear_new:N \l_@@_first_i_tl \tl_clear_new:N \l_@@_first_j_tl \tl_clear_new:N \l_@@_last_i_tl \tl_clear_new:N \l_@@_last_j_tl % \end{macrocode} % The command |\@@_cut_on_hyphen:w| cuts on the hyphen an argument of the form % $i$-$j$. The value of $i$ is stored in |\l_tmpa_tl| and the value of $j$ is % stored in |\l_tmpb_tl|. % \begin{macrocode} \@@_cut_on_hyphen:w #2 \q_stop \tl_set_eq:NN \l_@@_first_i_tl \l_tmpa_tl \tl_set_eq:NN \l_@@_first_j_tl \l_tmpb_tl \@@_cut_on_hyphen:w #3 \q_stop \tl_set_eq:NN \l_@@_last_i_tl \l_tmpa_tl \tl_set_eq:NN \l_@@_last_j_tl \l_tmpb_tl \bool_lazy_or:nnTF { \int_compare_p:nNn \l_@@_last_i_tl > \g_@@_row_total_int } { \int_compare_p:nNn \l_@@_last_j_tl > \g_@@_col_total_int } { \@@_error:n { SubMatrix~too~large } } { \str_clear_new:N \l_@@_submatrix_name_str \keys_set:nn { NiceMatrix / SubMatrix } { #5 } \pgfpicture \pgfrememberpicturepositiononpagetrue \pgf@relevantforpicturesizefalse \pgfset { inner~sep = \c_zero_dim } \dim_set_eq:NN \l_@@_x_initial_dim \c_max_dim \dim_set:Nn \l_@@_x_final_dim { - \c_max_dim } % \end{macrocode} % The last value of |\int_step_inline:nnn| is provided by currifycation. % \begin{macrocode} \bool_if:NTF \l_@@_submatrix_slim_bool { \int_step_inline:nnn \l_@@_first_i_tl \l_@@_last_i_tl } { \int_step_inline:nnn \l_@@_first_row_int \g_@@_row_total_int } { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - \l_@@_first_j_tl } { \pgfpointanchor { \@@_env: - ##1 - \l_@@_first_j_tl } { west } \dim_set:Nn \l_@@_x_initial_dim { \dim_min:nn \l_@@_x_initial_dim \pgf@x } } \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - ##1 - \l_@@_last_j_tl } { \pgfpointanchor { \@@_env: - ##1 - \l_@@_last_j_tl } { east } \dim_set:Nn \l_@@_x_final_dim { \dim_max:nn \l_@@_x_final_dim \pgf@x } } } \dim_compare:nNnTF \l_@@_x_initial_dim = \c_max_dim { \@@_error:nn { impossible~delimiter } { left } } { \dim_compare:nNnTF \l_@@_x_final_dim = { - \c_max_dim } { \@@_error:nn { impossible~delimiter } { right } } { \@@_sub_matrix_i:nnnn { #1 } { #4 } { #6 } { #7 } } } \endpgfpicture } \group_end: } % \end{macrocode} % % \bigskip % |#1| is the left delimiter, |#2| is the right one, |#3| is the subscript and % |#4| is the superscript. % \begin{macrocode} \cs_new_protected:Npn \@@_sub_matrix_i:nnnn #1 #2 #3 #4 { \@@_qpoint:n { row - \l_@@_first_i_tl - base } \dim_set:Nn \l_@@_y_initial_dim { \pgf@y + ( \box_ht:N \strutbox + \extrarowheight ) * \arraystretch } \@@_qpoint:n { row - \l_@@_last_i_tl - base } \dim_set:Nn \l_@@_y_final_dim { \pgf@y - ( \box_dp:N \strutbox ) * \arraystretch } \int_step_inline:nnn \l_@@_first_col_int \g_@@_col_total_int { \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - \l_@@_first_i_tl - ##1 } { \pgfpointanchor { \@@_env: - \l_@@_first_i_tl - ##1 } { north } \dim_set:Nn \l_@@_y_initial_dim { \dim_max:nn \l_@@_y_initial_dim \pgf@y } } \cs_if_exist:cT { pgf @ sh @ ns @ \@@_env: - \l_@@_last_i_tl - ##1 } { \pgfpointanchor { \@@_env: - \l_@@_last_i_tl - ##1 } { south } \dim_set:Nn \l_@@_y_final_dim { \dim_min:nn \l_@@_y_final_dim \pgf@y } } } \dim_set:Nn \l_tmpa_dim { \l_@@_y_initial_dim - \l_@@_y_final_dim + \l_@@_submatrix_extra_height_dim - \arrayrulewidth } \dim_set_eq:NN \nulldelimiterspace \c_zero_dim % \end{macrocode} % % \bigskip % We will draw the rules in the |\SubMatrix|. % \begin{macrocode} \group_begin: \pgfsetlinewidth { 1.1 \arrayrulewidth } \tl_if_empty:NF \l_@@_rules_color_tl { \exp_after:wN \@@_set_CT@arc@: \l_@@_rules_color_tl \q_stop } \CT@arc@ % \end{macrocode} % Now, we draw the potential vertical rules specified in the preamble of the % environments with the letter fixed with the key |vlines-in-sub-matrix|. The % list of the columns where there is such rule to draw is in |\g_@@_cols_vlism_seq|. % \begin{macrocode} \seq_map_inline:Nn \g_@@_cols_vlism_seq { \int_compare:nNnT \l_@@_first_j_tl < { ##1 } { \int_compare:nNnT { ##1 } < { \int_eval:n { \l_@@_last_j_tl + 1 } } { % \end{macrocode} % First, we extract the value of the abscissa of the rule we have to draw. % \begin{macrocode} \@@_qpoint:n { col - ##1 } \pgfpathmoveto { \pgfpoint \pgf@x \l_@@_y_initial_dim } \pgfpathlineto { \pgfpoint \pgf@x \l_@@_y_final_dim } \pgfusepathqstroke } } } % \end{macrocode} % % \medskip % Now, we draw the vertical rules specified in the key |vlines| of |\SubMatrix|. % The last argument of |\int_step_inline:nn| or |\clist_map_inline:Nn| is given % by curryfication. % \begin{macrocode} \tl_if_eq:NnTF \l_@@_submatrix_vlines_clist { all } { \int_step_inline:nn { \l_@@_last_j_tl - \l_@@_first_j_tl } } { \clist_map_inline:Nn \l_@@_submatrix_vlines_clist } { \bool_lazy_and:nnTF { \int_compare_p:nNn { ##1 } > 0 } { \int_compare_p:nNn { ##1 } < { \l_@@_last_j_tl - \l_@@_first_j_tl + 1 } } { \@@_qpoint:n { col - \int_eval:n { ##1 + \l_@@_first_j_tl } } \pgfpathmoveto { \pgfpoint \pgf@x \l_@@_y_initial_dim } \pgfpathlineto { \pgfpoint \pgf@x \l_@@_y_final_dim } \pgfusepathqstroke } { \@@_error:nnn { Wrong~line~in~SubMatrix } { vertical } { ##1 } } } % \end{macrocode} % % \medskip % Now, we draw the horizontal rules specified in the key |hlines| of % |\SubMatrix|. % The last argument of |\int_step_inline:nn| or |\clist_map_inline:Nn| is given % by curryfication. % \begin{macrocode} \tl_if_eq:NnTF \l_@@_submatrix_hlines_clist { all } { \int_step_inline:nn { \l_@@_last_i_tl - \l_@@_first_i_tl } } { \clist_map_inline:Nn \l_@@_submatrix_hlines_clist } { \bool_lazy_and:nnTF { \int_compare_p:nNn { ##1 } > 0 } { \int_compare_p:nNn { ##1 } < { \l_@@_last_i_tl - \l_@@_first_i_tl + 1 } } { \@@_qpoint:n { row - \int_eval:n { ##1 + \l_@@_first_i_tl } } % \end{macrocode} % We use a group to protect |\l_tmpa_dim| and |\l_tmpb_dim|. % \begin{macrocode} \group_begin: % \end{macrocode} % We compute in |\l_tmpa_dim| the $x$-value of the left end of the rule. % \begin{macrocode} \dim_set:Nn \l_tmpa_dim { \l_@@_x_initial_dim - \l_@@_submatrix_left_xshift_dim } \str_case:nn { #1 } { ( { \dim_sub:Nn \l_tmpa_dim { 0.9 mm } } [ { \dim_sub:Nn \l_tmpa_dim { 0.2 mm } } \{ { \dim_sub:Nn \l_tmpa_dim { 0.9 mm } } } \pgfpathmoveto { \pgfpoint \l_tmpa_dim \pgf@y } % \end{macrocode} % We compute in |\l_tmpb_dim| the $x$-value of the right end of the rule. % \begin{macrocode} \dim_set:Nn \l_tmpb_dim { \l_@@_x_final_dim + \l_@@_submatrix_right_xshift_dim } \str_case:nn { #2 } { ) { \dim_add:Nn \l_tmpb_dim { 0.9 mm } } ] { \dim_add:Nn \l_tmpb_dim { 0.2 mm } } \} { \dim_add:Nn \l_tmpb_dim { 0.9 mm } } } \pgfpathlineto { \pgfpoint \l_tmpb_dim \pgf@y } \pgfusepathqstroke \group_end: } { \@@_error:nnn { Wrong~line~in~SubMatrix } { horizontal } { ##1 } } } % \end{macrocode} % % \medskip % If the key |name| has been used for the command |\SubMatrix|, we create a PGF % node with that name for the submatrix (this node does not encompass the % delimiters that we will put after). % \begin{macrocode} \str_if_empty:NF \l_@@_submatrix_name_str { \@@_pgf_rect_node:nnnnn \l_@@_submatrix_name_str \l_@@_x_initial_dim \l_@@_y_initial_dim \l_@@_x_final_dim \l_@@_y_final_dim } \group_end: % \end{macrocode} % The group was for |\CT@arc@| (the color of the rules). % % \medskip % Now, we deal with the left delimiter. Of course, the environment % |{pgfscope}| is for the |\pgftransformshift|. % \begin{macrocode} \begin { pgfscope } \pgftransformshift { \pgfpoint { \l_@@_x_initial_dim - \l_@@_submatrix_left_xshift_dim } { ( \l_@@_y_initial_dim + \l_@@_y_final_dim ) / 2 } } \str_if_empty:NTF \l_@@_submatrix_name_str { \@@_node_left:nn #1 { } } { \@@_node_left:nn #1 { \@@_env: - \l_@@_submatrix_name_str - left } } \end { pgfscope } % \end{macrocode} % % \medskip % Now, we deal with the right delimiter. % \begin{macrocode} \pgftransformshift { \pgfpoint { \l_@@_x_final_dim + \l_@@_submatrix_right_xshift_dim } { ( \l_@@_y_initial_dim + \l_@@_y_final_dim ) / 2 } } \str_if_empty:NTF \l_@@_submatrix_name_str { \@@_node_right:nnnn #2 { } { #3 } { #4 } } { \@@_node_right:nnnn #2 { \@@_env: - \l_@@_submatrix_name_str - right } { #3 } { #4 } } % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN \pgfpointanchor \@@_pgfpointanchor:n \flag_clear_new:n { nicematrix } \l_@@_code_tl } % \end{macrocode} % % \bigskip % In the key |code| of the command |\SubMatrix| there may be Tikz instructions. % We want that, in these instructions, the $i$ and $j$ in specifications of % nodes of the forms $i$|-|$j$, |row-|$i$, |col-|$j$ and $i$\verb+-|+$j$ refer % to the number of row and columm \emph{relative} of the current |\SubMatrix|. % That's why we will patch (locally in the |\SubMatrix|) the command % |\pgfpointanchor|. % \begin{macrocode} \cs_set_eq:NN \@@_old_pgfpointanchor \pgfpointanchor % \end{macrocode} % % \bigskip % The following command will be linked to |\pgfpointanchor| just before the % execution of the option |code| of the command |\SubMatrix|. In this command, % we catch the argument |#1| of |\pgfpointanchor| and we apply to it the command % |\@@_pgfpointanchor_i:nn| before passing it to the original |\pgfpointanchor|. % We have to act in an expandable way because the command |\pgfpointanchor| is % used in names of Tikz nodes which are computed in an expandable way. % \begin{macrocode} \cs_new_protected:Npn \@@_pgfpointanchor:n #1 { \use:e { \exp_not:N \@@_old_pgfpointanchor { \@@_pgfpointanchor_i:nn #1 } } } % \end{macrocode} % % \bigskip % In fact, the argument of |\pgfpointanchor| is always of the form % |\a_command { name_of_node }| where ``|name_of_node|'' is the name of the Tikz % node without the potential prefix and suffix. That's why we catch two % arguments and work only on the second by trying (first) to extract an hyphen |-|. % \begin{macrocode} \cs_new:Npn \@@_pgfpointanchor_i:nn #1 #2 { #1 { \@@_pgfpointanchor_ii:w #2 - \q_stop } } % \end{macrocode} % % \bigskip % Since |\seq_if_in:NnTF| and |\clist_if_in:NnTF| are not expandable, we will % use the following token list and |\str_case:nVTF| to test whether we have an % integer or not. % \begin{macrocode} \tl_const:Nn \c_@@_integers_alist_tl { { 1 } { } { 2 } { } { 3 } { } { 4 } { } { 5 } { } { 6 } { } { 7 } { } { 8 } { } { 9 } { } { 10 } { } { 11 } { } { 12 } { } { 13 } { } { 14 } { } { 15 } { } { 16 } { } { 17 } { } { 18 } { } { 19 } { } { 20 } { } } % \end{macrocode} % % \bigskip % \begin{macrocode} \cs_new:Npn \@@_pgfpointanchor_ii:w #1-#2\q_stop { % \end{macrocode} % If there is no hyphen, that means that the node is of the form of a single % number (ex.: |5| or |11|). In that case, we are in an analysis which result % from a specification of node of the form $i$\verb+-|+$j$. In that case, the % $i$ of the number of row arrives first (and alone) in a |\pgfpointanchor| and, % the, the $j$ arrives (alone) in the following |\pgfpointanchor|. In order to % know whether we have a number of row of a number of column, we keep track of % the number of such treatments by the expandable flag called |nicematrix|. % \begin{macrocode} \tl_if_empty:nTF { #2 } { \str_case:nVTF { #1 } \c_@@_integers_alist_tl { \flag_raise:n { nicematrix } \int_if_even:nTF { \flag_height:n { nicematrix } } { \int_eval:n { #1 + \l_@@_first_i_tl - 1 } } { \int_eval:n { #1 + \l_@@_first_j_tl - 1 } } } { #1 } } % \end{macrocode} % If there is an hyphen, we have to see whether we have a node of the form % $i$|-|$j$, |row-|$i$ or |col-|$j$. % \begin{macrocode} { \@@_pgfpointanchor_iii:w { #1 } #2 } } % \end{macrocode} % % \bigskip % There was an hyphen in the name of the node and that's why we have to retrieve % the extra hyphen we have put (cf. |\@@_pgfpointanchor_i:nn|). % \begin{macrocode} \cs_new:Npn \@@_pgfpointanchor_iii:w #1 #2 - { \str_case:nnF { #1 } { { row } { row - \int_eval:n { #2 + \l_@@_first_i_tl - 1 } } { col } { col - \int_eval:n { #2 + \l_@@_first_j_tl - 1 } } } % \end{macrocode} % Now the case of a node of the form $i$|-|$j$. % \begin{macrocode} { \int_eval:n { #1 + \l_@@_first_i_tl - 1 } - \int_eval:n { #2 + \l_@@_first_j_tl - 1 } } } % \end{macrocode} % % \medskip % The command |\@@_node_left:nn| puts the left delimiter with the correct size. % The argument |#1| is the delimiter to put. The argument |#2| is the name we % will give to this PGF node (if the key |name| has been used in |\SubMatrix|). % \begin{macrocode} \cs_new_protected:Npn \@@_node_left:nn #1 #2 { \pgfnode { rectangle } { east } { \nullfont \c_math_toggle_token \tl_if_empty:NF \l_@@_delimiters_color_tl { \color { \l_@@_delimiters_color_tl } } \left #1 \vcenter { \nullfont \hrule \@height \l_tmpa_dim \@depth \c_zero_dim \@width \c_zero_dim } \right . \c_math_toggle_token } { #2 } { } } % \end{macrocode} % % \medskip % The command |\@@_node_right:nn| puts the right delimiter with the correct size. % The argument |#1| is the delimiter to put. The argument |#2| is the name we % will give to this PGF node (if the key |name| has been used in |\SubMatrix|). % The argument |#3| is the subscript and |#4| is the superscript. % \begin{macrocode} \cs_new_protected:Npn \@@_node_right:nnnn #1 #2 #3 #4 { \pgfnode { rectangle } { west } { \nullfont \c_math_toggle_token \tl_if_empty:NF \l_@@_delimiters_color_tl { \color { \l_@@_delimiters_color_tl } } \left . \vcenter { \nullfont \hrule \@height \l_tmpa_dim \@depth \c_zero_dim \@width \c_zero_dim } \right #1 \tl_if_empty:nF { #3 } { _ { \smash { #3 } } } ^ { \smash { #4 } } \c_math_toggle_token } { #2 } { } } % \end{macrocode} % % % % % \bigskip % \subsection*{We process the options at package loading} % % % We process the options when the package is loaded (with |\usepackage|) but we % recommend to use |\NiceMatrixOptions| instead. % % We must process these options after the definition of the environment % |{NiceMatrix}| because the option |renew-matrix| executes the code % |\cs_set_eq:NN \env@matrix \NiceMatrix|. % % Of course, the command |\NiceMatrix| must be defined before such an % instruction is executed. % % \medskip % The boolean |\g_@@_footnotehyper_bool| will indicate if the option % |footnotehyper| is used. % \begin{macrocode} \bool_new:N \c_@@_footnotehyper_bool % \end{macrocode} % % \medskip % The boolean |\c_@@_footnote_bool| will indicate if the option |footnote| is % used, but quicky, it will also be set to |true| if the option |footnotehyper| % is used. % \begin{macrocode} \bool_new:N \c_@@_footnote_bool % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~package } { The~key~'\l_keys_key_str'~is~unknown. \\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ footnote,~ footnotehyper,~ renew-dots,~and renew-matrix. } % \end{macrocode} % % \medskip % Maybe we will completely delete the key 'transparent' in a future version. % \begin{macrocode} \@@_msg_new:nn { Key~transparent } { The~key~'transparent'~is~now~obsolete~(because~it's~name~ is~not~clear).~You~should~use~the~conjonction~of~'renew-dots'~ and~'renew-matrix'.~However,~you~can~go~on. } % \end{macrocode} % % \begin{macrocode} \keys_define:nn { NiceMatrix / Package } { renew-dots .bool_set:N = \l_@@_renew_dots_bool , renew-dots .value_forbidden:n = true , renew-matrix .code:n = \@@_renew_matrix: , renew-matrix .value_forbidden:n = true , transparent .code:n = { \@@_renew_matrix: \bool_set_true:N \l_@@_renew_dots_bool \@@_error:n { Key~transparent } } , transparent .value_forbidden:n = true, footnote .bool_set:N = \c_@@_footnote_bool , footnotehyper .bool_set:N = \c_@@_footnotehyper_bool , unknown .code:n = \@@_error:n { Unknown~key~for~package } } \ProcessKeysOptions { NiceMatrix / Package } % \end{macrocode} % % \bigskip % \begin{macrocode} \@@_msg_new:nn { footnote~with~footnotehyper~package } { You~can't~use~the~option~'footnote'~because~the~package~ footnotehyper~has~already~been~loaded.~ If~you~want,~you~can~use~the~option~'footnotehyper'~and~the~footnotes~ within~the~environments~of~nicematrix~will~be~extracted~with~the~tools~ of~the~package~footnotehyper.\\ If~you~go~on,~the~package~footnote~won't~be~loaded. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { footnotehyper~with~footnote~package } { You~can't~use~the~option~'footnotehyper'~because~the~package~ footnote~has~already~been~loaded.~ If~you~want,~you~can~use~the~option~'footnote'~and~the~footnotes~ within~the~environments~of~nicematrix~will~be~extracted~with~the~tools~ of~the~package~footnote.\\ If~you~go~on,~the~package~footnotehyper~won't~be~loaded. } % \end{macrocode} % % \medskip % \begin{macrocode} \bool_if:NT \c_@@_footnote_bool { % \end{macrocode} % The class \cls{beamer} has its own system to extract footnotes and that's why % we have nothing to do if \cls{beamer} is used. % \begin{macrocode} \@ifclassloaded { beamer } { \bool_set_false:N \c_@@_footnote_bool } { \@ifpackageloaded { footnotehyper } { \@@_error:n { footnote~with~footnotehyper~package } } { \usepackage { footnote } } } } % \end{macrocode} % % \begin{macrocode} \bool_if:NT \c_@@_footnotehyper_bool { % \end{macrocode} % The class \cls{beamer} has its own system to extract footnotes and that's why % we have nothing to do if \cls{beamer} is used. % \begin{macrocode} \@ifclassloaded { beamer } { \bool_set_false:N \c_@@_footnote_bool } { \@ifpackageloaded { footnote } { \@@_error:n { footnotehyper~with~footnote~package } } { \usepackage { footnotehyper } } } \bool_set_true:N \c_@@_footnote_bool } % \end{macrocode} % The flag |\c_@@_footnote_bool| is raised and so, we will only have to test % |\c_@@_footnote_bool| in order to know if we have to insert an environment % |{savenotes}|. % % % \bigskip % \subsection*{Error messages of the package} % % % The following message will be deleted when we will delete the key % |except-corners| for the command |\arraycolor|. % \begin{macrocode} \@@_msg_new:nn { key except-corners } { The~key~'except-corners'~has~been~deleted~for~the~command~\token_to_str:N \arraycolor\ in~the~\token_to_str:N \CodeBefore.~You~should~instead~use~ the~key~'corners'~in~your~\@@_full_name_env:.\\ If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % % \begin{macrocode} \seq_new:N \c_@@_types_of_matrix_seq \seq_set_from_clist:Nn \c_@@_types_of_matrix_seq { NiceMatrix , pNiceMatrix , bNiceMatrix , vNiceMatrix, BNiceMatrix, VNiceMatrix } \seq_set_map_x:NNn \c_@@_types_of_matrix_seq \c_@@_types_of_matrix_seq { \tl_to_str:n { #1 } } % \end{macrocode} % % \bigskip % If the user uses too much columns, the command |\@@_error_too_much_cols:| is % executed. This command raises an error but try to give the best information to % the user in the error message. The command |\seq_if_in:NVTF| is not expandable % and that's why we can't put it in the error message itself. We have to do the % test before the |\@@_fatal:n|. % \begin{macrocode} \cs_new_protected:Npn \@@_error_too_much_cols: { \seq_if_in:NVTF \c_@@_types_of_matrix_seq \g_@@_name_env_str { \int_compare:nNnTF \l_@@_last_col_int = { -2 } { \@@_fatal:n { too~much~cols~for~matrix } } { \bool_if:NF \l_@@_last_col_without_value_bool { \@@_fatal:n { too~much~cols~for~matrix~with~last~col } } } } { \@@_fatal:n { too~much~cols~for~array } } } % \end{macrocode} % % The following command must \emph{not} be protected since it's used in an error message. % \begin{macrocode} \cs_new:Npn \@@_message_hdotsfor: { \tl_if_empty:VF \g_@@_HVdotsfor_lines_tl { ~Maybe~your~use~of~\token_to_str:N \Hdotsfor\ is~incorrect.} } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { too~much~cols~for~matrix~with~last~col } { You~try~to~use~more~columns~than~allowed~by~your~ \@@_full_name_env:.\@@_message_hdotsfor:\ The~maximal~number~of~ columns~is~\int_eval:n { \l_@@_last_col_int - 1 }~(plus~the~ exterior~columns).~This~error~is~fatal. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { too~much~cols~for~matrix } { You~try~to~use~more~columns~than~allowed~by~your~ \@@_full_name_env:.\@@_message_hdotsfor:\ Recall~that~the~maximal~ number~of~columns~for~a~matrix~is~fixed~by~the~LaTeX~counter~ 'MaxMatrixCols'.~Its~actual~value~is~\int_use:N \c@MaxMatrixCols.~ This~error~is~fatal. } % \end{macrocode} % % \medskip % For the following message, remind that the test is not done after the % construction of the array but in each row. That's why we have to put % |\c@jCol-1| and not |\c@jCol|. % \begin{macrocode} \@@_msg_new:nn { too~much~cols~for~array } { You~try~to~use~more~columns~than~allowed~by~your~ \@@_full_name_env:.\@@_message_hdotsfor:\ The~maximal~number~of~columns~is~ \int_use:N \g_@@_static_num_of_col_int\ ~(plus~the~potential~exterior~ones).~ This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { last~col~not~used } { The~key~'last-col'~is~in~force~but~you~have~not~used~that~last~column~ in~your~\@@_full_name_env:.~However,~you~can~go~on. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { columns~not~used } { The~preamble~of~your~\@@_full_name_env:\ announces~\int_use:N \g_@@_static_num_of_col_int\ columns~but~you~use~only~\int_use:N \c@jCol.\\ You~can~go~on~but~the~columns~you~did~not~used~won't~be~created. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { in~first~col } { You~can't~use~the~command~#1 in~the~first~column~(number~0)~of~the~array.\\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { in~last~col } { You~can't~use~the~command~#1 in~the~last~column~(exterior)~of~the~array.\\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { in~first~row } { You~can't~use~the~command~#1 in~the~first~row~(number~0)~of~the~array.\\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { in~last~row } { You~can't~use~the~command~#1 in~the~last~row~(exterior)~of~the~array.\\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { double~closing~delimiter } { You~can't~put~a~second~closing~delimiter~"#1"~just~after~a~first~closing~ delimiter.~This~delimiter~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { delimiter~after~opening } { You~can't~put~a~second~delimiter~"#1"~just~after~a~first~opening~ delimiter.~This~delimiter~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { bad~option~for~line-style } { Since~you~haven't~loaded~Tikz,~the~only~value~you~can~give~to~'line-style'~ is~'standard'.~If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Unknown~key~for~xdots } { As~for~now,~there~is~only~three~keys~available~here:~'color',~'line-style'~ and~'shorten'~(and~you~try~to~use~'\l_keys_key_str').~If~you~go~on,~ this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Unknown~key~for~RowStyle } { As~for~now,~there~is~only~four~keys~available~here:~'cell-space-top-limit',~ 'cell-space-bottom-limit~'cell-space-limits'~and~color~(and~you~try~to~use~ '\l_keys_key_str').~If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Unknown~key~for~rowcolors } { As~for~now,~there~is~only~two~keys~available~here:~'cols'~and~'respect-blocks'~ (and~you~try~to~use~'\l_keys_key_str').~If~you~go~on,~ this~key~will~be~ignored. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { ampersand~in~light-syntax } { You~can't~use~an~ampersand~(\token_to_str:N &)~to~separate~columns~because~ ~you~have~used~the~key~'light-syntax'.~This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { SubMatrix~too~large } { Your~command~\token_to_str:N \SubMatrix\ can't~be~drawn~because~your~matrix~is~too~small.\\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { double-backslash~in~light-syntax } { You~can't~use~\token_to_str:N \\~to~separate~rows~because~you~have~used~ the~key~'light-syntax'.~You~must~use~the~character~'\l_@@_end_of_row_tl'~ (set~by~the~key~'end-of-row').~This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { standard-cline~in~document } { The~key~'standard-cline'~is~available~only~in~the~preamble.\\ If~you~go~on~this~command~will~be~ignored. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { bad~value~for~baseline } { The~value~given~to~'baseline'~(\int_use:N \l_tmpa_int)~is~not~ valid.~The~value~must~be~between~\int_use:N \l_@@_first_row_int\ and~ \int_use:N \g_@@_row_total_int\ or~equal~to~'t',~'c'~or~'b'.\\ If~you~go~on,~a~value~of~1~will~be~used. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Invalid~name~format } { You~can't~give~the~name~'\l_keys_value_tl'~to~a~\token_to_str:N \SubMatrix.\\ A~name~must~be~accepted~by~the~regular~expression~[A-Za-z][A-Za-z0-9]*.\\ If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Wrong~line~in~SubMatrix } { You~try~to~draw~a~#1~line~of~number~'#2'~in~a~ \token_to_str:N \SubMatrix\ of~your~\@@_full_name_env:\ but~that~ number~is~not~valid.~If~you~go~on,~it~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { impossible~delimiter } { It's~impossible~to~draw~the~#1~delimiter~of~your~ \token_to_str:N \SubMatrix\ because~all~the~cells~are~empty~ in~that~column. \bool_if:NT \l_@@_submatrix_slim_bool { ~Maybe~you~should~try~without~the~key~'slim'. } \\ If~you~go~on,~this~\token_to_str:N \SubMatrix\ will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { width~without~X~columns } { You~have~used~the~key~'width'~but~you~have~put~no~'X'~column. \\ If~you~go~on,~that~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { empty~environment } { Your~\@@_full_name_env:\ is~empty.~This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Delimiter~with~small } { You~can't~put~a~delimiter~in~the~preamble~of~your~\@@_full_name_env:\ because~the~key~'small'~is~in~force.\\ This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { unknown~cell~for~line~in~CodeAfter } { Your~command~\token_to_str:N\line\{#1\}\{#2\}~in~the~'code-after'~ can't~be~executed~because~a~cell~doesn't~exist.\\ If~you~go~on~this~command~will~be~ignored. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nnn { Duplicate~name~for~SubMatrix } { The~name~'#1'~is~already~used~for~a~\token_to_str:N \SubMatrix\ in~this~\@@_full_name_env:.\\ If~you~go~on,~this~key~will~be~ignored.\\ For~a~list~of~the~names~already~used,~type~H~. } { The~names~already~defined~in~this~\@@_full_name_env:\ are:~ \seq_use:Nnnn \g_@@_submatrix_names_seq { ~and~ } { ,~ } { ~and~ }. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { r~or~l~with~preamble } { You~can't~use~the~key~'\l_keys_key_str'~in~your~\@@_full_name_env:.~ You~must~specify~the~alignment~of~your~columns~with~the~preamble~of~ your~\@@_full_name_env:.\\ If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Hdotsfor~in~col~0 } { You~can't~use~\token_to_str:N \Hdotsfor\ in~an~exterior~column~of~ the~array.~This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { bad~corner } { #1~is~an~incorrect~specification~for~a~corner~(in~the~keys~ 'corners'~and~'except-corners').~The~available~ values~are:~NW,~SW,~NE~and~SE.\\ If~you~go~on,~this~specification~of~corner~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { bad~border } { #1~is~an~incorrect~specification~for~a~border~(in~the~key~ 'borders'~of~the~command~\token_to_str:N \Block).~The~available~ values~are:~left,~right,~top~and~bottom.\\ If~you~go~on,~this~specification~of~border~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { tikz~key~without~tikz } { You~can't~use~the~key~'tikz'~for~the~command~'\token_to_str:N \Block'~because~you~have~not~loaded~Tikz.~ If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { last-col~non~empty~for~NiceArray } { In~the~\@@_full_name_env:,~you~must~use~the~key~ 'last-col'~without~value.\\ However,~you~can~go~on~for~this~time~ (the~value~'\l_keys_value_tl'~will~be~ignored). } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { last-col~non~empty~for~NiceMatrixOptions } { In~\NiceMatrixoptions,~you~must~use~the~key~ 'last-col'~without~value.\\ However,~you~can~go~on~for~this~time~ (the~value~'\l_keys_value_tl'~will~be~ignored). } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { Block~too~large~1 } { You~try~to~draw~a~block~in~the~cell~#1-#2~of~your~matrix~but~the~matrix~is~ too~small~for~that~block. \\ } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Block~too~large~2 } { The~preamble~of~your~\@@_full_name_env:\ announces~\int_use:N \g_@@_static_num_of_col_int\ columns~but~you~use~only~\int_use:N \c@jCol\ and~that's~why~a~block~ specified~in~the~cell~#1-#2~can't~be~drawn.~You~should~add~some~ampersands~ (&)~at~the~end~of~the~first~row~of~your~ \@@_full_name_env:.\\ If~you~go~on,this~block~and~maybe~others~will~be~ignored. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { unknown~column~type } { The~column~type~'#1'~in~your~\@@_full_name_env:\ is~unknown. \\ This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { tabularnote~forbidden } { You~can't~use~the~command~\token_to_str:N\tabularnote\ ~in~a~\@@_full_name_env:.~This~command~is~available~only~in~ \{NiceTabular\},~\{NiceArray\}~and~\{NiceMatrix\}. \\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { borders~forbidden } { You~can't~use~the~key~'borders'~of~the~command~\token_to_str:N \Block\ because~the~option~'rounded-corners'~ is~in~force~with~a~non-zero~value.\\ If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { bottomrule~without~booktabs } { You~can't~use~the~key~'tabular/bottomrule'~because~you~haven't~ loaded~'booktabs'.\\ If~you~go~on,~this~key~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { enumitem~not~loaded } { You~can't~use~the~command~\token_to_str:N\tabularnote\ ~because~you~haven't~loaded~'enumitem'.\\ If~you~go~on,~this~command~will~be~ignored. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Wrong~last~row } { You~have~used~'last-row=\int_use:N \l_@@_last_row_int'~but~your~ \@@_full_name_env:\ seems~to~have~\int_use:N \c@iRow \ rows.~ If~you~go~on,~the~value~of~\int_use:N \c@iRow \ will~be~used~for~ last~row.~You~can~avoid~this~problem~by~using~'last-row'~ without~value~(more~compilations~might~be~necessary). } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nn { Yet~in~env } { Environments~of~nicematrix~can't~be~nested.\\ This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Outside~math~mode } { The~\@@_full_name_env:\ can~be~used~only~in~math~mode~ (and~not~in~\token_to_str:N \vcenter).\\ This~error~is~fatal. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { One~letter~allowed } { The~value~of~key~'\l_keys_key_str'~must~be~of~length~1.\\ If~you~go~on,~it~will~be~ignored. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~Block } { The~key~'\l_keys_key_str'~is~unknown~for~the~command~\token_to_str:N \Block.\\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~b,~borders,~c,~draw,~fill,~ hvlines,~l,~line-width,~rounded-corners,~r,~t~and~tikz. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~CodeAfter } { The~key~'\l_keys_key_str'~is~unknown.\\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~available~keys~in~\token_to_str:N \CodeAfter,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ delimiters/color,~ rules~(with~the~subkeys~'color'~and~'width'),~ sub-matrix~(several~subkeys)~ and~xdots~(several~subkeys).~ The~latter~is~for~the~command~\token_to_str:N \line. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~SubMatrix } { The~key~'\l_keys_key_str'~is~unknown.\\ If~you~go~on,~this~key~will~be~ignored. \\ For~a~list~of~the~available~keys~in~\token_to_str:N \SubMatrix,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ 'delimiters/color',~ 'extra-height',~ 'hlines',~ 'hvlines',~ 'left-xshift',~ 'name',~ 'right-xshift',~ 'rules'~(with~the~subkeys~'color'~and~'width'),~ 'slim',~ 'vlines'~and~'xshift'~(which~sets~both~'left-xshift'~ and~'right-xshift').\\ } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~notes } { The~key~'\l_keys_key_str'~is~unknown.\\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~available~keys~about~notes,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ bottomrule,~ code-after,~ code-before,~ enumitem-keys,~ enumitem-keys-para,~ para,~ label-in-list,~ label-in-tabular~and~ style. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~NiceMatrixOptions } { The~key~'\l_keys_key_str'~is~unknown~for~the~command~ \token_to_str:N \NiceMatrixOptions. \\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~*principal*~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ allow-duplicate-names,~ cell-space-bottom-limit,~ cell-space-limits,~ cell-space-top-limit,~ code-for-first-col,~ code-for-first-row,~ code-for-last-col,~ code-for-last-row,~ corners,~ create-extra-nodes,~ create-medium-nodes,~ create-large-nodes,~ delimiters~(several~subkeys),~ end-of-row,~ first-col,~ first-row,~ hlines,~ hvlines,~ last-col,~ last-row,~ left-margin,~ letter-for-dotted-lines,~ light-syntax,~ notes~(several~subkeys),~ nullify-dots,~ renew-dots,~ renew-matrix,~ right-margin,~ rules~(with~the~subkeys~'color'~and~'width'),~ small,~ sub-matrix~(several~subkeys), vlines,~ xdots~(several~subkeys). } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~NiceArray } { The~key~'\l_keys_key_str'~is~unknown~for~the~environment~ \{NiceArray\}. \\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~*principal*~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ b,~ baseline,~ c,~ cell-space-bottom-limit,~ cell-space-limits,~ cell-space-top-limit,~ code-after,~ code-for-first-col,~ code-for-first-row,~ code-for-last-col,~ code-for-last-row,~ colortbl-like,~ columns-width,~ corners,~ create-extra-nodes,~ create-medium-nodes,~ create-large-nodes,~ delimiters/color,~ extra-left-margin,~ extra-right-margin,~ first-col,~ first-row,~ hlines,~ hvlines,~ last-col,~ last-row,~ left-margin,~ light-syntax,~ name,~ notes/bottomrule,~ notes/para,~ nullify-dots,~ renew-dots,~ right-margin,~ rules~(with~the~subkeys~'color'~and~'width'),~ small,~ t,~ tabularnote,~ vlines,~ xdots/color,~ xdots/shorten~and~ xdots/line-style. } % \end{macrocode} % % \medskip % This error message is used for the set of keys |NiceMatrix/NiceMatrix| and % |NiceMatrix/pNiceArray| (but not by |NiceMatrix/NiceArray| because, for this % set of keys, there is also the keys |t|, |c| and~|b|). % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~NiceMatrix } { The~key~'\l_keys_key_str'~is~unknown~for~the~ \@@_full_name_env:. \\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~*principal*~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ b,~ baseline,~ c,~ cell-space-bottom-limit,~ cell-space-limits,~ cell-space-top-limit,~ code-after,~ code-for-first-col,~ code-for-first-row,~ code-for-last-col,~ code-for-last-row,~ colortbl-like,~ columns-width,~ corners,~ create-extra-nodes,~ create-medium-nodes,~ create-large-nodes,~ delimiters~(several~subkeys),~ extra-left-margin,~ extra-right-margin,~ first-col,~ first-row,~ hlines,~ hvlines,~ l,~ last-col,~ last-row,~ left-margin,~ light-syntax,~ name,~ nullify-dots,~ r,~ renew-dots,~ right-margin,~ rules~(with~the~subkeys~'color'~and~'width'),~ small,~ t,~ vlines,~ xdots/color,~ xdots/shorten~and~ xdots/line-style. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nnn { Unknown~key~for~NiceTabular } { The~key~'\l_keys_key_str'~is~unknown~for~the~environment~ \{NiceTabular\}. \\ If~you~go~on,~it~will~be~ignored. \\ For~a~list~of~the~*principal*~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ b,~ baseline,~ c,~ cell-space-bottom-limit,~ cell-space-limits,~ cell-space-top-limit,~ code-after,~ code-for-first-col,~ code-for-first-row,~ code-for-last-col,~ code-for-last-row,~ colortbl-like,~ columns-width,~ corners,~ create-extra-nodes,~ create-medium-nodes,~ create-large-nodes,~ extra-left-margin,~ extra-right-margin,~ first-col,~ first-row,~ hlines,~ hvlines,~ last-col,~ last-row,~ left-margin,~ light-syntax,~ name,~ notes/bottomrule,~ notes/para,~ nullify-dots,~ renew-dots,~ right-margin,~ rules~(with~the~subkeys~'color'~and~'width'),~ t,~ tabularnote,~ vlines,~ xdots/color,~ xdots/shorten~and~ xdots/line-style. } % \end{macrocode} % % % \begin{macrocode} \@@_msg_new:nnn { Duplicate~name } { The~name~'\l_keys_value_tl'~is~already~used~and~you~shouldn't~use~ the~same~environment~name~twice.~You~can~go~on,~but,~ maybe,~you~will~have~incorrect~results~especially~ if~you~use~'columns-width=auto'.~If~you~don't~want~to~see~this~ message~again,~use~the~key~'allow-duplicate-names'~in~ '\token_to_str:N \NiceMatrixOptions'.\\ For~a~list~of~the~names~already~used,~type~H~. \\ } { The~names~already~defined~in~this~document~are:~ \seq_use:Nnnn \g_@@_names_seq { ~and~ } { ,~ } { ~and~ }. } % \end{macrocode} % % \begin{macrocode} \@@_msg_new:nn { Option~auto~for~columns-width } { You~can't~give~the~value~'auto'~to~the~key~'columns-width'~here.~ If~you~go~on,~the~key~will~be~ignored. } % \end{macrocode} % % % % \vspace{1cm} % \section{History} % % The successive versions of the file |nicematrix.sty| provided by TeXLive are available on the % \textsc{svn} server of TeXLive: % % \smallskip % { % \small % \nolinkurl{https:www.tug.org/svn/texlive/trunk/Master/texmf-dist/tex/latex/nicematrix/nicematrix.sty} % } % % % \subsection*{Changes between versions 1.0 and 1.1} % % The dotted lines are no longer drawn with Tikz nodes but with Tikz circles % (for efficiency). % % Modification of the code which is now twice faster. % % \subsection*{Changes between versions 1.1 and 1.2} % % New environment |{NiceArray}| with column types |L|, |C| and |R|. % % \subsection*{Changes between version 1.2 and 1.3} % % New environment |{pNiceArrayC}| and its variants. % % Correction of a bug in the definition of |{BNiceMatrix}|, |{vNiceMatrix}| and % |{VNiceMatrix}| (in fact, it was a typo). % % Options are now available locally in |{pNiceMatrix}| and its variants. % % The names of the options are changed. The old names were names in ``camel % style''. % % \subsection*{Changes between version 1.3 and 1.4} % % The column types |w| and |W| can now be used in the environments % |{NiceArray}|, |{pNiceArrayC}| and its variants with the same meaning as in % the package \pkg{array}. % % New option |columns-width| to fix the same width for all the columns of the % array. % % % \subsection*{Changes between version 1.4 and 2.0} % % The versions 1.0 to 1.4 of \pkg{nicematrix} were focused on the continuous % dotted lines whereas the version 2.0 of \pkg{nicematrix} provides different % features to improve the typesetting of mathematical matrices. % % \subsection*{Changes between version 2.0 and 2.1} % % New implementation of the environment |{pNiceArrayRC}|. With this new % implementation, there is no restriction on the width of the columns. % % The package \pkg{nicematrix} no longer loads \pkg{mathtools} but only % \pkg{amsmath}. % % Creation of ``medium nodes'' and ``large nodes''. % % \subsection*{Changes between version 2.1 and 2.1.1} % % Small corrections: for example, the option |code-for-first-row| is now % available in the command |\NiceMatrixOptions|. % % Following a discussion on % TeX StackExchange\footnote{cf. % |tex.stackexchange.com/questions/450841/tikz-externalize-and-nicematrix-package|}, % Tikz externalization is now deactivated in the environments of the % package \pkg{nicematrix}.\footnote{Before this version, there was an error % when using \pkg{nicematrix} with Tikz externalization. In any case, it's not % possible to externalize the Tikz elements constructed by \pkg{nicematrix} % because they use the options |overlay| and |remember picture|.} % % % \subsection*{Changes between version 2.1.2 and 2.1.3} % % When searching the end of a dotted line from a command like |\Cdots| issued in % the ``main matrix'' (not in the exterior column), the cells in the exterior % column are considered as outside the matrix. That means that it's possible to % do the following matrix with only a |\Cdots| command (and a single |\Vdots|). % \[\begin{pNiceArray}{Wc{5mm}cWc{5mm}}[first-row,last-col] % & C_j & \\ % \mbox{\Large $0$} & \Vdots & \mbox{\Large $0$} \\ % \strut & a & \Cdots & L_i \\ % \mbox{\Large $0$} & & \mbox{\Large $0$} \\ % \end{pNiceArray}\] % % \subsection*{Changes between version 2.1.3 and 2.1.4} % % Replacement of some options |O { }| in commands and environments defined with % \pkg{xparse} by |! O { }| (because a recent version of \pkg{xparse} introduced % the specifier |!| and modified the default behaviour of the last optional % arguments). % % See |www.texdev.net/2018/04/21/xparse-optional-arguments-at-the-end| % % \subsection*{Changes between version 2.1.4 and 2.1.5} % % Compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}. % % Option |allow-duplicate-names|. % % \subsection*{Changes between version 2.1.5 and 2.2} % % Possibility to draw horizontal dotted lines to separate rows with the command % |\hdottedline| (similar to the classical command |\hline| and the command % |\hdashline| of \pkg{arydshln}). % % Possibility to draw vertical dotted lines to separate columns with the % specifier ``|:|'' in the preamble (similar to the classical specifier % ``"|"'' and the specifier ``|:|'' of \pkg{arydshln}). % % \subsection*{Changes between version 2.2 and 2.2.1} % % Improvment of the vertical dotted lines drawn by the specifier ``:'' in the % preamble. % % Modification of the position of the dotted lines drawn by |\hdottedline|. % % \subsection*{Changes between version 2.2.1 and 2.3} % % Compatibility with the column type |S| of \pkg{siunitx}. % % Option |hlines|. % % % \subsection*{Changes between version 2.3 and 3.0} % % Modification of |\Hdotsfor|. Now |\Hdotsfor| erases the |\vlines| (of ``"|"'') % as |\hdotsfor| does. % % Composition of exterior rows and columns on the four sides of the matrix (and % not only on two sides) with the options |first-row|, |last-row|, |first-col| % and |last-col|. % % \subsection*{Changes between version 3.0 and 3.1} % % Command |\Block| to draw block matrices. % % Error message when the user gives an incorrect value for |last-row|. % % A dotted line can no longer cross another dotted line (excepted the dotted % lines drawn by |\cdottedline|, the symbol ``|:|'' (in the preamble of the % array) and |\line| in |code-after|). % % The starred versions of |\Cdots|, |\Ldots|, etc. are now deprecated because, % with the new implementation, they become pointless. These starred versions % are no longer documented. % % The vertical rules in the matrices (drawn by ``"|"'') are now compatible with % the color fixed by \pkg{colortbl}. % % Correction of a bug: it was not possible to use the colon ``|:|'' in the % preamble of an array when |pdflatex| was used with \pkg{french-babel} (because % \pkg{french-babel} activates the colon in the beginning of the document). % % % \subsection*{Changes between version 3.1 and 3.2 (and 3.2a)} % % Option |small|. % % \subsection*{Changes between version 3.2 and 3.3} % % The options |first-row|, |last-row|, |first-col| and |last-col| are now % available in the environments |{NiceMatrix}|, |{pNiceMatrix}|, % |{bNiceMatrix}|, etc. % % The option |columns-width=auto| doesn't need any more a second compilation. % % The options |renew-dots|, |renew-matrix| and |transparent| are now available % as package options (as said in the documentation). % % The previous version of \pkg{nicematrix} was incompatible with a recent % version of \pkg{expl3} (released 2019/09/30). This version is compatible. % % % \subsection*{Changes between version 3.3 and 3.4} % % Following a discussion on TeX StackExchange\footnote{cf. % |tex.stackexchange.com/questions/510841/nicematrix-and-tikz-external-optimize|}, % optimization of Tikz externalization is disabled in the environments of % \pkg{nicematrix} when the class \cls{standalone} or the package % \pkg{standalone} is used. % % \subsection*{Changes between version 3.4 and 3.5} % % Correction on a bug on the two previous versions where the |code-after| was % not executed. % % \subsection*{Changes between version 3.5 and 3.6} % % LaTeX counters |iRow| and |jCol| available in the cells of the array. % % Addition of |\normalbaselines| before the construction of the array: in % environments like |{align}| of \pkg{amsmath} the value of |\baselineskip| is % changed and if the options |first-row| and |last-row| were used in an % environment of \pkg{nicematrix}, the position of the delimiters was wrong. % % A warning is written in the |.log| file if an obsolete environment is used. % % There is no longer artificial errors |Duplicate~name| in the environments of % \pkg{amsmath}. % % \subsection*{Changes between version 3.6 and 3.7} % % The four ``corners'' of the matrix are correctly protected against the four % codes: |code-for-first-col|, |code-for-last-col|, |code-for-first-row| and % |code-for-last-row|. % % New command |\pAutoNiceMatrix| and its variants (suggestion of Christophe % Bal). % % \subsection*{Changes between version 3.7 and 3.8} % % New programmation for the command |\Block| when the block has only one row. % With this programmation, the vertical rules drawn by the specifier % ``\verb+|+'' at the end of the block is actually drawn. In previous versions, % they were not because the block of one row was constructed with % |\multicolumn|. % % An error is raised when an obsolete environment is used. % % % \subsection*{Changes between version 3.8 and 3.9} % % New commands |\NiceMatrixLastEnv| and |\OnlyMainNiceMatrix|. % % New options |create-medium-nodes| and |create-large-nodes|. % % \subsection*{Changes between version 3.9 and 3.10} % % New option |light-syntax| (and |end-of-row|). % % New option |dotted-lines-margin| for fine tuning of the dotted lines. % % \subsection*{Changes between versions 3.10 and 3.11} % % Correction of a bug linked to |first-row| and |last-row|. % % \subsection*{Changes between versions 3.11 and 3.12} % % Command |\rotate| in the cells of the array. % % Options |vlines|, |hlines| and |hvlines|. % % Option |baseline| pour |{NiceArray}| (not for the other environments). % % The name of the Tikz nodes created by the command |\Block| has changed: when % the command has been issued in the cell $i$|-|$j$, the name is % $i$|-|$j$|-block| and, if the creation of the ``medium nodes'' is required, a % node $i$|-|$j$|-block-medium| is created. % % If the user tries to use more columns than allowed by its environment, an error % is raised by nicematrix (instead of a low-level error). % % The package must be loaded with the option |obsolete-environments| if we want % to use the deprecated environments. % % \subsection*{Changes between versions 3.12 and 3.13} % % The behaviour of the command |\rotate| is improved when used in the ``last % row''. % % The option |dotted-lines-margin| has been renamed in |xdots/shorten| and the % options |xdots/color| and |xdots/line-style| have been added for a complete % customisation of the dotted lines. % % In the environments without preamble (|{NiceMatrix}|, |{pNiceMatrix}|, etc.), % it's possible to use the options |l| (=|L|) or |r| (=|R|) to specify the type % of the columns. % % The starred versions of the commands |\Cdots|, |\Ldots|, |\Vdots|, |\Ddots| % and |\Iddots| are deprecated since the version 3.1 of \pkg{nicematrix}. Now, % one should load \pkg{nicematrix} with the option |starred-commands| to avoid % an error at the compilation. % % The code of \pkg{nicematrix} no longer uses Tikz but only \textsc{pgf}. By % default, Tikz is \emph{not} loaded by \pkg{nicematrix}. % % \subsection*{Changes between versions 3.13 and 3.14} % % Correction of a bug (question 60761504 on |stackoverflow|). % % Better error messages when the user uses |&| or |\\| when |light-syntax| is in % force. % % \subsection*{Changes between versions 3.14 and 3.15} % % It's possible to put labels on the dotted lines drawn by |\Ldots|, |\Cdots|, % |\Vdots|, |\Ddots|, |\Iddots|, |\Hdotsfor| and the command |\line| in the % |code-after| with the tokens |_| and |^|. % % The option |baseline| is now available in all the environments of % \pkg{nicematrix}. Before, it was available only in |{NiceArray}|. % % New keyword |\CodeAfter| (in the environments of \pkg{nicematrix}). % % % \subsection*{Changes between versions 3.15 and 4.0} % % New environment |{NiceTabular}| % % Commands to color cells, rows and columns with a perfect result in the \textsc{pdf}. % % \subsection*{Changes between versions 4.0 and 4.1} % % New keys |cell-space-top-limit| and |cell-space-bottom-limit| % % New command |\diagbox| % % The key |hvline| don't draw rules in the blocks (commands |\Block|) and in the % virtual blocks corresponding to the dotted lines. % % \subsection*{Changes between versions 4.1 and 4.2} % % It's now possible to write |\begin{pNiceMatrix}a&b\\c&d\end{pNiceMatrix}^2| % with the expected result. % % \subsection*{Changes between versions 4.2 and 4.3} % % The horizontal centering of the content of a |\Block| is correct even when an % instruction such as |!{\qquad}| is used in the preamble of the array. % % It's now possible to use the command |\Block| in the ``last row''. % % \subsection*{Changes between versions 4.3 and 4.4} % % New key |hvlines-except-corners|. % % \subsection*{Changes between versions 4.4 and 5.0} % % Use of the standard column types |l|, |c| and |r| instead of |L|, |C| and |R|. % % It's now possible to use the command |\diagbox| in a |\Block|. % % Command |\tabularnote| % % \subsection*{Changes between versions 5.0 and 5.1} % % The vertical rules specified by \verb+|+ in the preamble are not broken by % |\hline\hline| (and other). % % Environment |{NiceTabular*}| % % Command |\Vdotsfor| similar to |\Hdotsfor| % % The variable |\g_nicematrix_code_after_tl| is now public. % % \subsection*{Changes between versions 5.1 and 5.2} % % The vertical rules specified by \verb+|+ or \verb+||+ in the preamble respect % the blocks. % % Key |respect-blocks| for |\rowcolors| (with a \emph{s}) in the |code-before|. % % The variable |\g_nicematrix_code_before_tl| is now public. % % The key |baseline| may take in as value an expression of the form % \textsl{line-i} to align the |\hline| in the row \textsl{i}. % % The key |hvlines-except-corners| may take in as value a list of corners (eg: NW,SE). % % \subsection*{Changes between versions 5.2 and 5.3} % % Keys |c|, |r| and |l| for the command |\Block|. % % It's possible to use the key |draw-first| with |\Ddots| and |\Iddots| to % specify which dotted line will be drawn first (the other lines will be drawn % parallel to that one if parallelization is activated). % % \subsection*{Changes between versions 5.3 and 5.4} % % Key |tabularnote|. % % Different behaviour for the mono-column blocks. % % \subsection*{Changes between versions 5.4 and 5.5} % % The user must never put |\omit| before |\CodeAfter|. % % Correction of a bug: the tabular notes |\tabularnotes| were not composed when % present in a block (except a mono-column block). % % \subsection*{Changes between versions 5.5 and 5.6} % % Different behaviour for the mono-row blocks. % % New command |\NotEmpty|. % % \subsection*{Changes between versions 5.6 and 5.7} % % New key |delimiters-color| % % Keys |fill|, |draw| and |line-width| for the command |\Block|. % % \subsection*{Changes between versions 5.7 and 5.8} % % Keys |cols| and |restart| of the command |\rowcolors| in the |code-before|. % % Modification of the behaviour of |\\| in the columns of type |p|, |m| or |b| % (for a behaviour similar to the environments of \pkg{array}). % % Better error messages for the command |\Block|. % % \subsection*{Changes between versions 5.8 and 5.9} % % Correction of a bug: in the previous versions, it was not possible to use the % key |line-style| for the continuous dotted lines when the Tikz library |babel| % was loaded. % % New key |cell-space-limits|. % % \subsection*{Changes between versions 5.9 and 5.10} % % New command |\SubMatrix| available in the |\CodeAfter|. % % It's possible to provide options (between brackets) to the keyword |\CodeAfter|. % % A (non fatal) error is raised when the key |transparent|, which is % deprecated, is used. % % \subsection*{Changes between versions 5.10 and 5.11} % % It's now possible, in the |code-before| and in the |\CodeAfter|, to use the % syntax \verb+|(i-|j)+ for the Tikz node at the intersection of the (potential) % horizontal rule number~$i$ and the (potential) vertical rule number~$j$. % % \subsection*{Changes between versions 5.11 and 5.12} % % Keywords |\CodeBefore| and |\Body| (alternative syntax to the key % |code-before|). % % New key |delimiters/max-width|. % % New keys |hlines|, |vlines| and |hvlines| for the command |\SubMatrix| in the % |\CodeAfter|. % % New key |rounded-corners| for the command |\Block|. % % \subsection*{Changes between versions 5.12 and 5.13} % % New command |\arraycolor| in the |\CodeBefore| (with its key % |except-corners|). % % New key |borders| for the command |\Block|. % % New command |\Hline| (for horizontal rules not drawn in the blocks). % % The keys |vlines| and |hlines| takes in as value a (comma-separated) list of % numbers (for the rules to draw). % % % \subsection*{Changes between versions 5.13 and 5.14} % % Nodes of the form |(1.5)|, |(2.5)|, |(3.5)|, etc. % % Keys |t| and |b| for the command |\Block|. % % Key |corners|. % % \subsection*{Changes between versions 5.14 and 5.15} % % Key |hvlines| for the command |\Block|. % % The commands provided by \pkg{nicematrix} to color cells, rows and columns % don't color the cells which are in the ``corners'' (when the key |corner| is % used). % % It's now possible to specify delimiters for submatrices in the preamble of an % environment. % % The version 5.15b is compatible with the version 3.0+ of \pkg{siunitx} % (previous versions were not). % % \subsection*{Changes between versions 5.15 and 5.16} % % It's now possible to use the cells corresponding to the contents of the nodes % (of the form |i-j|) in the |\CodeBefore| when the key |create-cell-nodes| of % that |\CodeBefore| is used. The medium and the large nodes are also available % if the corresponding keys are used. % % \subsection*{Changes between versions 5.16 and 5.17} % % The key |define-L-C-R| (only available at load-time) now raises a (non fatal) % error. % % Keys |L|, |C| and |R| for the command |\Block|. % % Key |hvlines-except-borders|. % % It's now possible to use a key |l|, |r| or |c| with the command % |\pAutoNiceMatrix| (and the similar ones). % % \subsection*{Changes between versions 5.17 and 5.18} % % New command |\RowStyle| % % \subsection*{Changes between versions 5.18 and 5.19} % % New key |tikz| for the command |\Block|. % % % \subsection*{Changes between versions 5.19 and 6.0} % % Columns |X| and environment |{NiceTabularX}|. % % Command |\rowlistcolors| available in the |\CodeBefore|. % % In columns with fixed width, the blocks are composed as paragraphs (wrapping % of the lines). % % The key |define-L-C-R| has been deleted. % % % \subsection*{Changes between versions 6.0 and 6.1} % % Better computation of the widths of the |X| columns. % % Key |\color| for the command |\RowStyle|. % % % \PrintIndex % % \tableofcontents % % \endinput % Local Variables: % TeX-fold-mode: t % TeX-fold-preserve-comments: nil % flyspell-mode: nil % fill-column: 80 % End: