From 95bdae3d8a40af1f2f82f786dc29d3761fe431f1 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 16 May 2023 03:01:57 +0000 Subject: CTAN sync 202305160301 --- macros/latex/contrib/nicematrix/README.md | 2 +- .../latex/contrib/nicematrix/nicematrix-code.dtx | 16060 +++++++++++++ .../latex/contrib/nicematrix/nicematrix-code.pdf | Bin 0 -> 909639 bytes .../latex/contrib/nicematrix/nicematrix-french.pdf | Bin 553017 -> 577804 bytes .../latex/contrib/nicematrix/nicematrix-french.tex | 616 +- macros/latex/contrib/nicematrix/nicematrix.dtx | 23021 ------------------- macros/latex/contrib/nicematrix/nicematrix.ins | 2 +- macros/latex/contrib/nicematrix/nicematrix.pdf | Bin 1380299 -> 571224 bytes macros/latex/contrib/nicematrix/nicematrix.tex | 7484 ++++++ 9 files changed, 24057 insertions(+), 23128 deletions(-) create mode 100644 macros/latex/contrib/nicematrix/nicematrix-code.dtx create mode 100644 macros/latex/contrib/nicematrix/nicematrix-code.pdf delete mode 100644 macros/latex/contrib/nicematrix/nicematrix.dtx create mode 100644 macros/latex/contrib/nicematrix/nicematrix.tex (limited to 'macros/latex/contrib/nicematrix') diff --git a/macros/latex/contrib/nicematrix/README.md b/macros/latex/contrib/nicematrix/README.md index 5822e17e0e..da760d4374 100644 --- a/macros/latex/contrib/nicematrix/README.md +++ b/macros/latex/contrib/nicematrix/README.md @@ -19,7 +19,7 @@ The package `nicematrix` is present in the distributions MiKTeX, TeXLive and Mac For a manual installation: -* put the files `nicematrix.ins` and `nicematrix.dtx` in the same directory; +* put the files `nicematrix.ins` and `nicematrix-code.dtx` in the same directory; * run `latex nicematrix.ins` in that directory. The file `nicematrix.sty` will be generated. diff --git a/macros/latex/contrib/nicematrix/nicematrix-code.dtx b/macros/latex/contrib/nicematrix/nicematrix-code.dtx new file mode 100644 index 0000000000..4c28160949 --- /dev/null +++ b/macros/latex/contrib/nicematrix/nicematrix-code.dtx @@ -0,0 +1,16060 @@ +% \iffalse meta-comment +% +% This file should be compiled with $xelatex$. +% +% Copyright (C) 2018-2023 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.19} +\def\myfiledate{2023/05/15} +% +% +%<*batchfile> +\begingroup +\input l3docstrip.tex +\keepsilent +\usedir{tex/latex/nicematrix} +\preamble + + +Copyright (C) 2018-2023 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} +\usepackage{nicematrix} + +\NewDocumentEnvironment {scope} {} {} {} +\def\interitem{\vspace{7mm plus 2 mm minus 3mm}} + +\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} +\parindent 0pt +\skip \footins = 2 \bigskipamount + + +\begin{document} +\DocInput{nicematrix-code.dtx} +\end{document} +% +% \fi +% \title{The code of 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 code of the package 'nicematrix' , +% Subject = A LaTeX package , +% Author = F. Pantigny +% } +% } +% +% +% \maketitle +% +% \begin{abstract} +% This document is the documented code of the LaTeX package \pkg{nicematrix}. It +% is \emph{not} its user's guide. The guide of utilisation is the document +% |nicematrix.pdf| (with a French traduction: |nicematrix-french.pdf|). +% \end{abstract} +% +% +% \bigskip +% 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}. 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 +% \section{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. +% \begin{macrocode} +\RequirePackage { array } +\RequirePackage { amsmath } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_error:n { \msg_error:nn { nicematrix } } +\cs_new_protected:Npn \@@_warning:n { \msg_warning:nn { nicematrix } } +\cs_new_protected:Npn \@@_error:nn { \msg_error:nnn { nicematrix } } +\cs_generate_variant:Nn \@@_error:nn { n x } +\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 } } +% \end{macrocode} +% +% With Overleaf, a document is compiled in non-stop mode. When there is an +% error, there is no way to the user to use the key H in order to have more +% information. That's why we decide to put that piece of information (for the +% messages with such information) in the main part of the message when the key +% |messages-for-Overleaf| is used (at load-time). +% \begin{macrocode} +\cs_new_protected:Npn \@@_msg_new:nnn #1 #2 #3 + { + \bool_if:NTF \c_@@_messages_for_Overleaf_bool + { \msg_new:nnn { nicematrix } { #1 } { #2 \\ #3 } } + { \msg_new:nnnn { nicematrix } { #1 } { #2 } { #3 } } + } +% \end{macrocode} +% +% \bigskip +% We also create a command which will genereate usually an error but only a +% warning on Overleaf. The argument is given by currification. +% \begin{macrocode} +\cs_new_protected:Npn \@@_error_or_warning:n + { \bool_if:NTF \c_@@_messages_for_Overleaf_bool \@@_warning:n \@@_error:n } +% \end{macrocode} +% +% We try to detect whether the compilation is done on Overleaf. We use +% |\c_sys_jobname_str| because, with Overleaf, the value of |\c_sys_jobname_str| +% is always ``|output|''. +% \begin{macrocode} +\bool_set:Nn \c_@@_messages_for_Overleaf_bool + { + \str_if_eq_p:Vn \c_sys_jobname_str { _region_ } % for Emacs + || \str_if_eq_p:Vn \c_sys_jobname_str { output } % for Overleaf + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_msg_redirect_name:nn + { \msg_redirect_name:nnn { nicematrix } } +\cs_new_protected:Npn \@@_gredirect_none:n #1 + { + \group_begin: + \globaldefs = 1 + \@@_msg_redirect_name:nn { #1 } { none } + \group_end: + } +\cs_new_protected:Npn \@@_err_gredirect_none:n #1 + { + \@@_error:n { #1 } + \@@_gredirect_none:n { #1 } + } +\cs_new_protected:Npn \@@_warning_gredirect_none:n #1 + { + \@@_warning:n { #1 } + \@@_gredirect_none:n { #1 } + } +% \end{macrocode} +% +% \bigskip +% \section{Security test} +% +% Within the package \pkg{nicematrix}, we will have to test whether a cell of a +% |{NiceTabular}| is empty. For the cells of the columns of type |p|, |b|, |m|, +% |X| and |V|, we will test whether the cell is syntactically empty (that is to +% say that there is only spaces between the ampersands |&|). That test will be +% done with the command |\@@_test_if_empty:| by testing if the two first tokens +% in the cells are (during the TeX process) are |\ignorespaces| and |\unskip|. +% +% However, if, one day, there is a changement in the implementation of +% \pkg{array}, maybe that this test will be broken (and \pkg{nicematrix} also). +% +% That's why, by security, we will take a test in a small |{tabular}| composed +% in the box |\l_tmpa_box| used as sandbox. +% +% \begin{macrocode} +\@@_msg_new:nn { Internal~error } + { + Potential~problem~when~using~nicematrix.\\ + The~package~nicematrix~have~detected~a~modification~of~the~ + standard~environment~{array}~(of~the~package~array).~Maybe~you~will~encounter~ + some~slight~problems~when~using~nicematrix.~If~you~don't~want~to~see~ + this~message~again,~load~nicematrix~with:~\token_to_str:N + \usepackage[no-test-for-array]{nicematrix}. + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\@@_msg_new:nn { mdwtab~loaded } + { + The~packages~'mdwtab'~and~'nicematrix'~are~incompatible.~ + This~error~is~fatal. + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_security_test:n #1 + { + \peek_meaning:NTF \ignorespaces + { \@@_security_test_i:w } + { \@@_error:n { Internal~error } } + #1 + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_security_test_i:w \ignorespaces #1 + { + \peek_meaning:NF \unskip { \@@_error:n { Internal~error } } + #1 + } +% \end{macrocode} +% +% \bigskip +% Here, the box |\l_tmpa_box| will be used as sandbox to take our security test. +% This code has been modified in version 6.18 (see question 682891 on TeX +% StackExchange). +% \begin{macrocode} +\hook_gput_code:nnn { begindocument / after } { . } + { + \IfPackageLoadedTF { mdwtab } + { \@@_fatal:n { mdwtab~loaded } } + { + \bool_if:NF \c_@@_no_test_for_array_bool + { + \group_begin: + \hbox_set:Nn \l_tmpa_box + { + \begin { tabular } { c > { \@@_security_test:n } c c } + text & & text + \end { tabular } + } + \group_end: + } + } + } +% \end{macrocode} +% +% \bigskip +% \section{Technical definitions} +% +% \begin{macrocode} +\tl_new:N \l_@@_argspec_tl +% \end{macrocode} +% +% \begin{macrocode} +\cs_generate_variant:Nn \seq_set_split:Nnn { N V n } +\cs_generate_variant:Nn \keys_define:nn { n x } +\cs_generate_variant:Nn \str_lowercase:n { V } +% \end{macrocode} +% +% \medskip +% \begin{macrocode} +\hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { 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. The tokens +% |\exp_not:N| are mandatory. +% \begin{macrocode} + \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 March 2023, the current +% version \cls{revtex4-2} is 4.2e (compatible with \pkg{booktabs}). +% +% \begin{macrocode} +\@ifclassloaded { revtex4-1 } + { \bool_const:Nn \c_@@_revtex_bool \c_true_bool } + { + \@ifclassloaded { revtex4-2 } + { \bool_const:Nn \c_@@_revtex_bool \c_true_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_const:Nn \c_@@_revtex_bool \c_true_bool } + { \bool_const:Nn \c_@@_revtex_bool \c_false_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} +\hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { 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} +\hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { colortbl } + { } + { +% \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 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 { \int_eval:n { #1 - 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} or the form +% \textsl{i}. +% \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 + { + \tl_if_empty:nTF { #3 } + { \@@_cline_iii:w #1|#2-#2 \q_stop } + { \@@_cline_ii:w #1|#2-#3 \q_stop } + } +\cs_set:Npn \@@_cline_ii:w #1|#2-#3-\q_stop + { \@@_cline_iii:w #1|#2-#3 \q_stop } +\cs_set:Npn \@@_cline_iii: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 { \int_eval:n { #3 + 1 } } } + { \everycr { } \cr } + } +\cs_generate_variant:Nn \@@_cline_i:nn { e n } +% \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@:n #1 + { + \tl_if_blank:nF { #1 } + { + \tl_if_head_eq_meaning:nNTF { #1 } [ + { \cs_set:Npn \CT@arc@ { \color #1 } } + { \cs_set:Npn \CT@arc@ { \color { #1 } } } + } + } +\cs_generate_variant:Nn \@@_set_CT@arc@:n { V } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_CT@drsc@:n #1 + { + \tl_if_head_eq_meaning:nNTF { #1 } [ + { \cs_set:Npn \CT@drsc@ { \color #1 } } + { \cs_set:Npn \CT@drsc@ { \color { #1 } } } + } +\cs_generate_variant:Nn \@@_set_CT@drsc@:n { V } +% \end{macrocode} +% +% \bigskip +% The following command must \emph{not} be protected since it will be used to +% write instructions in the (internal) |\CodeBefore|. +% \begin{macrocode} +\cs_new:Npn \@@_exp_color_arg:Nn #1 #2 + { + \tl_if_head_eq_meaning:nNTF { #2 } [ + { #1 #2 } + { #1 { #2 } } + } +\cs_generate_variant:Nn \@@_exp_color_arg:Nn { N V } +% \end{macrocode} +% +% The following command must be protected because of its use of the command |\color|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_color:n #1 + { \tl_if_blank:nF { #1 } { \@@_exp_color_arg:Nn \color { #1 } } } +\cs_generate_variant:Nn \@@_color:n { V } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_set_eq:NN \@@_old_pgfpointanchor \pgfpointanchor +% \end{macrocode} +% +% \bigskip +% \textbf{The column S of siunitx}\par\nobreak +% +% 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} +\hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { siunitx } + { + \cs_new_protected:Npn \@@_renew_NC@rewrite@S: + { + \renewcommand*{\NC@rewrite@S}[1][] + { +% \end{macrocode} +% |\@temptokena| is a toks (not supported by the L3 programming layer). +% \begin{macrocode} + \tl_if_empty:nTF { ##1 } + { + \@temptokena \exp_after:wN + { \tex_the:D \@temptokena \@@_S: } + } + { + \@temptokena \exp_after:wN + { \tex_the:D \@temptokena \@@_S: [ ##1 ] } + } + \NC@find + } + } + } + { \cs_set_eq:NN \@@_renew_NC@rewrite@S: \prg_do_nothing: } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_rescan_for_spanish:N #1 + { + \tl_set_rescan:Nno + #1 + { + \char_set_catcode_other:N > + \char_set_catcode_other:N < + } + #1 + } +% \end{macrocode} +% +% \bigskip +% \section{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 +% It's possible to put tabular notes (with |\tabularnote|) in the caption if +% that caption is composed \emph{above} the tabular. In such case, we will count +% in |\g_@@_notes_caption_int| the number of uses of the command +% |\tabularnote| \emph{without optional argument} in that caption. +% \begin{macrocode} +\int_new:N \g_@@_notes_caption_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 parameter will be used by |\@@_create_row_node:| to avoid to +% create the same row-node twice (at the end of the array). +% \begin{macrocode} +\int_new:N \g_@@_last_row_node_int +% \end{macrocode} +% +% \bigskip +% The following counter corresponds to the key |nb-rows| of the command +% |\RowStyle|. +% \begin{macrocode} +\int_new:N \l_@@_key_nb_rows_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 example, 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 for the mono-row blocks. +% \begin{macrocode} +\dim_new:N \g_@@_blocks_ht_dim +\dim_new:N \g_@@_blocks_dp_dim +% \end{macrocode} +% +% \bigskip +% The following dimension will be used by the command |\Block| for the blocks +% with a key of vertical position equal to |T| or |B|. +% \begin{macrocode} +\dim_new:N \l_@@_block_ysep_dim +% \end{macrocode} +% +% \bigskip +% The following dimension correspond to the key |width| (which may be fixed in +% |\NiceMatrixOptions| but also in an environment |{NiceTabular}|). +% \begin{macrocode} +\dim_new:N \l_@@_width_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 +% The following key corresponds to the key |notes/detect_duplicates|. +% \begin{macrocode} +\bool_new:N \l_@@_notes_detect_duplicates_bool +\bool_set_true:N \l_@@_notes_detect_duplicates_bool +% \end{macrocode} +% +% \bigskip +% If the user uses |{NiceArray}| or |{NiceTabular}| the flag +% |\g_@@_NiceArray_bool| will be raised. +% \begin{macrocode} +\bool_new:N \g_@@_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}|, |{NiceTabular*}| or |{NiceTabularX}|, 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 +% The following dimension will be used for the total width of composite rules +% (\emph{total} means that the spaces on both sides are included). +% \begin{macrocode} +\dim_new:N \l_@@_rule_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} +% +% \begin{macrocode} +\bool_new:N \g_@@_caption_finished_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 +% The following parameter corresponds to the key |columns-type| of the +% environments |{NiceMatrix}|, |{pNiceMatrix}|, etc. and also the key +% |matrix / columns-type| of |\NiceMatrixOptions|. However, it does \emph{not} +% contain the value provided by the final user. Indeed, a transformation is done +% in order to have a preamble (for the package \pkg{array}) which is +% nicematrix-aware. That transformation is done with the command +% |\@@_set_preamble:Nn|. +% \begin{macrocode} +\tl_new:N \l_@@_columns_type_tl +\hook_gput_code:nnn { begindocument } { . } + { \@@_set_preamble:Nn \l_@@_columns_type_tl { c } } +% \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_new:N \g_@@_com_or_env_str +\tl_gset: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|). +% That parameter is \emph{public}. +% \begin{macrocode} +\tl_new:N \g_nicematrix_code_after_tl +\bool_new:N \l_@@_in_code_after_bool +% \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 +% For the key |pgf-node-code|. That code will be used when the nodes of the +% cells (that is to say the nodes of the form |i-j|) will be created. +% \begin{macrocode} +\tl_new:N \l_@@_pgf_node_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_@@_pre_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_@@_pre_code_after_tl +% \end{macrocode} +% +% \bigskip +% The value of the key |code-before| will be added to the left of +% |\g_@@_pre_code_before_tl|. Idem for the code between |\CodeBefore| and +% |\Body|. +% \begin{macrocode} +\tl_new:N \g_nicematrix_code_before_tl +\tl_new:N \g_@@_pre_code_before_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 sequence will contain the names (without backslash) of the +% commands created by |custom-line| by the key |command| or |ccommand| (commands +% used by the final user in order to draw horizontal rules). +% \begin{macrocode} +\seq_new:N \l_@@_custom_line_commands_seq +% \end{macrocode} +% +% \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 an 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 the 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. +% \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 five components: +% |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}{|% +% \textsl{name}|}|. 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 five components: +% |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}{|% +% \textsl{name}|}|. +% \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|, 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| is used in an environment +% |{NiceTabular}| (not in a command |\NiceMatrixOptions|). 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 |\CodeBefore| (and not in the |\CodeAfter|). It will contain the position of +% all the sub-matrices specified in the |\CodeBefore|. Each sub-matrix is +% represented by an ``object'' of the form |{|$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 dimension corresponds to the key |rounded-corners| available in +% an individual environment |{NiceTabular}|. When that key is used, a clipping +% is applied in the |\CodeBefore| of the environment in order to have rounded +% corners for the potential colored panels. +% \begin{macrocode} +\dim_new:N \l_@@_tab_rounded_corners_dim +% \end{macrocode} +% +% \medskip +% The following token list correspond to the key |color| of the command |\Block| +% and also the key |color| of the command |\RowStyle|. +% \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} +\str_new:N \l_@@_vpos_of_block_str +\str_set:Nn \l_@@_vpos_of_block_str { 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 keys |vlines| and |hlines| of the +% command |\Block| (the key |hvlines| is the conjunction of both). +% \begin{macrocode} +\bool_new:N \l_@@_vlines_block_bool +\bool_new:N \l_@@_hlines_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} +% +% \medskip +% The following key is set when the keys |hvlines| and |hvlines-except-borders| +% are used. It's used only to change slightly the clipping path set by the key +% |rounded-corners| (for a |{tabular}|). +% \begin{macrocode} +\bool_new:N \l_@@_hvlines_bool +% \end{macrocode} +% +% +% +% \bigskip +% The following flag will be used by (for instance) |\@@_vline_ii:|. +% When |\l_@@_dotted_bool| is |true|, a dotted line (with our system) will be drawn. +% \begin{macrocode} +\bool_new:N \l_@@_dotted_bool +% \end{macrocode} +% +% \bigskip +% The following flag will be set to true during the composition of a caption +% specified (by the key |caption|). +% \begin{macrocode} +\bool_new:N \l_@@_in_caption_bool +% \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 +% \textbf{Some utilities} +% +% \medskip +% \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} +% +% +% The following takes as argument the name of a |clist| and which should be a +% list of intervals of integers. It \emph{expands} that list, that is to say, +% it replaces (by a sort of |mapcan| or |flat_map|) the interval by the explicit +% list of the integers. +% \begin{macrocode} +\cs_new_protected:Npn \@@_expand_clist:N #1 + { + \clist_if_in:NnF #1 { all } + { + \clist_clear:N \l_tmpa_clist + \clist_map_inline:Nn #1 + { + \tl_if_in:nnTF { ##1 } { - } + { \@@_cut_on_hyphen:w ##1 \q_stop } + { + \tl_set:Nn \l_tmpa_tl { ##1 } + \tl_set:Nn \l_tmpb_tl { ##1 } + } + \int_step_inline:nnn { \l_tmpa_tl } { \l_tmpb_tl } + { \clist_put_right:Nn \l_tmpa_clist { ####1 } } + } + \tl_set_eq:NN #1 \l_tmpa_clist + } + } +% \end{macrocode} +% +% \bigskip +% \section{The command \textbackslash tabularnote} +% +% \bigskip +% Of course, it's possible to use |\tabularnote| in the main tabular. But there +% is also the possibility to use that command in the caption of the tabular. And +% the caption may be specified by two means: +% +% \begin{itemize} +% \item The caption may of course be provided by the command |\caption| in a +% floating environment. Of course, a command |\tabularnote| in that |\caption| +% makes sens only if the |\caption| is \emph{before} the |{tabular}|. +% \item It's also possible to use |\tabularnote| in the value of the key +% |caption| of the |{NiceTabular}| when the key |caption-above| is in force. +% However, in that case, one must remind that the caption is composed +% \emph{after} the composition of the box which contains the main tabular +% (that's mandatory since that caption must be wrapped with a line width equal +% to the width ot the tabular). However, we want the labels of the successive +% tabular notes in the logical order. That's why: +% \begin{itemize} +% \item The number of tabular notes present in the caption will be written on +% the |aux| file and available in |\g_@@_notes_caption_int|.\footnote{More +% precisely, it's the number of tabular notes which do not use the optional +% argument of |\tabularnote|.} +% \item During the composition of the main tabular, the tabular notes will be +% numbered from |\g_@@_notes_caption_int|+1 and the notes will be stored in +% |\g_@@_notes_seq|. Each composant of |\g_@@_notes_seq| will be a kind of +% couple of the form : \texttt{\{\textsl{label}\}\{\textsl{text of the +% tabularnote}\}}. The first composante is the optional argument (between square +% brackets) of the command |\tabularnote| (if the optional argument is not used, +% the value will be the special marker |\c_novalue_tl|). +% \item During the composition of the caption (value of |\l_@@_caption_tl|), the +% tabular notes will be numbered from $1$ to |\g_@@_notes_caption_int| and the +% notes themselves will be stored in |\g_@@_notes_in_caption_seq|. The structure +% of the composantes of that sequence will be the same as for |\g_@@_notes_seq|. +% \item After the composition of the main tabular and after the composition of +% the caption, the sequences |\g_@@_notes_in_caption_seq| and |\g_@@_notes_seq| +% will be merged (in that order) and the notes will be composed. +% \end{itemize} +% \end{itemize} +% +% +% \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} +% +% \begin{macrocode} +\seq_new:N \g_@@_notes_seq +\seq_new:N \g_@@_notes_in_caption_seq +% \end{macrocode} +% +% \bigskip +% Before the actual tabular notes, it's possible to put a text +% specified by the key |tabularnote| of the environment. The token list +% |\g_@@_tabularnote_tl| corresponds to the value of that key. +% \begin{macrocode} +\tl_new:N \g_@@_tabularnote_tl +% \end{macrocode} +% +% \bigskip +% We prepare the tools for the formatting of the references of the footnotes (in +% the tabular itself). There may have several references of footnote at the same +% point and we have to take into account that point. +% \begin{macrocode} +\seq_new:N \l_@@_notes_labels_seq +\newcounter{nicematrix_draft} +\cs_new_protected:Npn \@@_notes_format:n #1 + { + \setcounter { nicematrix_draft } { #1 } + \@@_notes_style:n { nicematrix_draft } + } +% \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 tabular 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} +\hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { enumitem } + { +% \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} +% +% \bigskip +% One must remind that we have allowed a |\tabular| in the caption and +% that caption may also be found in the list of tables (|\listoftables|). We +% want the command |\tabularnote| be no-op during the composition of that list. +% That's why we program |\tabularnote| to be no-op excepted in a floating +% environment or in an environment of \pkg{nicematrix}. +% \begin{macrocode} + \NewDocumentCommand \tabularnote { o m } + { + \bool_if:nT { \cs_if_exist_p:N \@captype || \l_@@_in_env_bool } + { + \bool_if:nTF { ! \l_@@_NiceTabular_bool && \l_@@_in_env_bool } + { \@@_error:n { tabularnote~forbidden } } + { + \bool_if:NTF \l_@@_in_caption_bool + { \@@_tabularnote_caption:nn { #1 } { #2 } } + { \@@_tabularnote:nn { #1 } { #2 } } + } + } + } + } + { + \NewDocumentCommand \tabularnote { o m } + { + \@@_error_or_warning:n { enumitem~not~loaded } + \@@_gredirect_none:n { enumitem~not~loaded } + } + } + } +% \end{macrocode} +% +% \bigskip +% For the version in normal conditions, that is to say not in the |caption|. +% |#1| is the optional argument of |\tabularnote| (maybe equal to the special +% marker |\c_novalue_tl|) and |#2| is the mandatory argument of |\tabularnote|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_tabularnote:nn #1 #2 + { +% \end{macrocode} +% You have to see whether the argument of |\tabularnote| has yet been used as +% argument of another |\tabularnote| in the same tabular. In that case, there +% will be only one note (for both commands |\tabularnote|) at the end of the +% tabular. We search the argument of our command |\tabularnote| in +% |\g_@@_notes_seq|. The position in the sequence will be stored in +% |\l_tmpa_int| (0 if the text is not in the sequence yet). +% \begin{macrocode} + \int_zero:N \l_tmpa_int + \bool_if:NT \l_@@_notes_detect_duplicates_bool + { +% \end{macrocode} +% We recall that each component of |\g_@@_notes_seq| is a kind of couple of the form +% \begin{center} +% \texttt{\{\textsl{label}\}\{\textsl{text of the tabularnote}\}}. +% \end{center} +% If the user have used |\tabularnote| without the optional argument, the +% \texttt{\textsl{label}} will be the special marker |\c_novalue_tl|. +% \begin{macrocode} + \seq_map_indexed_inline:Nn \g_@@_notes_seq + { + \tl_if_eq:nnT { { #1 } { #2 } } { ##2 } + { \int_set:Nn \l_tmpa_int { ##1 } \seq_map_break: } + } + \int_compare:nNnF \l_tmpa_int = \c_zero_int + { \int_add:Nn \l_tmpa_int \g_@@_notes_caption_int } + } + \int_compare:nNnT \l_tmpa_int = \c_zero_int + { + \seq_gput_right:Nn \g_@@_notes_seq { { #1 } { #2 } } + \tl_if_novalue:nT { #1 } { \int_gincr:N \c@tabularnote } + } + \seq_put_right:Nx \l_@@_notes_labels_seq + { + \tl_if_novalue:nTF { #1 } + { + \@@_notes_format:n + { + \int_eval:n + { + \int_compare:nNnTF \l_tmpa_int = \c_zero_int + \c@tabularnote + \l_tmpa_int + } + } + } + { #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 an 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 +% put the labels in a |\textsuperscript|. +% \begin{macrocode} + \@@_notes_label_in_tabular:n + { + \seq_use:Nnnn + \l_@@_notes_labels_seq { , } { , } { , } + } + } +% \end{macrocode} +% We want the (last) tabular note referenceable (with the standard command |\label|). +% \begin{macrocode} + \int_gsub:Nn \c@tabularnote { 1 } + \int_set_eq:NN \l_tmpa_int \c@tabularnote + \refstepcounter { tabularnote } + \int_compare:nNnT \l_tmpa_int = \c@tabularnote + { \int_gincr:N \c@tabularnote } + \seq_clear:N \l_@@_notes_labels_seq + \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} +% +% \bigskip +% Now the version when the command is used in the key |caption|. The main +% difficulty is that the argument of the command |\caption| is composed several +% times. In order to know the number of commands |\tabularnote| in the caption, +% we will consider that there should not be the same tabular note twice in the +% caption (in the main tabular, it's possible). Once we have found a tabular +% note which has yet been encountered, we consider that you are in a new +% composition of the argument of |\caption|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_tabularnote_caption:nn #1 #2 + { + \bool_if:NTF \g_@@_caption_finished_bool + { + \int_compare:nNnT + \c@tabularnote = \g_@@_notes_caption_int + { \int_gzero:N \c@tabularnote } +% \end{macrocode} +% Now, we try to detect duplicate notes in the caption. +% \begin{macrocode} + \bool_set_false:N \l_tmpa_bool + \seq_map_inline:Nn \g_@@_notes_in_caption_seq + { \@@_if_eq_two_three:nnn ##1 { #2 } } +% \end{macrocode} +% Be careful! We must put |\bool_if:NF| and not |\bool_if:NT|! +% \begin{macrocode} + \bool_if:NF \l_tmpa_bool + { \@@_error:n { Identical~notes~in~caption } } + } + { +% \end{macrocode} +% In the following code, we are in the first composition of the caption or at +% the first |\tabularnote| of the second composition. We have +% to see whether the text of our tabular note is among the texts of the +% tabularnotes stored in |\g_@@_notes_in_caption_seq|. For that, we will loop on +% |\g_@@_notes_in_caption_seq| and we will raise |\l_tmpa_bool| if the text is found. +% \begin{macrocode} + \bool_set_false:N \l_tmpa_bool + \seq_map_inline:Nn \g_@@_notes_in_caption_seq + { \@@_if_eq_two_three:nnn ##1 { #2 } } + \bool_if:NTF \l_tmpa_bool + { +% \end{macrocode} +% Now, we known that are in the second composition of the caption since we are +% reading a tabular note which has yet been read. Now, the value of +% |\g_@@_notes_caption_int| won't change anymore: it's the number of uses +% \emph{without optional argument} of the command |\tabularnote| in the caption. +% \begin{macrocode} + \bool_gset_true:N \g_@@_caption_finished_bool + \int_gset_eq:NN \g_@@_notes_caption_int \c@tabularnote + \int_gzero:N \c@tabularnote + } + { \seq_gput_right:Nn \g_@@_notes_in_caption_seq { { #1 } { #2 } } } + } +% \end{macrocode} +% Now, we will compose the label of the footnote (in the caption). Even if we +% are not in the first composition, we have to compose that label! +% \begin{macrocode} + \tl_if_novalue:nT { #1 } { \int_gincr:N \c@tabularnote } + \seq_put_right:Nx \l_@@_notes_labels_seq + { + \tl_if_novalue:nTF { #1 } + { \@@_notes_format:n { \int_use:N \c@tabularnote } } + { #1 } + } + \peek_meaning:NF \tabularnote + { + \@@_notes_label_in_tabular:n + { \seq_use:Nnnn \l_@@_notes_labels_seq { , } { , } { , } } + \seq_clear:N \l_@@_notes_labels_seq + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_if_eq_two_three:nnn #1 #2 #3 + { + \tl_if_eq:nnT { #2 } { #3 } + { + \bool_set_true:N \l_tmpa_bool + \seq_map_break: + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_count_novalue_first:nn #1 #2 + { \tl_if_novalue:nT { #1 } { \int_gincr:N \g_@@_notes_caption_int } } +% \end{macrocode} +% +% +% \section{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:nnnnn|: +% 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 +% \section{The options} +% +% The following parameter corresponds to the keys |caption|, |short-caption| and +% |label| of the environment |{NiceTabular}|. +% \begin{macrocode} +\tl_new:N \l_@@_caption_tl +\tl_new:N \l_@@_short_caption_tl +\tl_new:N \l_@@_label_tl +% \end{macrocode} +% +% \bigskip +% The following parameter corresponds to the key |caption-above| of +% |\NiceMatrixOptions|. When this paremeter is |true|, the captions of the +% environments |{NiceTabular}|, specified with the key |caption| are put above +% the tabular (and below elsewhere). +% \begin{macrocode} +\bool_new:N \l_@@_caption_above_bool +% \end{macrocode} +% +% \bigskip +% 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 +% |\arrayrulewidth|. 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_@@_xdots_inter_dim +\hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_xdots_inter_dim { 0.45 em } } +% \end{macrocode} +% We use a hook only by 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_start_dim +\dim_new:N \l_@@_xdots_shorten_end_dim +\hook_gput_code:nnn { begindocument } { . } + { + \dim_set:Nn \l_@@_xdots_shorten_start_dim { 0.3 em } + \dim_set:Nn \l_@@_xdots_shorten_end_dim { 0.3 em } + } +% \end{macrocode} +% We use a hook only by 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_@@_xdots_radius_dim +\hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_xdots_radius_dim { 0.53 pt } } +% \end{macrocode} +% We use a hook only by security in case \cls{revtex4-1} is used (even though 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 +\hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_notes_above_space_dim { 1 mm } } +% \end{macrocode} +% We use a hook only by security in case \cls{revtex4-1} is used (even though 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} +% +% \medskip +% The following flag corresponds to the key |respect-arraystretch| (that key has +% an effect on the blocks). +% \begin{macrocode} +\bool_new:N \l_@@_respect_arraystretch_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 + { \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 .code:n = + \hook_gput_code:nnn { begindocument } { . } + { + \dim_set:Nn \l_@@_xdots_shorten_start_dim { #1 } + \dim_set:Nn \l_@@_xdots_shorten_end_dim { #1 } + } , + shorten-start .code:n = + \hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_xdots_shorten_start_dim { #1 } } , + shorten-end .code:n = + \hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_xdots_shorten_end_dim { #1 } } , +% \end{macrocode} +% We use a hook only by security in case \cls{revtex4-1} +% is used (even though it is obsolete). Idem for the following keys. +% \begin{macrocode} + shorten .value_required:n = true , + shorten-start .value_required:n = true , + shorten-end .value_required:n = true , + radius .code:n = + \hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_xdots_radius_dim { #1 } } , + radius .value_required:n = true , + inter .code:n = + \hook_gput_code:nnn { begindocument } { . } + { \dim_set:Nn \l_@@_xdots_inter_dim { #1 } } , + radius .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 , + unknown .code:n = \@@_error:n { Unknown~key~for~rules } + } +% \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 } + { + custom-line .code:n = \@@_custom_line:n { #1 } , + 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 = + { + \bool_set_true:N \l_@@_hvlines_bool + \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_@@_hvlines_bool + \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 , + respect-arraystretch .bool_set:N = \l_@@_respect_arraystretch_bool , + respect-arraystretch .default:n = true , + pgf-node-code .tl_set:N = \l_@@_pgf_node_code_tl , + pgf-node-code .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 } + { + corners .clist_set:N = \l_@@_corners_clist , + corners .default:n = { NW , SW , NE , SE } , + code-before .code:n = + { + \tl_if_empty:nF { #1 } + { + \tl_gput_left:Nn \g_@@_pre_code_before_tl { #1 } + \bool_set_true:N \l_@@_code_before_bool + } + } , + code-before .value_required:n = true , +% \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 = + { + \hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { enumitem } + { \setlist* [ tabularnotes ] { #1 } } + { } + } + } , + enumitem-keys .value_required:n = true , + enumitem-keys-para .code:n = + { + \hook_gput_code:nnn { begindocument } { . } + { + \IfPackageLoadedTF { enumitem } + { \setlist* [ tabularnotes* ] { #1 } } + { } + } + } , + enumitem-keys-para .value_required:n = true , + detect-duplicates .bool_set:N = \l_@@_notes_detect_duplicates_bool , + detect-duplicates .default: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 / sub-matrix .inherit:n = NiceMatrix / sub-matrix , + SubMatrix / rules .inherit:n = NiceMatrix / rules , + CodeAfter / xdots .inherit:n = NiceMatrix / xdots , + CodeBefore / sub-matrix .inherit:n = NiceMatrix / sub-matrix , + NiceMatrix .inherit:n = + { + NiceMatrix / Global , + NiceMatrix / Env , + } , + NiceMatrix / xdots .inherit:n = NiceMatrix / xdots , + NiceMatrix / rules .inherit:n = NiceMatrix / rules , + NiceTabular .inherit:n = + { + NiceMatrix / Global , + NiceMatrix / Env + } , + NiceTabular / xdots .inherit:n = NiceMatrix / xdots , + NiceTabular / rules .inherit:n = NiceMatrix / rules , + NiceTabular / notes .inherit:n = NiceMatrix / notes , + NiceArray .inherit:n = + { + NiceMatrix / Global , + NiceMatrix / Env , + } , + NiceArray / xdots .inherit:n = NiceMatrix / xdots , + NiceArray / rules .inherit:n = NiceMatrix / rules , + pNiceArray .inherit:n = + { + NiceMatrix / Global , + NiceMatrix / Env , + } , + pNiceArray / xdots .inherit:n = NiceMatrix / xdots , + pNiceArray / rules .inherit:n = NiceMatrix / rules , + } +% \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 } + { + delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , + delimiters / color .value_required:n = true , + delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , + delimiters / max-width .default:n = true , + delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , + delimiters .value_required:n = true , + width .code:n = \dim_set:Nn \l_@@_width_dim { #1 } , + width .value_required:n = true , + 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} +% +% \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} (these 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 , + 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 , + matrix / columns-type .code:n = + \@@_set_preamble:Nn \l_@@_columns_type_tl { #1 }, + matrix / columns-type .value_required:n = true , + caption-above .bool_set:N = \l_@@_caption_above_bool , + caption-above .default:n = true , + unknown .code:n = \@@_error:n { Unknown~key~for~NiceMatrixOptions } + } +% \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|''. +% That set of keys will be used by |{NiceMatrix}|, |{pNiceMatrix}|, +% |{bNiceMatrix}|, etc. +% +% \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 } } , + columns-type .code:n = \@@_set_preamble:Nn \l_@@_columns_type_tl { #1 } , + columns-type .value_required:n = true , + l .meta:n = { columns-type = l } , + r .meta:n = { columns-type = r } , + delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , + delimiters / color .value_required:n = true , + delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , + delimiters / max-width .default:n = true , + delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , + delimiters .value_required:n = true , + 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 , + 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 , + delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , + delimiters / color .value_required:n = true , + delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , + delimiters / max-width .default:n = true , + delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , + delimiters .value_required:n = true , + 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. +% If there is no column of type |X|, an error will be raised. +% \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 , + rounded-corners .dim_set:N = \l_@@_tab_rounded_corners_dim , + rounded-corners .default:n = 4 pt , + notes .code:n = \keys_set:nn { NiceMatrix / notes } { #1 } , + tabularnote .tl_gset:N = \g_@@_tabularnote_tl , + tabularnote .value_required:n = true , + caption .tl_set:N = \l_@@_caption_tl , + caption .value_required:n = true , + short-caption .tl_set:N = \l_@@_short_caption_tl , + short-caption .value_required:n = true , + label .tl_set:N = \l_@@_label_tl , + label .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 +% \section{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} +% |\g_@@_cell_after_hook_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. +% \begin{macrocode} + \tl_gclear:N \g_@@_cell_after_hook_tl +% \end{macrocode} +% At the beginning of the cell, we link |\CodeAfter| to a command which do +% begin with |\\| (whereas the standard version of |\CodeAfter| does +% not). +% \begin{macrocode} + \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: +% \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|. 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} +% +% \begin{macrocode} + \g_@@_row_style_tl +% \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} + \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: + { + \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: + \@@_cell_end_i: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_cell_end_i: + { +% \end{macrocode} +% The token list |\g_@@_cell_after_hook_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_@@_cell_after_hook_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 for the columns of type |p|, |m|, |b|, |V| (of \pkg{varwidth}) or |X|, +% we test whether the cell is syntactically empty with |\@@_test_if_empty:| and +% |\@@_test_if_empty_for_S:| +% \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|, |\llap|, |\clap| +% 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} +% +% \bigskip +% The following variant of |\@@_cell_end:| is only for the columns of type +% |w{s}{...}| or |W{s}{...}| (which use the horizontal alignement key |s| of +% |\makebox|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_cell_end_for_w_s: + { + \@@_math_toggle_token: + \hbox_set_end: + \bool_if:NF \g_@@_rotate_bool + { + \hbox_set:Nn \l_@@_cell_box + { + \makebox [ \l_@@_col_width_dim ] [ s ] + { \hbox_unpack_drop:N \l_@@_cell_box } + } + } + \@@_cell_end_i: + } +% \end{macrocode} +% +% +% \bigskip +% The following command creates the \textsc{pgf} name of the node with, of +% course, |\l_@@_cell_box| as the content. +% \begin{macrocode} +\pgfset + { + nicematrix / cell-node /.style = + { + inner~sep = \c_zero_dim , + minimum~width = \c_zero_dim + } + } +\cs_new_protected:Npn \@@_node_for_cell: + { + \pgfpicture + \pgfsetbaseline \c_zero_dim + \pgfrememberpicturepositiononpagetrue + \pgfset { nicematrix / cell-node } + \pgfnode + { rectangle } + { base } + { +% \end{macrocode} +% The following instruction |\set@color| has been added on 2022/10/06. It's +% necessary only with XeLaTeX and not with the other engines (we don't know why). +% \begin{macrocode} + \set@color + \box_use_drop:N \l_@@_cell_box + } + { \@@_env: - \int_use:N \c@iRow - \int_use:N \c@jCol } + { \l_@@_pgf_node_code_tl } + \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} +% +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_array:n + { + \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 ] + } +\cs_generate_variant:Nn \@@_array:n { V } +% \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: + { + \int_compare:nNnT \c@iRow > \g_@@_last_row_node_int + { + \int_gset_eq:NN \g_@@_last_row_node_int \c@iRow + \@@_create_row_node_i: + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_create_row_node_i: + { +% \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 - \int_eval:n { \c@iRow + 1 } } + \skip_vertical:N -0.5\arrayrulewidth + } + } + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgfcoordinate { \@@_env: - row - \int_eval:n { \c@iRow + 1 } } + { \pgfpoint \c_zero_dim { - 0.5 \arrayrulewidth } } + \str_if_empty:NF \l_@@_name_str + { + \pgfnodealias + { \l_@@_name_str - row - \int_eval:n { \c@iRow + 1 } } + { \@@_env: - row - \int_eval:n { \c@iRow + 1 } } + } + \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 now the rules of the key |hlines| (or |hvlines|) but we reserve the +% vertical space for theses rules (the rules will be drawn by \textsc{pgf}). +% \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 + { \int_eval:n { \c@iRow + 1 } } + } + { +% \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} +% +% \begin{macrocode} + \@@_expand_clist:N \l_@@_hlines_clist + \@@_expand_clist:N \l_@@_vlines_clist +% \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} + \IfPackageLoadedTF { booktabs } + { \tl_put_left:Nn \@BTnormal \@@_create_row_node_i: } + { } + \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 + { + \IfPackageLoadedTF { colortbl } + { + \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 others) 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 \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 \@@_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 + \seq_map_inline:Nn \l_@@_custom_line_commands_seq + { \cs_set_eq:cc { ##1 } { nicematrix - ##1 } } + \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. +% \begin{macrocode} + \cs_set_eq:NN \multicolumn \@@_multicolumn:nnn + \hook_gput_code:nnn { env / tabular / begin } { . } + { \cs_set_eq:NN \multicolumn \@@_old_multicolumn } +% \end{macrocode} +% If there is one or several commands |\tabularnote| in the caption specified +% by the key |caption| and if that caption has to be composed above the tabular, +% we have now that information because it has been written in the |aux| file at +% a previous run. We use that information to start couting the tabular notes in +% the main array at the right value (that remember that the caption will be +% composed \emph{after} the array!). +% \begin{macrocode} + \tl_if_exist:NT \l_@@_note_in_caption_tl + { + \tl_if_empty:NF \l_@@_note_in_caption_tl + { + \int_gset_eq:NN \g_@@_notes_caption_int + { \l_@@_note_in_caption_tl } + \int_gset:Nn \c@tabularnote { \l_@@_note_in_caption_tl } + } + } +% \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:N \g_nicematrix_code_before_tl + \tl_gclear:N \g_@@_pre_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 \g_@@_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 \g_@@_size_seq 6 } } + } +% \end{macrocode} +% +% \bigskip +% If there is an 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_@@_cols_vlism_seq + \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} +% +% \bigskip +% The command |\create_row_node:| will create a row-node (and not a row of +% nodes!). However, at the end of the array we construct a ``false row'' (for +% the col-nodes) and it interfers with the construction of the last row-node +% of the array. We don't want to create such row-node twice (to avaid warnings +% or, maybe, errors). That's why the command |\@@_create_row_node:| will use the +% following counter to avoid such construction. +% \begin{macrocode} + \int_gset:Nn \g_@@_last_row_node_int { -2 } +% \end{macrocode} +% The value $-2$ is important. +% +% +% \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} +% +% +% \medskip +% We compute the width of both delimiters. We remind 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 \g_@@_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 |\@@_CodeBefore_Body:w| will be used when the keyword +% |\CodeBefore| is present at the beginning of the environment. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_CodeBefore_Body:w #1 \Body + { + \tl_gput_left:Nn \g_@@_pre_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 +% \section{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 \g_@@_size_seq 2 } + \int_set:Nn \c@jCol { \seq_item:Nn \g_@@_size_seq 5 } + \int_set_eq:NN \g_@@_row_total_int { \seq_item:Nn \g_@@_size_seq 3 } + \int_set_eq:NN \g_@@_col_total_int { \seq_item:Nn \g_@@_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} +% +% \medskip +% Now, the recreation of the nodes of the blocks \emph{which have a name}. +% \begin{macrocode} + \@@_create_blocks_nodes: +% \end{macrocode} +% +% \begin{macrocode} + \IfPackageLoadedTF { tikz } + { + \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 + \cs_set_eq:NN \ShowCellNames \@@_ShowCellNames + } +% \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 |\CodeBefore| in math mode in order to nullify the spaces put +% by the user between instructions in the |\CodeBefore|. +% \begin{macrocode} + \bool_if:NT \l_@@_NiceTabular_bool \c_math_toggle_token +% \end{macrocode} +% +% \bigskip +% The following code is a security for the case the user has used \pkg{babel} +% with the option \pkg{spanish}: in that case, the characters |<| (de code +% \textsc{ascci} 60) and |>| are activated and Tikz is not able to solve the +% problem (even with the Tikz library \pkg{babel}). +% \begin{macrocode} + \int_compare:nNnT { \char_value_catcode:n { 60 } } = { 13 } + { + \@@_rescan_for_spanish:N \g_@@_pre_code_before_tl + \@@_rescan_for_spanish:N \l_@@_code_before_tl + } +% \end{macrocode} +% +% Here is the |\CodeBefore|. The construction is a bit complicated because +% |\g_@@_pre_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 |\g_@@_pre_code_before_tl| (when it is asked for the creation +% of cell nodes in the |\CodeBefore|). That's why we use a |\q_stop|: it +% will be used to discard the rest of |\g_@@_pre_code_before_tl|. +% \begin{macrocode} + \exp_last_unbraced:NV \@@_CodeBefore_keys: + \g_@@_pre_code_before_tl +% \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: + \l_@@_code_before_tl + \q_stop + \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~CodeBefore } + } +% \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: } + } + } + } + \int_step_inline:nn \c@iRow + { + \pgfnodealias + { \@@_env: - ##1 - last } + { \@@_env: - ##1 - \int_use:N \c@jCol } + } + \int_step_inline:nn \c@jCol + { + \pgfnodealias + { \@@_env: - last - ##1 } + { \@@_env: - \int_use:N \c@iRow - ##1 } + } + \@@_create_extra_nodes: + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_create_blocks_nodes: + { + \pgfpicture + \pgf@relevantforpicturesizefalse + \pgfrememberpicturepositiononpagetrue + \seq_map_inline:Nn \g_@@_pos_of_blocks_seq + { \@@_create_one_block_node:nnnnn ##1 } + \endpgfpicture + } +% \end{macrocode} +% +% The following command is called |\@@_create_one_block_node:nnnnn| but, in +% fact, it creates a node only if the last argument (|#5|) which is the name of +% the block, is not empty.\footnote{Moreover, there is also in the list +% |\g_@@_pos_of_blocks_seq| the positions of the dotted lines (created by +% |\Cdots|, etc.) and, for these entries, there is, of course, no name (the +% fifth component is empty).} +% \begin{macrocode} +\cs_new_protected:Npn \@@_create_one_block_node:nnnnn #1 #2 #3 #4 #5 + { + \tl_if_empty:nF { #5 } + { + \@@_qpoint:n { col - #2 } + \dim_set_eq:NN \l_tmpa_dim \pgf@x + \@@_qpoint:n { #1 } + \dim_set_eq:NN \l_tmpb_dim \pgf@y + \@@_qpoint:n { col - \int_eval:n { #4 + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x + \@@_qpoint:n { \int_eval:n { #3 + 1 } } + \dim_set_eq:NN \l_@@_tmpd_dim \pgf@y + \@@_pgf_rect_node:nnnnn + { \@@_env: - #5 } + { \dim_use:N \l_tmpa_dim } + { \dim_use:N \l_tmpb_dim } + { \dim_use:N \l_@@_tmpc_dim } + { \dim_use:N \l_@@_tmpd_dim } + } + } +% \end{macrocode} +% +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_for_revtex: + { + \cs_set_eq:NN \@addamp \@addamp@LaTeX + \cs_set_eq:NN \insert@column \insert@column@array + \cs_set_eq:NN \@classx \@classx@array + \cs_set_eq:NN \@xarraycr \@xarraycr@array + \cs_set_eq:NN \@arraycr \@arraycr@array + \cs_set_eq:NN \@xargarraycr \@xargarraycr@array + \cs_set_eq:NN \array \array@array + \cs_set_eq:NN \@array \@array@array + \cs_set_eq:NN \@tabular \@tabular@array + \cs_set_eq:NN \@mkpream \@mkpream@array + \cs_set_eq:NN \endarray \endarray@array + \cs_set:Npn \@tabarray { \@ifnextchar [ { \@array } { \@array [ c ] } } + \cs_set:Npn \endtabular { \endarray $\egroup} % $ + } +% \end{macrocode} +% +% +% \bigskip +% \section{The environment \{NiceArrayWithDelims\}} +% +% \begin{macrocode} +\NewDocumentEnvironment { NiceArrayWithDelims } + { m m O { } m ! O { } t \CodeBefore } + { + \bool_if:NT \c_@@_revtex_bool \@@_patch_for_revtex: +% \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 } } + \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 + } + \tl_if_empty:NF \g_@@_pre_code_before_tl + { \bool_set_true:N \l_@@_code_before_bool } +% \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 \g_@@_NiceArray_bool + { \keys_set:nn { NiceMatrix / NiceArray } } + { \keys_set:nn { NiceMatrix / pNiceArray } } + { #3 , #5 } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} + \@@_set_CT@arc@:V \l_@@_rules_color_tl +% \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 |\@@_CodeBefore_Body:w|. After that job, the command |\@@_CodeBefore_Body:w| +% will go on with |\@@_pre_array:|. +% \begin{macrocode} + \IfBooleanTF { #6 } \@@_CodeBefore_Body:w \@@_pre_array: + } +% \end{macrocode} +% +% Now, the second part of the environment |{NiceArrayWithDelims}|. +% \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_or_warning: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 +% actual 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 |\g_@@_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 \g_@@_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 + \@@_color:V \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 - \arrayrulewidth } + \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 + \arrayrulewidth } + } +% \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} + \@@_color:V \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 + { \@@_warning_gredirect_none:n { columns~not~used } } + } + \@@_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 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} +% \section{We construct the preamble of the array} +% +% \bigskip +% The transformation of the preamble is an operation in several +% steps.\footnote{Be careful: the transformation of the preamble may also have +% by-side effects, for example, the boolean |\g_@@_NiceArray_bool| will be set +% to |false| if we detect in the preamble a delimiter at the beginning or at the +% end.} +% +% \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 \@@_transform_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 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 to use 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} +% +% \bigskip +% If the package \pkg{varwidth} has defined the column type |V|, we protect from +% expansion by redefining it to |\@@_V:| (which will be catched by our system). +% \begin{macrocode} + \cs_if_exist:NT \NC@find@V { \@@_newcolumntype V { \@@_V: } } +% \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} +% +% \bigskip +% The following sequence will store the arguments of the successive |>| in the +% preamble. +% \begin{macrocode} + \tl_gclear_new:N \g_@@_pre_cell_tl +% \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_gset_false:N \g_@@_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 + { + \g_@@_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 + { + \g_@@_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*}| (we control that with the value of +% |\l_@@_tabular_width_dim|). +% \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 +% The command |\@@_patch_preamble:n| is the main function for the transformation +% of the preamble. It is recursive. +% \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_xiv:n } + ! { \@@_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 } + \@@_V: { \@@_patch_preamble_v:n } + V { \@@_patch_preamble_v:n } + \@@_w: { \@@_patch_preamble_vi:nnnn { } #1 } + \@@_W: { \@@_patch_preamble_vi:nnnn { \@@_special_W: } #1 } + \@@_S: { \@@_patch_preamble_vii:n } + ( { \@@_patch_preamble_viii:nn #1 } + [ { \@@_patch_preamble_viii:nn #1 } + \{ { \@@_patch_preamble_viii:nn #1 } + \left { \@@_patch_preamble_viii:nn } + ) { \@@_patch_preamble_ix:nn #1 } + ] { \@@_patch_preamble_ix:nn #1 } + \} { \@@_patch_preamble_ix:nn #1 } + \right { \@@_patch_preamble_ix:nn } + X { \@@_patch_preamble_x:n } +% \end{macrocode} +% When \pkg{tabularx} is loaded, a local redefinition of the specifier |X| is +% done to replace |X| by |\@@_X|. Thus, our column type |X| will be used in the +% |{NiceTabularX}|. +% \begin{macrocode} + \@@_X { \@@_patch_preamble_x:n } + \q_stop { } + } + { + \str_if_eq:nVTF { #1 } \l_@@_letter_vlism_tl + { + \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 + } +% \end{macrocode} +% Now the case of a letter set by the final user for a customized rule. Such +% customized rule is defined by using the key |custom-line| in +% |\NiceMatrixOptions|. That key takes in as value a list of \textsl{key=value} +% pairs. Among the keys avalaible in that list, there is the key |letter|. All +% the letters defined by this way by the final user for such customized rules +% are added in the set of keys |{NiceMatrix/ColumnTypes}|. That set of keys is +% used to store the characteristics of those types of rules for convenience: the +% keys of that set of keys won't never be used as keys by the final user (he +% will use, instead, letters in the preamble of its array). +% \begin{macrocode} + { + \keys_if_exist:nnTF { NiceMatrix / ColumnTypes } { #1 } + { + \keys_set:nn { NiceMatrix / ColumnTypes } { #1 } + \@@_patch_preamble:n + } + { + \tl_if_eq:nnT { #1 } { S } + { \@@_fatal:n { unknown~column~type~S } } + { \@@_fatal:nn { unknown~column~type } { #1 } } + } + } + } + } +% \end{macrocode} +% +% +% \bigskip +% Now, we will list all the auxiliary functions for the different types of +% entries in the preamble of the array. +% +% \medskip +% For |c|, |l| and |r| +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_i:n #1 + { + \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl + \tl_gclear:N \g_@@_pre_cell_tl + \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_xi: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 | } + { + \dim_set:Nn \l_tmpa_dim + { + \arrayrulewidth * \l_tmpa_int + + \doublerulesep * ( \l_tmpa_int - 1) + } + \tl_gput_right:Nx \g_@@_preamble_tl + { +% \end{macrocode} +% Here, the command |\dim_eval:n| is mandatory. +% \begin{macrocode} + \exp_not:N ! { \skip_horizontal:n { \dim_eval:n { \l_tmpa_dim } } } + } + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { + \@@_vline:n + { + position = \int_eval:n { \c@jCol + 1 } , + multiplicity = \int_use:N \l_tmpa_int , + total-width = \dim_use:N \l_tmpa_dim % added 2022-08-06 + } +% \end{macrocode} +% We don't have provided value for |start| nor for |end|, which means that the +% rule will cover (potentially) all the rows of the array. +% +% \begin{macrocode} + } + \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} +\cs_new_protected:Npn \@@_patch_preamble_xiv:n #1 + { + \tl_gput_right:Nn \g_@@_pre_cell_tl { > { #1 } } + \@@_patch_preamble:n + } +% \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|, |b|, |V| and |X|) have an +% optional argument between square brackets for a list of +% \emph{key}-\emph{value} pairs. Here are the corresponding keys. +% \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 , + R .code:n = + \IfPackageLoadedTF { ragged2e } + { \str_set:Nn \l_@@_hpos_col_str { R } } + { + \@@_error_or_warning:n { ragged2e~not~loaded } + \str_set:Nn \l_@@_hpos_col_str { r } + } , + R .value_forbidden:n = true , + L .code:n = + \IfPackageLoadedTF { ragged2e } + { \str_set:Nn \l_@@_hpos_col_str { L } } + { + \@@_error_or_warning:n { ragged2e~not~loaded } + \str_set:Nn \l_@@_hpos_col_str { l } + } , + L .value_forbidden:n = true , + C .code:n = + \IfPackageLoadedTF { ragged2e } + { \str_set:Nn \l_@@_hpos_col_str { C } } + { + \@@_error_or_warning:n { ragged2e~not~loaded } + \str_set:Nn \l_@@_hpos_col_str { c } + } , + C .value_forbidden:n = true , + S .code:n = \str_set:Nn \l_@@_hpos_col_str { si } , + S .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|, |r|, |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 } + \tl_set:Nn \l_tmpa_tl { #1 } + \tl_replace_all:Nnn \l_tmpa_tl { \@@_S: } { S } + \@@_keys_p_column:V \l_tmpa_tl + \@@_patch_preamble_iv_iv:nn { #2 } { minipage } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_keys_p_column:n #1 + { \keys_set_known:nnN { WithArrows / p-column } { #1 } \l_tmpa_tl } +\cs_generate_variant:Nn \@@_keys_p_column:n { V } +% \end{macrocode} +% +% \medskip +% The first argument is the width of the column. The second is the type of +% environment: |minipage| or |varwidth|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_iv_iv:nn #1 #2 + { + \use:x + { + \@@_patch_preamble_iv_v:nnnnnnnn + { \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 + { \str_lowercase:V \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 } + 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: } + { #2 } + { + \str_case:VnF \l_@@_hpos_col_str + { + { j } { c } + { si } { c } + } +% \end{macrocode} +% We use |\str_lowercase:n| to convert |R| to |r|, etc. +% \begin{macrocode} + { \str_lowercase:V \l_@@_hpos_col_str } + } + } +% \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_xi:n + } +% \end{macrocode} +% +% \medskip +% |#1| is the optional argument of |{minipage}| (or |{varwidth}|): |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}| (or |{varwidth}|), 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). It's also possible +% to put in that |#3| some code to fix the value of |\l_@@_hpos_cell_str| which +% will be available in each cell of the column. +% +% |#4| is an extra-code which contains |\@@_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| (or |r| or |l|: see |#8|). +% +% |#6| is a code put just after the |c| (or |r| or |l|: see |#8|). +% +% |#7| is the type of environment: |minipage| or |varwidth|. +% +% |#8| is the letter |c| or |r| or |l| which is the basic specificier of column +% which is used \emph{in fine}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_iv_v:nnnnnnnn #1 #2 #3 #4 #5 #6 #7 #8 + { + \str_if_eq:VnTF \l_@@_hpos_col_str { si } + { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_test_if_empty_for_S: } } } + { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_test_if_empty: } } } + \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl + \tl_gclear:N \g_@@_pre_cell_tl + \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 { #7 } [ #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|, |\RaggedRight|, etc.). +% \begin{macrocode} + #3 +% \end{macrocode} +% The following code is to allow something like |\centering| in |\RowStyle|. +% \begin{macrocode} + \g_@@_row_style_tl + \arraybackslash + #5 + } + #8 + < { + #6 +% \end{macrocode} +% The following line has been taken from |array.sty|. +% \begin{macrocode} + \@finalstrut \@arstrutbox + % \bool_if:NT \g_@@_rotate_bool { \raggedright \hsize = 3 cm } + \end { #7 } +% \end{macrocode} +% If the letter in the preamble is |m|, |#4| will be equal to +% |\@@_center_cell_box:| (see just below). +% \begin{macrocode} + #4 + \@@_cell_end: + } + } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_test_if_empty: \ignorespaces #1 + { + \peek_meaning:NT \unskip + { + \tl_gput_right:Nn \g_@@_cell_after_hook_tl + { + \box_set_wd:Nn \l_@@_cell_box \c_zero_dim +% \end{macrocode} +% We put the following code in order to have a column with the correct width +% even when all the cells of the column are empty. +% \begin{macrocode} + \skip_horizontal:N \l_@@_col_width_dim + } + } + #1 + } +% \end{macrocode} +% +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_test_if_empty_for_S: #1 + { + \peek_meaning:NT \__siunitx_table_skip:n + { + \tl_gput_right:Nn \g_@@_cell_after_hook_tl + { \box_set_wd:Nn \l_@@_cell_box \c_zero_dim } + } + #1 + } +% \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_@@_cell_after_hook_tl|, we require a +% post-action of the box |\l_@@_cell_box|. +% \begin{macrocode} + \tl_gput_right:Nn \g_@@_cell_after_hook_tl + { + \int_compare:nNnT + { \box_ht:N \l_@@_cell_box } + > +% \end{macrocode} +% Previously, we had |\@arstrutbox| and not |\strutbox| in the following line +% but the code in \pkg{array} has changed in v 2.5g and we follow the change +% (see \emph{array: Correctly identify single-line m-cells} in LaTeX~News~36). +% \begin{macrocode} + { \box_ht:N \strutbox } + { + \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 |V| (similar to the |V| of \pkg{varwidth}). +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_v:n #1 + { + \str_if_eq:nnTF { #1 } { [ } + { \@@_patch_preamble_v_i:w [ } + { \@@_patch_preamble_v_i:w [ ] { #1 } } + } +\cs_new_protected:Npn \@@_patch_preamble_v_i:w [ #1 ] + { \@@_patch_preamble_v_ii:nn { #1 } } +\cs_new_protected:Npn \@@_patch_preamble_v_ii:nn #1 #2 + { + \str_set:Nn \l_@@_vpos_col_str { p } + \str_set:Nn \l_@@_hpos_col_str { j } + \tl_set:Nn \l_tmpa_tl { #1 } + \tl_replace_all:Nnn \l_tmpa_tl { \@@_S: } { S } + \@@_keys_p_column:V \l_tmpa_tl + \IfPackageLoadedTF { varwidth } + { \@@_patch_preamble_iv_iv:nn { #2 } { varwidth } } + { + \@@_error_or_warning:n { varwidth~not~loaded } + \@@_patch_preamble_iv_iv:nn { #2 } { minipage } + } + } +% \end{macrocode} +% +% \medskip +% For |w| and |W| +% +% |#1| is a special argument: empty for |w| and equal to |\@@_special_W:| for |W|; +% +% |#2| is the type of column (|w| or |W|); +% +% |#3| is the type of horizontal alignment (|c|, |l|, |r| or |s|); +% +% |#4| is the width of the column. +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_vi:nnnn #1 #2 #3 #4 + { + \str_if_eq:nnTF { #3 } { s } + { \@@_patch_preamble_vi_i:nnnn { #1 } { #4 } } + { \@@_patch_preamble_vi_ii:nnnn { #1 } { #2 } { #3 } { #4 } } + } +% \end{macrocode} +% +% \bigskip +% First, the case of an horizontal alignment equal to |s| (for \emph{stretch}). +% +% |#1| is a special argument: empty for |w| and equal to |\@@_special_W:| for +% |W|; +% +% |#2| is the width of the column. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_vi_i:nnnn #1 #2 + { + \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl + \tl_gclear:N \g_@@_pre_cell_tl + \tl_gput_right:Nn \g_@@_preamble_tl + { + > { + \dim_set:Nn \l_@@_col_width_dim { #2 } + \@@_cell_begin:w + \str_set:Nn \l_@@_hpos_cell_str { c } + } + c + < { + \@@_cell_end_for_w_s: + #1 + \@@_adjust_size_box: + \box_use_drop:N \l_@@_cell_box + } + } + \int_gincr:N \c@jCol + \@@_patch_preamble_xi:n + } +% \end{macrocode} +% +% \bigskip +% Then, the most important version, for the horizontal alignments types of |c|, +% |l| and |r| (and not |s|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_vi_ii:nnnn #1 #2 #3 #4 + { + \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl + \tl_gclear:N \g_@@_pre_cell_tl + \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: + \hbox_set_end: + % The following line is probably pointless + % \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: + #1 + \@@_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_xi:n + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_special_W: + { + \dim_compare:nNnT { \box_wd:N \l_@@_cell_box } > \l_@@_col_width_dim + { \@@_warning:n { W~warning } } + } +% \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_vii:n #1 + { + \str_if_eq:nnTF { #1 } { [ } + { \@@_patch_preamble_vii_i:w [ } + { \@@_patch_preamble_vii_i:w [ ] { #1 } } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_vii_i:w [ #1 ] + { \@@_patch_preamble_vii_ii:n { #1 } } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_vii_ii:n #1 + { + \IfPackageAtLeastTF { siunitx } { 2022/01/01 } + { + \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl + \tl_gclear:N \g_@@_pre_cell_tl + \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_xi:n + } + { \@@_fatal:n { Version~of~siunitx~too~old } } + } +% \end{macrocode} +% +% +% \medskip +% For |(|, |[| and |\{|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_viii: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_viii_i:nn { #1 } { #2 } + } + } + { \@@_patch_preamble_viii_i:nn { #1 } { #2 } } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_viii_i:nn #1 #2 + { + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { \@@_delimiter:nnn #1 { \int_eval:n { \c@jCol + 1 } } \c_true_bool } + \tl_if_in:nnTF { ( [ \{ ) ] \} \left \right } { #2 } + { + \@@_error:nn { delimiter~after~opening } { #2 } + \@@_patch_preamble:n + } + { \@@_patch_preamble:n #2 } + } +% \end{macrocode} +% +% \bigskip +% For the closing delimiters. 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_ix:nn #1 #2 + { + \bool_if:NT \l_@@_small_bool { \@@_fatal:n { Delimiter~with~small } } + \tl_if_in:nnTF { ) ] \} } { #2 } + { \@@_patch_preamble_ix_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_@@_pre_code_after_tl + { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } + \@@_patch_preamble:n #2 + } + } + { + \tl_if_in:nnT { ( [ \{ \left } { #2 } + { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } } + \tl_gput_right:Nx \g_@@_pre_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_ix_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_@@_pre_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_@@_pre_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_@@_pre_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_x:n #1 + { + \str_if_eq:nnTF { #1 } { [ } + { \@@_patch_preamble_x_i:w [ } + { \@@_patch_preamble_x_i:w [ ] #1 } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_x_i:w [ #1 ] + { \@@_patch_preamble_x_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_x_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} (now obsolete) or \pkg{tabularray}. +% \begin{macrocode} + \int_zero_new:N \l_@@_weight_int + \int_set:Nn \l_@@_weight_int { 1 } + \tl_set:Nn \l_tmpa_tl { #1 } + \tl_replace_all:Nnn \l_tmpa_tl { \@@_S: } { S } + \@@_keys_p_column:V \l_tmpa_tl + \keys_set:nV { WithArrows / X-column } \l_tmpa_tl + \int_compare:nNnT \l_@@_weight_int < 0 + { + \@@_error_or_warning:n { negative~weight } + \int_set:Nn \l_@@_weight_int { - \l_@@_weight_int } + } + \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 + { + \exp_args:Nnx + \@@_patch_preamble_iv_iv:nn + { \l_@@_weight_int \l_@@_X_columns_dim } + { minipage } + } + { + \tl_gput_right:Nn \g_@@_preamble_tl + { + > { + \@@_cell_begin:w + \bool_set_true:N \l_@@_X_column_bool +% \end{macrocode} +% You encounter a problem on 2023-03-04: for an environment with |X| columns, +% during the first compilations (which are not the definitive one), sometimes, +% some cells are declared empty even if they should not. That's a problem +% because user's instructions may use these nodes. That's why we have added the +% following |\NotEmpty|. +% \begin{macrocode} + \NotEmpty +% \end{macrocode} +% The following code will nullify the box of the cell. +% \begin{macrocode} + \tl_gput_right:Nn \g_@@_cell_after_hook_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_xi: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. In fact, we have +% also to test whether there is, after the |<{...}|, a |@{...}|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_xi:n #1 + { + \str_if_eq:nnTF { #1 } { < } + \@@_patch_preamble_xiii:n + { + \str_if_eq:nnTF { #1 } { @ } + \@@_patch_preamble_xv: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 { \int_eval:n { \c@jCol + 1 } } + { + \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_xiii:n #1 + { + \tl_gput_right:Nn \g_@@_preamble_tl { < { #1 } } + \@@_patch_preamble_xi:n + } +% \end{macrocode} +% +% We have to catch a |@{...}| after a specifier of column because, if we have to +% draw a vertical rule, we have to add in that |@{...}| a |\hskip| corresponding +% to the width of the vertical rule. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_preamble_xv:n #1 + { + \tl_if_eq:NnTF \l_@@_vlines_clist { all } + { + \tl_gput_right:Nn \g_@@_preamble_tl + { @ { #1 \skip_horizontal:N \arrayrulewidth } } + } + { + \exp_args:NNx + \clist_if_in:NnTF \l_@@_vlines_clist { \int_eval:n { \c@jCol + 1 } } + { + \tl_gput_right:Nn \g_@@_preamble_tl + { @ { #1 \skip_horizontal:N \arrayrulewidth } } + } + { \tl_gput_right:Nn \g_@@_preamble_tl { @ { #1 } } } + } + \@@_patch_preamble:n + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_preamble:Nn #1 #2 + { + \group_begin: + \@@_newcolumntype w [ 2 ] { \@@_w: { ##1 } { ##2 } } + \@@_newcolumntype W [ 2 ] { \@@_W: { ##1 } { ##2 } } + \@temptokena { #2 } + \@tempswatrue + \@whilesw \if@tempswa \fi { \@tempswafalse \the \NC@list } + \tl_gclear:N \g_@@_preamble_tl + \exp_after:wN \@@_patch_m_preamble:n \the \@temptokena \q_stop + \group_end: + \tl_set_eq:NN #1 \g_@@_preamble_tl + } +% \end{macrocode} +% +% \bigskip +% \section{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} +% +% \begin{macrocode} + \@@_newcolumntype w [ 2 ] { \@@_w: { ##1 } { ##2 } } + \@@_newcolumntype W [ 2 ] { \@@_W: { ##1 } { ##2 } } +% \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 - \int_eval:n { \c@jCol + 1 } } + \seq_gput_left:Nn \g_@@_multicolumn_sizes_seq { #1 } + \seq_gput_right:Nx \g_@@_pos_of_blocks_seq + { + { + \int_compare:nNnTF \c@jCol = 0 + { \int_eval:n { \c@iRow + 1 } } + { \int_use:N \c@iRow } + } + { \int_eval:n { \c@jCol + 1 } } + { + \int_compare:nNnTF \c@jCol = 0 + { \int_eval:n { \c@iRow + 1 } } + { \int_use:N \c@iRow } + } + { \int_eval:n { \c@jCol + #1 } } + { } % for the name of the block + } + } +% \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 { \@@_special_W: } #1 } + \q_stop { } + } + { + \tl_if_eq:nnT { #1 } { S } + { \@@_fatal:n { unknown~column~type~S } } + { \@@_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 + { + > { + \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: + \hbox_set_end: + \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: + #1 + \@@_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} +% +% +% After a specifier of column, we have to test whether there is one or several +% |<{..}|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_m_preamble_x:n #1 + { + \str_if_eq:nnTF { #1 } { < } + \@@_patch_m_preamble_ix:n + { \@@_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 - \int_eval:n { \c@iRow + 1 } } + \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 \g_@@_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 } + \bool_if:NT \l_@@_caption_above_bool + { + \tl_if_empty:NF \l_@@_caption_tl + { +% \end{macrocode} +% \begin{macrocode} + \bool_set_false:N \g_@@_caption_finished_bool + \int_gzero:N \c@tabularnote + \@@_insert_caption: +% \end{macrocode} +% If there is one or several commands |\tabularnote| in the caption, we will +% write in the |aux| file the number of such tabular notes... but only the +% tabular notes for which the command |\tabularnote| has been used without its +% optional argument (between square brackets). +% \begin{macrocode} + \int_compare:nNnT \g_@@_notes_caption_int > 0 + { + \tl_gput_right:Nx \g_@@_aux_tl + { + \tl_set:Nn \exp_not:N \l_@@_note_in_caption_tl + { \int_use:N \g_@@_notes_caption_int } + } + \int_gzero:N \g_@@_notes_caption_int + } + } + } +% \end{macrocode} +% The |\hbox| avoids that the |pgfpicture| inside |\@@_draw_blocks| adds a extra +% vertical space before the notes. +% \begin{macrocode} + \hbox + { + \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: + } +% \end{macrocode} +% We don't do the following test with |\c@tabularnote| because the value of that +% counter is not reliable when the command |\ttabbox| of \pkg{floatrow} is used +% (because |\ttabbox| de-activate |\stepcounter| because if compiles several +% twice its tabular). +% \begin{macrocode} + \bool_lazy_any:nT + { + { ! \seq_if_empty_p:N \g_@@_notes_seq } + { ! \seq_if_empty_p:N \g_@@_notes_in_caption_seq } + { ! \tl_if_empty_p:V \g_@@_tabularnote_tl } + } + \@@_insert_tabularnotes: + \cs_set_eq:NN \tabularnote \@@_tabularnote_error:n + \bool_if:NF \l_@@_caption_above_bool \@@_insert_caption: + \end { minipage } + } +% \end{macrocode} +% +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_insert_caption: + { + \tl_if_empty:NF \l_@@_caption_tl + { + \cs_if_exist:NTF \@captype + { \@@_insert_caption_i: } + { \@@_error:n { caption~outside~float } } + } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_insert_caption_i: + { + \group_begin: +% \end{macrocode} +% The flag |\l_@@_in_caption_bool| affects only the behaviour of the command +% |\tabularnote| when used in the caption. +% \begin{macrocode} + \bool_set_true:N \l_@@_in_caption_bool +% \end{macrocode} +% The package \pkg{floatrow} does a redefinition of |\@makecaption| which will +% extract the caption from the tabular. However, the old version of +% |\@makecaption| has been stored by \pkg{floatrow} in |\FR@makecaption|. That's +% why we restore the old version. +% \begin{macrocode} + \IfPackageLoadedTF { floatrow } + { \cs_set_eq:NN \@makecaption \FR@makecaption } + { } + \tl_if_empty:NTF \l_@@_short_caption_tl + { \caption } + { \caption [ \l_@@_short_caption_tl ] } + { \l_@@_caption_tl } + \tl_if_empty:NF \l_@@_label_tl { \label { \l_@@_label_tl } } + \group_end: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_tabularnote_error:n #1 + { + \@@_error_or_warning:n { tabularnote~below~the~tabular } + \@@_gredirect_none:n { tabularnote~below~the~tabular } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_insert_tabularnotes: + { + \seq_gconcat:NNN \g_@@_notes_seq \g_@@_notes_in_caption_seq \g_@@_notes_seq + \int_set:Nn \c@tabularnote { \seq_count:N \g_@@_notes_seq } + \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 \g_@@_tabularnote_tl + { + \g_@@_tabularnote_tl \par + \tl_gclear:N \g_@@_tabularnote_tl + } +% \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_@@_notes_seq + { \@@_one_tabularnote:nn ##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_@@_notes_seq + { \@@_one_tabularnote:nn ##1 } + \strut + \endtabularnotes + } + } + \unskip + \group_end: + \bool_if:NT \l_@@_notes_bottomrule_bool + { + \IfPackageLoadedTF { booktabs } + { +% \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_or_warning:n { bottomrule~without~booktabs } } + } + \l_@@_notes_code_after_tl + \seq_gclear:N \g_@@_notes_seq + \seq_gclear:N \g_@@_notes_in_caption_seq + \int_gzero:N \c@tabularnote + } +% \end{macrocode} +% +% \medskip +% The following command will format (after the main tabular) one tabularnote +% (with the command |\item|) . |#1| is the label (when the command +% |\tabularnote| has been used with an optional argument between square +% brackets) and |#2| is the text of the note. The second argument is provided by +% currification. +% \begin{macrocode} +\cs_set_protected:Npn \@@_one_tabularnote:nn #1 + { + \tl_if_novalue:nTF { #1 } + { \item } + { \item [ \@@_notes_label_in_list:n { #1 } ] } + } +% \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 + { \box_ht_plus_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 + { \box_ht_plus_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_remove_spaces:n + { + \peek_meaning:NTF \end + \@@_analyze_end:Nn + { + \@@_transform_preamble: +% \end{macrocode} +% Here is the call to |\array| (we have a dedicated macro |\@@_array:n| because +% of compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}). +% \begin{macrocode} + \@@_array:V \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|). +% % \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:w #1 \CodeAfter \q_stop +% \end{macrocode} +% The command |\array| is hidden somewhere in |\@@_light_syntax_i:w|. +% \begin{macrocode} + } +% \end{macrocode} +% Now, the second part of the environment. We must leave these lines in the +% second part (and not put them in the first part even though we caught the +% whole body of the environment with an argument of type |b|) in order to have +% the columns |S| of \pkg{siunitx} working fine. +% \begin{macrocode} + { + \@@_create_col_nodes: + \endarray + } +% \end{macrocode} +% +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_light_syntax_i:w #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_clear_new:N \l_@@_rows_seq +% \end{macrocode} +% We rescan the character of end of line in order to have the correct catcode. +% \begin{macrocode} + \tl_set_rescan:Nno \l_@@_end_of_row_tl { } \l_@@_end_of_row_tl + \seq_set_split:NVn \l_@@_rows_seq \l_@@_end_of_row_tl { #1 } +% \end{macrocode} +% We delete the last row if it is empty. +% \begin{macrocode} + \seq_pop_right:NN \l_@@_rows_seq \l_tmpa_tl + \tl_if_empty:NF \l_tmpa_tl + { \seq_put_right:NV \l_@@_rows_seq \l_tmpa_tl } +% \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 compute 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 \l_@@_rows_seq } } +% \end{macrocode} +% +% +% \bigskip +% The new value of the body (that is to say after replacement of the separators +% of rows and columns by |\\| and |&|) of the environment will be stored in +% |\l_@@_new_body_tl| (that part of the implementation has been changed in the +% version 6.11 of \pkg{nicematrix} in order to allow the use of commands such as +% |\hline| or |\hdottedline| with the key |light-syntax|). +% \begin{macrocode} + \tl_clear_new:N \l_@@_new_body_tl + \int_zero_new:N \l_@@_nb_cols_int +% \end{macrocode} +% First, we treat the first row. +% \begin{macrocode} + \seq_pop_left:NN \l_@@_rows_seq \l_tmpa_tl + \@@_line_with_light_syntax:V \l_tmpa_tl +% \end{macrocode} +% Now, the other rows (with the same treatment, excepted that we have to insert +% |\\| between the rows). +% \begin{macrocode} + \seq_map_inline:Nn \l_@@_rows_seq + { + \tl_put_right:Nn \l_@@_new_body_tl { \\ } + \@@_line_with_light_syntax:n { ##1 } + } +% \end{macrocode} +% +% \begin{macrocode} + \int_compare:nNnT \l_@@_last_col_int = { -1 } + { + \int_set:Nn \l_@@_last_col_int + { \l_@@_nb_cols_int - 1 + \l_@@_first_col_int } + } +% \end{macrocode} +% +% Now, we can construct the preamble: if the user has used the key |last-col|, +% we have the correct number of columns even though the user has used |last-col| +% without value. +% \begin{macrocode} + \@@_transform_preamble: +% \end{macrocode} +% +% The call to |\array| is in the following command (we have a dedicated macro +% |\@@_array:n| because of compatibility with the classes \cls{revtex4-1} and +% \cls{revtex4-2}). +% \begin{macrocode} + \@@_array:V \g_@@_preamble_tl \l_@@_new_body_tl + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_line_with_light_syntax:n #1 + { + \seq_clear_new:N \l_@@_cells_seq + \seq_set_split:Nnn \l_@@_cells_seq { ~ } { #1 } + \int_set:Nn \l_@@_nb_cols_int + { + \int_max:nn + \l_@@_nb_cols_int + { \seq_count:N \l_@@_cells_seq } + } + \seq_pop_left:NN \l_@@_cells_seq \l_tmpa_tl + \tl_put_right:NV \l_@@_new_body_tl \l_tmpa_tl + \seq_map_inline:Nn \l_@@_cells_seq + { \tl_put_right:Nn \l_@@_new_body_tl { & ##1 } } + } +\cs_generate_variant:Nn \@@_line_with_light_syntax:n { V } +% \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). When this command is used, |#1| is, in fact, always |\end|. +% \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 - \int_eval:n { \g_tmpa_int + 1 } } + \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 - \int_eval:n { \g_tmpa_int + 1 } } + { \pgfpoint { - 0.5 \arrayrulewidth } \c_zero_dim } + \str_if_empty:NF \l_@@_name_str + { + \pgfnodealias + { \l_@@_name_str - col - \int_eval:n { \g_tmpa_int + 1 } } + { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } + } + \endpgfpicture + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} + & + \omit +% \end{macrocode} +% The two following lines have been added on 2021-12-15 to solve a bug +% mentionned by Joao Luis Soares by mail. +% \begin{macrocode} + \int_compare:nNnT \g_@@_col_total_int = 1 + { \skip_gset:Nn \g_tmpa_skip { 0 pt~plus 1 fill } } + \skip_horizontal:N \g_tmpa_skip + \int_gincr:N \g_tmpa_int + \bool_lazy_all:nT + { + \g_@@_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 \g_@@_NiceArray_bool + { \skip_horizontal:N -\arraycolsep } + \pgfsys@markposition + { \@@_env: - col - \int_eval:n { + \g_tmpa_int + 1 } } + \skip_horizontal:N 0.5\arrayrulewidth + \bool_lazy_and:nnT \l_@@_Matrix_bool \g_@@_NiceArray_bool + { \skip_horizontal:N \arraycolsep } + } + } + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgfcoordinate { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } + { + \bool_lazy_and:nnTF \l_@@_Matrix_bool \g_@@_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 - \int_eval:n { \g_tmpa_int + 1 } } + { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } + } + \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 - \int_eval:n { \g_@@_col_total_int + 1 } } + } + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgfcoordinate + { \@@_env: - col - \int_eval:n { \g_@@_col_total_int + 1 } } + \pgfpointorigin + \str_if_empty:NF \l_@@_name_str + { + \pgfnodealias + { + \l_@@_name_str - col + - \int_eval:n { \g_@@_col_total_int + 1 } + } + { \@@_env: - col - \int_eval:n { \g_@@_col_total_int + 1 } } + } + \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 +% begins with |\\| (whereas the standard version of |\CodeAfter| begins does +% not). +% \begin{macrocode} + \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: + \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 +% begins with |\\| (whereas the standard version of |\CodeAfter| begins does +% not). +% \begin{macrocode} + \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: +% \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 |\g_@@_NiceArray_bool|. +% In |{NiceArrayWithDelims}|, some special code will be executed if this flag is +% raised. +% \begin{macrocode} +\NewDocumentEnvironment { NiceArray } { } + { + \bool_gset_true:N \g_@@_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 +% |\g_@@_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 } { } + { + \bool_gset_false:N \g_@@_NiceArray_bool + \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 +% \section{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_case:nnF \l_@@_last_col_int + { + { -2 } { \c@MaxMatrixCols } + { -1 } { \int_eval:n { \c@MaxMatrixCols + 1 } } +% \end{macrocode} +% The value $0$ can't occur here since we are in a matrix (which is an +% environment without preamble). +% \begin{macrocode} + } + { \int_eval:n { \l_@@_last_col_int - 1 } } + } + { #2 } + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_generate_variant:Nn \@@_begin_of_NiceMatrix:nn { n V } +% \end{macrocode} +% +% \begin{macrocode} +\clist_map_inline:nn { p , b , B , v , V } + { + \NewDocumentEnvironment { #1 NiceMatrix } { ! O { } } + { + \bool_gset_false:N \g_@@_NiceArray_bool + \str_gset:Nn \g_@@_name_env_str { #1 NiceMatrix } + \keys_set:nn { NiceMatrix / NiceMatrix } { ##1 } + \@@_begin_of_NiceMatrix:nV { #1 } \l_@@_columns_type_tl + } + { \use:c { end #1 NiceArray } } + } +% \end{macrocode} +% +% \bigskip +% We define also an environment |{NiceMatrix}| +% \begin{macrocode} +\NewDocumentEnvironment { NiceMatrix } { ! O { } } + { + \bool_gset_false:N \g_@@_NiceArray_bool + \str_gset:Nn \g_@@_name_env_str { NiceMatrix } + \keys_set:nn { NiceMatrix / NiceMatrix } { #1 } + \@@_begin_of_NiceMatrix:nV { } \l_@@_columns_type_tl + } + { \endNiceArray } +% \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 +% \section{\{NiceTabular\}, \{NiceTabularX\} and \{NiceTabular*\}} +% +% \begin{macrocode} +\NewDocumentEnvironment { NiceTabular } { O { } m ! O { } } + { +% \end{macrocode} +% If the dimension |\l_@@_width_dim| is equal to $0$~pt, that means that it has +% not be set by a previous use of |\NiceMatrixOptions|. +% \begin{macrocode} + \dim_compare:nNnT \l_@@_width_dim = \c_zero_dim + { \dim_set_eq:NN \l_@@_width_dim \linewidth } + \str_gset:Nn \g_@@_name_env_str { NiceTabular } + \keys_set:nn { NiceMatrix / NiceTabular } { #1 , #3 } + \int_compare:nNnT \l_@@_tab_rounded_corners_dim > \c_zero_dim + { + \bool_if:NT \l_@@_hvlines_bool + { + \bool_set_true:N \l_@@_except_borders_bool + % we should try to be more efficient in the number of lines of code here + \tl_if_empty:NTF \l_@@_rules_color_tl + { + \tl_gput_right:Nn \g_@@_pre_code_after_tl + { + \@@_stroke_block:nnn + { rounded-corners = \dim_use:N \l_@@_tab_rounded_corners_dim } + { 1-1 } + { \int_use:N \c@iRow - \int_use:N \c@jCol } + } + } + { + \tl_gput_right:Nn \g_@@_pre_code_after_tl + { + \@@_stroke_block:nnn + { + rounded-corners = \dim_use:N \l_@@_tab_rounded_corners_dim , + draw = \l_@@_rules_color_tl + } + { 1-1 } + { \int_use:N \c@iRow - \int_use:N \c@jCol } + } + } + } + } + \tl_if_empty:NF \l_@@_short_caption_tl + { + \tl_if_empty:NT \l_@@_caption_tl + { + \@@_error_or_warning:n { short-caption~without~caption } + \tl_set_eq:NN \l_@@_caption_tl \l_@@_short_caption_tl + } + } + \tl_if_empty:NF \l_@@_label_tl + { + \tl_if_empty:NT \l_@@_caption_tl + { \@@_error_or_warning:n { label~without~caption } } + } + \NewDocumentEnvironment { TabularNote } { b } + { + \bool_if:NTF \l_@@_in_code_after_bool + { \@@_error_or_warning:n { TabularNote~in~CodeAfter } } + { + \tl_if_empty:NF \g_@@_tabularnote_tl + { \tl_gput_right:Nn \g_@@_tabularnote_tl { \par } } + \tl_gput_right:Nn \g_@@_tabularnote_tl { ##1 } + } + } + { } + \bool_set_true:N \l_@@_NiceTabular_bool + \NiceArray { #2 } + } + { \endNiceArray } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_set_protected:Npn \@@_newcolumntype #1 + { + \cs_if_free:cT { NC @ find @ #1 } + { \NC@list \expandafter { \the \NC@list \NC@do #1 } } + \cs_set:cpn {NC @ find @ #1 } ##1 #1 { \NC@ { ##1 } } + \peek_meaning:NTF [ + { \newcol@ #1 } + { \newcol@ #1 [ 0 ] } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\NewDocumentEnvironment { NiceTabularX } { m O { } m ! O { } } + { +% \end{macrocode} +% The following code prevents the expansion of the `X` columns with the +% definition of that columns in \pkg{tabularx} (this would result in an error in +% |{NiceTabularX}|). +% \begin{macrocode} + \IfPackageLoadedTF { tabularx } + { \newcolumntype { X } { \@@_X } } + { } + \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 +% \section{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 \g_@@_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 +% used to recreate the blocks with a name in the |\CodeBefore| and also 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} +% +% \medskip +% We create the aliases using |last| for the nodes of the cells in the last row +% and the last column. +% \begin{macrocode} + \pgfpicture + \int_step_inline:nn \c@iRow + { + \pgfnodealias + { \@@_env: - ##1 - last } + { \@@_env: - ##1 - \int_use:N \c@jCol } + } + \int_step_inline:nn \c@jCol + { + \pgfnodealias + { \@@_env: - last - ##1 } + { \@@_env: - \int_use:N \c@iRow - ##1 } + } + \str_if_empty:NF \l_@@_name_str + { + \int_step_inline:nn \c@iRow + { + \pgfnodealias + { \l_@@_name_str - ##1 - last } + { \@@_env: - ##1 - \int_use:N \c@jCol } + } + \int_step_inline:nn \c@jCol + { + \pgfnodealias + { \l_@@_name_str - last - ##1 } + { \@@_env: - \int_use:N \c@iRow - ##1 } + } + } + \endpgfpicture +% \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_@@_xdots_radius_dim| and +% |\l_@@_xdots_inter_dim| (used to draw the dotted lines created by +% |\hdottedline| and |\vdottedline| 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_@@_xdots_radius_dim { 0.7 \l_@@_xdots_radius_dim } + \dim_set:Nn \l_@@_xdots_inter_dim { 0.55 \l_@@_xdots_inter_dim } +% \end{macrocode} +% The dimensions |\l_@@_xdots_shorten_start_dim| and +% |\l_@@_xdots_shorten_start_dim| correspond to the options +% |xdots/shorten-start| and |xdots/shorten-end| available to the user. +% \begin{macrocode} + \dim_set:Nn \l_@@_xdots_shorten_start_dim + { 0.6 \l_@@_xdots_shorten_start_dim } + \dim_set:Nn \l_@@_xdots_shorten_end_dim + { 0.6 \l_@@_xdots_shorten_end_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} +% +% \begin{macrocode} + \tl_if_empty:NF \l_@@_hlines_clist \@@_draw_hlines: + \tl_if_empty:NF \l_@@_vlines_clist \@@_draw_vlines: +% \end{macrocode} +% +% \bigskip +% Now, the pre-code-after and then, the |\CodeAfter|. +% \begin{macrocode} + \IfPackageLoadedTF { tikz } + { + \tikzset + { + every~picture / .style = + { + overlay , + remember~picture , + name~prefix = \@@_env: - + } + } + } + { } + \cs_set_eq:NN \ialign \@@_old_ialign: + \cs_set_eq:NN \SubMatrix \@@_SubMatrix + \cs_set_eq:NN \UnderBrace \@@_UnderBrace + \cs_set_eq:NN \OverBrace \@@_OverBrace + \cs_set_eq:NN \ShowCellNames \@@_ShowCellNames + \cs_set_eq:NN \line \@@_line + \g_@@_pre_code_after_tl + \tl_gclear:N \g_@@_pre_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 +% The following code is a security for the case the user has used \pkg{babel} +% with the option \pkg{spanish}: in that case, the characters |>| and |<| are +% activated and Tikz is not able to solve the problem (even with the Tikz +% library \pkg{babel}). +% \begin{macrocode} + \int_compare:nNnT { \char_value_catcode:n { 60 } } = { 13 } + { \@@_rescan_for_spanish:N \g_nicematrix_code_after_tl } +% \end{macrocode} +% \medskip +% 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} + \bool_set_true:N \l_@@_in_code_after_bool + \exp_last_unbraced:NV \@@_CodeAfter_keys: \g_nicematrix_code_after_tl + \scan_stop: + \tl_gclear:N \g_nicematrix_code_after_tl + \group_end: +% \end{macrocode} +% +% +% \medskip +% |\g_@@_pre_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_@@_pre_code_before_tl + { + \tl_gput_right:Nx \g_@@_aux_tl + { + \tl_gset:Nn \exp_not:N \g_@@_pre_code_before_tl + { \exp_not:V \g_@@_pre_code_before_tl } + } + \tl_gclear:N \g_@@_pre_code_before_tl + } + \tl_if_empty:NF \g_nicematrix_code_before_tl + { + \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 } + } + \tl_gclear:N \g_nicematrix_code_before_tl + } +% \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:nnnnn ##1 } + } +% \end{macrocode} +% +% The following command must \emph{not} be protected. +% \begin{macrocode} +\cs_new:Npn \@@_adjust_pos_of_blocks_seq_i:nnnnn #1 #2 #3 #4 #5 + { + { #1 } + { #2 } + { + \int_compare:nNnTF { #3 } > { 99 } + { \int_use:N \c@iRow } + { #3 } + } + { + \int_compare:nNnTF { #4 } > { 99 } + { \int_use:N \c@jCol } + { #4 } + } + { #5 } + } +% \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} +\hook_gput_code:nnn { begindocument } { . } + { + \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 +% 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 +% \section{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 } +% \end{macrocode} +% Be careful: with |\Iddots|, |\l_@@_final_j_int| is inferior to +% |\l_@@_initial_j_int|. That's why we use |\int_min:nn| and |\int_max:nn|. +% \begin{macrocode} + { \int_min:nn \l_@@_initial_j_int \l_@@_final_j_int } + { \int_use:N \l_@@_final_i_int } + { \int_max:nn \l_@@_initial_j_int \l_@@_final_j_int } + { } % for the name of the block + } + } +% \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 we are analyzing. +% \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 - \int_eval:n { \l_@@_final_j_int + 1 } } + \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_@@_xdots_radius_dim + \dim_add:Nn \l_@@_y_final_dim \l_@@_xdots_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 - \int_eval:n { \l_@@_initial_i_int + 1 } } + \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 + { + \fp_to_dim:n + { + \pgf@y + + ( \box_ht:N \strutbox + \extrarowheight ) * \arraystretch + } + } % modified 6.13c + \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 + { \fp_to_dim:n { \pgf@y - ( \box_dp:N \strutbox ) * \arraystretch } } + % modified 6.13c + \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 - \int_eval:n { \l_@@_initial_j_int + 1 } } + \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: + \@@_open_x_initial_dim: + } + { \@@_set_initial_coords_from_anchor:n { south~east } } + \bool_if:NTF \l_@@_final_open_bool + { + \@@_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 +% \section{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 + \bool_lazy_or:nnTF + { \tl_if_eq_p:NN \l_@@_xdots_line_style_tl \c_@@_standard_tl } + \l_@@_dotted_bool + \@@_draw_standard_dotted_line: + \@@_draw_unstandard_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_unstandard_dotted_line: + { + \begin { scope } + \@@_draw_unstandard_dotted_line:o + { \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_unstandard_dotted_line:n| is, in fact, the list of options. +% \begin{macrocode} +\cs_new_protected:Npn \@@_draw_unstandard_dotted_line:n #1 + { + \@@_draw_unstandard_dotted_line:nVV + { #1 } + \l_@@_xdots_up_tl + \l_@@_xdots_down_tl + } +\cs_generate_variant:Nn \@@_draw_unstandard_dotted_line:n { o } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_draw_unstandard_dotted_line:nnn #1 #2 #3 + { + \draw + [ + #1 , + shorten~> = \l_@@_xdots_shorten_end_dim , + shorten~< = \l_@@_xdots_shorten_start_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_unstandard_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_@@_xdots_inter_dim } + } + { + \int_set:Nn \l_tmpa_int + { + \dim_ratio:nn + { \l_@@_l_dim - \l_@@_xdots_shorten_start_dim } + \l_@@_xdots_inter_dim + } + } + } + { + \bool_if:NTF \l_@@_final_open_bool + { + \int_set:Nn \l_tmpa_int + { + \dim_ratio:nn + { \l_@@_l_dim - \l_@@_xdots_shorten_end_dim } + \l_@@_xdots_inter_dim + } + } + { + \int_set:Nn \l_tmpa_int + { + \dim_ratio:nn + { + \l_@@_l_dim + - \l_@@_xdots_shorten_start_dim - \l_@@_xdots_shorten_end_dim + } + \l_@@_xdots_inter_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_@@_xdots_inter_dim \l_@@_l_dim + } + \dim_set:Nn \l_tmpb_dim + { + ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) * + \dim_ratio:nn \l_@@_xdots_inter_dim \l_@@_l_dim + } +% \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_@@_xdots_inter_dim * \l_tmpa_int + + \l_@@_xdots_shorten_start_dim - \l_@@_xdots_shorten_end_dim + } + { 2 \l_@@_l_dim } + } + \dim_gadd:Nn \l_@@_y_initial_dim + { + ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) * + \dim_ratio:nn + { + \l_@@_l_dim - \l_@@_xdots_inter_dim * \l_tmpa_int + + \l_@@_xdots_shorten_start_dim - \l_@@_xdots_shorten_end_dim + } + { 2 \l_@@_l_dim } + } + \pgf@relevantforpicturesizefalse + \int_step_inline:nnn 0 \l_tmpa_int + { + \pgfpathcircle + { \pgfpoint \l_@@_x_initial_dim \l_@@_y_initial_dim } + { \l_@@_xdots_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 +% \section{User commands available in the new environments} +% +% +% 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 |\hook_gput_code:nnn { begindocument } { . }| +% and the \emph{arg spec} will be rescanned. +% +% \begin{macrocode} +\hook_gput_code:nnn { begindocument } { . } + { + \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 |\AddToHook|. +% +% +% \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} +\hook_gput_code:nnn { begindocument } { . } + { + \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} +% +% \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} +\hook_gput_code:nnn { begindocument } { . } + { + \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 |\AddToHook|. +% +% \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 +% \section{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 the following behaviour: +% \begin{itemize} +% \item If the argument is of the format $i$-$j$, our command applies +% the command |\int_eval:n| to $i$ and~$j$ ; +% \item If not (that is to say, when it's a name of a |\Block|), the argument is +% left unchanged. +% \end{itemize} +% 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 + { + \tl_if_empty:nTF { #2 } + { #1 } + { \@@_double_int_eval_i:n #1-#2 \q_stop } + } +\cs_new:Npn \@@_double_int_eval_i: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} +\hook_gput_code:nnn { begindocument } { . } + { + \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} +\hook_gput_code:nnn { begindocument } { . } + { + \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 +% \section{The command \textbackslash RowStyle} +% +% \medskip +% \begin{macrocode} +\keys_define:nn { NiceMatrix / RowStyle } + { + cell-space-top-limit .dim_set:N = \l_tmpa_dim , + cell-space-top-limit .initial:n = \c_zero_dim , + cell-space-top-limit .value_required:n = true , + cell-space-bottom-limit .dim_set:N = \l_tmpb_dim , + cell-space-bottom-limit .initial:n = \c_zero_dim , + cell-space-bottom-limit .value_required:n = true , + cell-space-limits .meta:n = + { + cell-space-top-limit = #1 , + cell-space-bottom-limit = #1 , + } , + color .tl_set:N = \l_@@_color_tl , + color .value_required:n = true , + bold .bool_set:N = \l_tmpa_bool , + bold .default:n = true , + bold .initial:n = false , + nb-rows .code:n = + \str_if_eq:nnTF { #1 } { * } + { \int_set:Nn \l_@@_key_nb_rows_int { 500 } } + { \int_set:Nn \l_@@_key_nb_rows_int { #1 } } , + nb-rows .value_required:n = true , + rowcolor .tl_set:N = \l_tmpa_tl , + rowcolor .value_required:n = true , + rowcolor .initial:n = , + unknown .code:n = \@@_error:n { Unknown~key~for~RowStyle } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\NewDocumentCommand \@@_RowStyle:n { O { } m } + { + \group_begin: + \tl_clear:N \l_tmpa_tl % value of \rowcolor + \tl_clear:N \l_@@_color_tl + \int_set:Nn \l_@@_key_nb_rows_int 1 + \keys_set:nn { NiceMatrix / RowStyle } { #1 } +% \end{macrocode} +% If the key |rowcolor| has been used. +% \begin{macrocode} + \tl_if_empty:NF \l_tmpa_tl + { +% \end{macrocode} +% First, the end of the current row (we remind that |\RowStyle| applies to the +% \emph{end} of the current row). +% \begin{macrocode} + \tl_gput_right:Nx \g_@@_pre_code_before_tl + { +% \end{macrocode} +% The command |\@@_exp_color_arg:NV| is \emph{fully expandable}. +% \begin{macrocode} + \@@_exp_color_arg:NV \@@_rectanglecolor \l_tmpa_tl + { \int_use:N \c@iRow - \int_use:N \c@jCol } + { \int_use:N \c@iRow - * } + } +% \end{macrocode} +% Then, the other rows (if there is several rows). +% \begin{macrocode} + \int_compare:nNnT \l_@@_key_nb_rows_int > 1 + { + \tl_gput_right:Nx \g_@@_pre_code_before_tl + { + \@@_exp_color_arg:NV \@@_rowcolor \l_tmpa_tl + { + \int_eval:n { \c@iRow + 1 } + - \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int - 1 } + } + } + } + } + \tl_gput_right:Nn \g_@@_row_style_tl { \ifnum \c@iRow < } + \tl_gput_right:Nx \g_@@_row_style_tl + { \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int } } + \tl_gput_right:Nn \g_@@_row_style_tl { #2 } +% \end{macrocode} +% |\l_tmpa_dim| is the value of the key |cell-space-top-limit| of |\RowStyle|. +% \begin{macrocode} + \dim_compare:nNnT \l_tmpa_dim > \c_zero_dim + { + \tl_gput_right:Nx \g_@@_row_style_tl + { + \tl_gput_right:Nn \exp_not:N \g_@@_cell_after_hook_tl + { + \dim_set:Nn \l_@@_cell_space_top_limit_dim + { \dim_use:N \l_tmpa_dim } + } + } + } +% \end{macrocode} +% |\l_tmpb_dim| is the value of the key |cell-space-bottom-limit| of |\RowStyle|. +% \begin{macrocode} + \dim_compare:nNnT \l_tmpb_dim > \c_zero_dim + { + \tl_gput_right:Nx \g_@@_row_style_tl + { + \tl_gput_right:Nn \exp_not:N \g_@@_cell_after_hook_tl + { + \dim_set:Nn \l_@@_cell_space_bottom_limit_dim + { \dim_use:N \l_tmpb_dim } + } + } + } +% \end{macrocode} +% |\l_@@_color_tl| is the value of the key |color| of |\RowStyle|. +% \begin{macrocode} + \tl_if_empty:NF \l_@@_color_tl + { + \tl_gput_right:Nx \g_@@_row_style_tl + { + \mode_leave_vertical: + \@@_color:n { \l_@@_color_tl } + } + } +% \end{macrocode} +% |\l_tmpa_bool| is the value of the key |bold|. +% \begin{macrocode} + \bool_if:NT \l_tmpa_bool + { + \tl_gput_right:Nn \g_@@_row_style_tl + { + \if_mode_math: + \c_math_toggle_token + \bfseries \boldmath + \c_math_toggle_token + \else: + \bfseries \boldmath + \fi: + } + } + \tl_gput_right:Nn \g_@@_row_style_tl { \fi } + \group_end: + \g_@@_row_style_tl + \ignorespaces + } +% \end{macrocode} +% +% \bigskip +% \section{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 +% \end{macrocode} +% We don't take into account the colors like |myserie!!+| because those colors +% are special color from a |\definecolorseries| of \pkg{xcolor}. +% \begin{macrocode} + \str_if_in:nnF { #1 } { !! } + { + \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 +% \end{macrocode} +% If the final user has used the key |rounded-corners| for the environment +% |{NiceTabular}|, we will clip to a rectangle with rounded corners before +% filling the rectangles. +% \begin{macrocode} + \dim_compare:nNnT \l_@@_tab_rounded_corners_dim > \c_zero_dim + { + \pgfsetcornersarced + { + \pgfpoint + { \l_@@_tab_rounded_corners_dim } + { \l_@@_tab_rounded_corners_dim } + } +% \end{macrococde} +% Because we want \pkg{nicematrix} compatible with arrays constructed by +% \pkg{array}, the nodes for the rows and columns (that is to say the nodes +% |row-|\textsl{i} and |col-|\textsl{j}) have not always the expected position, +% that is to say, there is sometimes a slight shifting of something such as +% |\arrayrulewidth|. Now, for the clipping, we have to change slightly the +% position of that clipping whether a rounded rectangle around the array is +% required. That's the point which is tested in the following line. +% \begin{macrocode} + \bool_if:NTF \l_@@_hvlines_bool + { + \pgfpathrectanglecorners + { + \pgfpointadd + { \@@_qpoint:n { row-1 } } + { \pgfpoint { 0.5 \arrayrulewidth } { \c_zero_dim } } + } + { + \pgfpointadd + { + \@@_qpoint:n + { \int_eval:n { \int_max:nn \c@iRow \c@jCol + 1 } } + } + { \pgfpoint \c_zero_dim { 0.5 \arrayrulewidth } } + } + } + { + \pgfpathrectanglecorners + { \@@_qpoint:n { row-1 } } + { + \pgfpointadd + { + \@@_qpoint:n + { \int_eval:n { \int_max:nn \c@iRow \c@jCol + 1 } } + } + { \pgfpoint \c_zero_dim \arrayrulewidth } + } + } + \pgfusepath { clip } + } + \seq_map_indexed_inline:Nn \g_@@_colors_seq + { + \begin { pgfscope } + \@@_color_opacity ##2 + \use:c { g_@@_color _ ##1 _tl } + \tl_gclear:c { g_@@_color _ ##1 _tl } + \pgfusepath { fill } + \end { pgfscope } + } + \endpgfpicture + } +% \end{macrocode} +% +% \bigskip +% The following command will extract the potential key |opacity| in its optional +% argument (between square brackets) and (of course) then apply the command |\color|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_color_opacity + { + \peek_meaning:NTF [ + { \@@_color_opacity:w } + { \@@_color_opacity:w [ ] } + } +% \end{macrocode} +% +% \bigskip +% The command |\@@_color_opacity:w| takes in as argument only the optional +% argument. One may consider that the second argument (the actual definition of +% the color) is provided by currification. +% \begin{macrocode} +\cs_new_protected:Npn \@@_color_opacity:w [ #1 ] + { + \tl_clear:N \l_tmpa_tl + \keys_set_known:nnN { nicematrix / color-opacity } { #1 } \l_tmpb_tl +% \end{macrocode} +% |\l_tmpa_tl| (if not empty) is now the opacity and |\l_tmpb_tl| (if not empty) is now the colorimetric space. +% \begin{macrocode} + \tl_if_empty:NF \l_tmpa_tl { \exp_args:NV \pgfsetfillopacity \l_tmpa_tl } + \tl_if_empty:NTF \l_tmpb_tl + { \@declaredcolor } + { \use:x { \exp_not:N \@undeclaredcolor [ \l_tmpb_tl ] } } + } +% \end{macrocode} +% +% \bigskip +% The following set of keys is used by the command |\@@_color_opacity:wn|. +% \begin{macrocode} +\keys_define:nn { nicematrix / color-opacity } + { + opacity .tl_set:N = \l_tmpa_tl , + opacity .value_required:n = true + } +% \end{macrocode} +% +% \bigskip +% \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 +% The command |\@@_arraycolor| (linked to |\arraycolor| at the beginning of +% the |\CodeBefore|) will color the whole tabular (excepted the potential +% exterior rows and columns) and the cells in the ``corners''. +% \begin{macrocode} +\NewDocumentCommand \@@_arraycolor { O { } m } + { + \@@_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 \textsl{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:nnnnn ##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:nnnnn ####1 } + \seq_map_inline:Nn \l_tmpb_seq { \@@_rowcolors_i:nnnnn ####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:nnnnn #1 #2 #3 #4 #5 + { + \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:nnnnn p + { + \bool_lazy_or:nnTF + { \int_compare_p:nNn { #4 } = \c_zero_int } + { \int_compare_p:nNn { #2 } = { \int_eval:n { \c@jCol + 1 } } } + \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:nnnnn 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 - \int_eval:n { \l_tmpb_tl + 1 } } + \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 - \int_eval:n { \l_tmpb_tl + 1 } } + \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 } + { + \tl_gput_right:Nx \g_@@_pre_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 } + } + \ignorespaces + } +% \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 } + { + \tl_gput_right:Nx \g_@@_pre_code_before_tl + { + \@@_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 } } + } + \ignorespaces + } +% \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_@@_pre_code_before_tl + { + \exp_not:N \columncolor [ #1 ] + { \exp_not:n { #2 } } { \int_use:N \c@jCol } + } + } + } +% \end{macrocode} +% +% +% +% \bigskip +% \section{The vertical and horizontal rules} +% +% +% \bigskip +% \subsubsection*{OnlyMainNiceMatrix} +% +% 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 +% \subsubsection*{General system for drawing rules} +% +% When a command, environment or ``subsystem'' of \pkg{nicematrix} wants to draw +% a rule, it will write in the internal |\CodeAfter| a command |\@@_vline:n| or +% |\@@_hline:n|. Both commands take in as argument a list of \textsl{key=value} +% pairs. That list will first be analyzed with the following set of keys. +% However, unknown keys will be analyzed further with another set of keys. +% +% \begin{macrocode} +\keys_define:nn { NiceMatrix / Rules } + { + position .int_set:N = \l_@@_position_int , + position .value_required:n = true , + start .int_set:N = \l_@@_start_int , + start .initial:n = 1 , + end .code:n = + \bool_lazy_or:nnTF + { \tl_if_empty_p:n { #1 } } + { \str_if_eq_p:nn { #1 } { last } } + { \int_set_eq:NN \l_@@_end_int \c@jCol } + { \int_set:Nn \l_@@_end_int { #1 } } + } +% \end{macrocode} +% +% \bigskip +% It's possible that the rule won't be drawn continuously from |start| ot |end| +% because of the blocks (created with the command |\Block|), the virtual blocks +% (created by |\Cdots|, etc.), etc. That's why an analyse is done and the rule +% is cut in small rules which will actually be drawn. The small continuous rules +% will be drawn by |\@@_vline_ii:| and |\@@_hline_ii:|. Those commands use the +% following set of keys. +% +% \begin{macrocode} +\keys_define:nn { NiceMatrix / RulesBis } + { + multiplicity .int_set:N = \l_@@_multiplicity_int , + multiplicity .initial:n = 1 , + dotted .bool_set:N = \l_@@_dotted_bool , + dotted .initial:n = false , + dotted .default:n = true , + color .code:n = \@@_set_CT@arc@:n { #1 } , + color .value_required:n = true , + sep-color .code:n = \@@_set_CT@drsc@:n { #1 } , + sep-color .value_required:n = true , +% \end{macrocode} +% If the user uses the key |tikz|, the rule (or more precisely: the different +% sub-rules since a rule may be broken by blocks or others) will be drawn with +% Tikz. +% \begin{macrocode} + tikz .tl_set:N = \l_@@_tikz_rule_tl , + tikz .value_required:n = true , + tikz .initial:n = , + total-width .dim_set:N = \l_@@_rule_width_dim , + total-width .value_required:n = true , + width .meta:n = { total-width = #1 } , + unknown .code:n = \@@_error:n { Unknow~key~for~RulesBis } + } +% \end{macrocode} +% +% +% \subsubsection*{The vertical rules} +% +% The following command will be executed in the internal |\CodeAfter|. The +% argument |#1| is a list of \textsl{key=value} pairs. +% \begin{macrocode} +\cs_new_protected:Npn \@@_vline:n #1 + { +% \end{macrocode} +% The group is for the options. +% \begin{macrocode} + \group_begin: + \int_zero_new:N \l_@@_end_int + \int_set_eq:NN \l_@@_end_int \c@iRow + \keys_set_known:nnN { NiceMatrix / Rules } { #1 } \l_@@_other_keys_tl +% \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 \l_@@_position_int < { \c@jCol + 2 } + \@@_vline_i: + \group_end: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_vline_i: + { + \int_zero_new:N \l_@@_local_start_int + \int_zero_new:N \l_@@_local_end_int +% \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 { \int_eval:n \l_@@_position_int } + \int_step_variable:nnNn \l_@@_start_int \l_@@_end_int + \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:nnnnn ##1 } + \seq_map_inline:Nn \g_@@_pos_of_xdots_seq + { \@@_test_vline_in_block:nnnnn ##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 + { + \int_compare:nNnT \l_@@_local_start_int = 0 +% \end{macrocode} +% We keep in memory that we have a rule to draw. |\l_@@_local_start_int| will be +% the starting row of the rule that we will have to draw. +% \begin{macrocode} + { \int_set:Nn \l_@@_local_start_int \l_tmpa_tl } + } + { + \int_compare:nNnT \l_@@_local_start_int > 0 + { + \int_set:Nn \l_@@_local_end_int { \l_tmpa_tl - 1 } + \@@_vline_ii: + \int_zero:N \l_@@_local_start_int + } + } + } + \int_compare:nNnT \l_@@_local_start_int > 0 + { + \int_set_eq:NN \l_@@_local_end_int \l_@@_end_int + \@@_vline_ii: + } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_test_in_corner_v: + { + \int_compare:nNnTF \l_tmpb_tl = { \int_eval:n { \c@jCol + 1 } } + { + \seq_if_in:NxT + \l_@@_corners_cells_seq + { \l_tmpa_tl - \int_eval:n { \l_tmpb_tl - 1 } } + { \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 - \int_eval:n { \l_tmpb_tl - 1 } } + { \bool_set_false:N \g_tmpa_bool } + } + } + } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_vline_ii: + { + \keys_set:nV { NiceMatrix / RulesBis } \l_@@_other_keys_tl + \bool_if:NTF \l_@@_dotted_bool + \@@_vline_iv: + { + \tl_if_empty:NTF \l_@@_tikz_rule_tl + \@@_vline_iii: + \@@_vline_v: + } + } +% \end{macrocode} +% +% \bigskip +% First the case of a standard rule: the user has not used the key |dotted| nor +% the key |tikz|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_vline_iii: + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \@@_qpoint:n { row - \int_use:N \l_@@_local_start_int } + \dim_set_eq:NN \l_tmpa_dim \pgf@y + \@@_qpoint:n { col - \int_use:N \l_@@_position_int } + \dim_set:Nn \l_tmpb_dim + { + \pgf@x + - 0.5 \l_@@_rule_width_dim + + + ( \arrayrulewidth * \l_@@_multiplicity_int + + \doublerulesep * ( \l_@@_multiplicity_int - 1 ) ) / 2 + } + \@@_qpoint:n { row - \int_eval:n { \l_@@_local_end_int + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y + \bool_lazy_all:nT + { + { \int_compare_p:nNn \l_@@_multiplicity_int > 1 } + { \cs_if_exist_p:N \CT@drsc@ } + { ! \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 ) + * ( \l_@@_multiplicity_int - 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 { \l_@@_multiplicity_int - 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 + \endpgfpicture + } +% \end{macrocode} +% +% +% \bigskip +% The following code is for the case of a dotted rule (with our system of +% rounded dots). +% \begin{macrocode} +\cs_new_protected:Npn \@@_vline_iv: + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \@@_qpoint:n { col - \int_use:N \l_@@_position_int } + \dim_set:Nn \l_@@_x_initial_dim { \pgf@x - 0.5 \l_@@_rule_width_dim } + \dim_set_eq:NN \l_@@_x_final_dim \l_@@_x_initial_dim + \@@_qpoint:n { row - \int_use:N \l_@@_local_start_int } + \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y + \@@_qpoint:n { row - \int_eval:n { \l_@@_local_end_int + 1 } } + \dim_set_eq:NN \l_@@_y_final_dim \pgf@y + \CT@arc@ + \@@_draw_line: + \endpgfpicture + } +% \end{macrocode} +% +% \bigskip +% The following code is for the case when the user uses the key |tikz| (in the +% definition of a customized rule by using the key |custom-line|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_vline_v: + { + \begin {tikzpicture } + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \@@_qpoint:n { row - \int_use:N \l_@@_local_start_int } + \dim_set_eq:NN \l_tmpa_dim \pgf@y + \@@_qpoint:n { col - \int_use:N \l_@@_position_int } + \dim_set:Nn \l_tmpb_dim { \pgf@x - 0.5 \l_@@_rule_width_dim } + \@@_qpoint:n { row - \int_eval:n { \l_@@_local_end_int + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y + \exp_args:NV \tikzset \l_@@_tikz_rule_tl + \use:x { \exp_not:N \draw [ \l_@@_tikz_rule_tl ] } + ( \l_tmpb_dim , \l_tmpa_dim ) -- + ( \l_tmpb_dim , \l_@@_tmpc_dim ) ; + \end { tikzpicture } + } +% \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 { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } + 1 2 + } + { + \bool_if:nTF { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } + { \int_eval:n { \c@jCol + 1 } } + \c@jCol + } + { + \tl_if_eq:NnF \l_@@_vlines_clist { all } + { \clist_if_in:NnT \l_@@_vlines_clist { ##1 } } + { \@@_vline:n { position = ##1 , total-width = \arrayrulewidth } } + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{The horizontal rules} +% +% \bigskip +% The following command will be executed in the internal |\CodeAfter|. The +% argument |#1| is a list of \textsl{key=value} pairs of the form +% |{NiceMatrix/Rules}|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_hline:n #1 + { +% \end{macrocode} +% The group is for the options. +% \begin{macrocode} + \group_begin: + \int_zero_new:N \l_@@_end_int + \int_set_eq:NN \l_@@_end_int \c@jCol + \keys_set_known:nnN { NiceMatrix / Rules } { #1 } \l_@@_other_keys_tl + \@@_hline_i: + \group_end: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_hline_i: + { + \int_zero_new:N \l_@@_local_start_int + \int_zero_new:N \l_@@_local_end_int +% \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:Nx \l_tmpa_tl { \int_use:N \l_@@_position_int } + \int_step_variable:nnNn \l_@@_start_int \l_@@_end_int + \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:nnnnn ##1 } + \seq_map_inline:Nn \g_@@_pos_of_xdots_seq + { \@@_test_hline_in_block:nnnnn ##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 + { + \int_compare:nNnT \l_@@_local_start_int = 0 +% \end{macrocode} +% We keep in memory that we have a rule to draw. |\l_@@_local_start_int| will be +% the starting row of the rule that we will have to draw. +% \begin{macrocode} + { \int_set:Nn \l_@@_local_start_int \l_tmpb_tl } + } + { + \int_compare:nNnT \l_@@_local_start_int > 0 + { + \int_set:Nn \l_@@_local_end_int { \l_tmpb_tl - 1 } + \@@_hline_ii: + \int_zero:N \l_@@_local_start_int + } + } + } + \int_compare:nNnT \l_@@_local_start_int > 0 + { + \int_set_eq:NN \l_@@_local_end_int \l_@@_end_int + \@@_hline_ii: + } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_test_in_corner_h: + { + \int_compare:nNnTF \l_tmpa_tl = { \int_eval:n { \c@iRow + 1 } } + { + \seq_if_in:NxT + \l_@@_corners_cells_seq + { \int_eval:n { \l_tmpa_tl - 1 } - \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 + { \int_eval:n { \l_tmpa_tl - 1 } - \l_tmpb_tl } + { \bool_set_false:N \g_tmpa_bool } + } + } + } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_hline_ii: + { + % \bool_set_false:N \l_@@_dotted_bool + \keys_set:nV { NiceMatrix / RulesBis } \l_@@_other_keys_tl + \bool_if:NTF \l_@@_dotted_bool + \@@_hline_iv: + { + \tl_if_empty:NTF \l_@@_tikz_rule_tl + \@@_hline_iii: + \@@_hline_v: + } + } +% \end{macrocode} +% +% \bigskip +% First the case of a standard rule (without the keys |dotted| and |tikz|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_hline_iii: + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \@@_qpoint:n { col - \int_use:N \l_@@_local_start_int } + \dim_set_eq:NN \l_tmpa_dim \pgf@x + \@@_qpoint:n { row - \int_use:N \l_@@_position_int } + \dim_set:Nn \l_tmpb_dim + { + \pgf@y + - 0.5 \l_@@_rule_width_dim + + + ( \arrayrulewidth * \l_@@_multiplicity_int + + \doublerulesep * ( \l_@@_multiplicity_int - 1 ) ) / 2 + } + \@@_qpoint:n { col - \int_eval:n { \l_@@_local_end_int + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x + \bool_lazy_all:nT + { + { \int_compare_p:nNn \l_@@_multiplicity_int > 1 } + { \cs_if_exist_p:N \CT@drsc@ } + { ! \tl_if_blank_p:V \CT@drsc@ } + } + { + \group_begin: + \CT@drsc@ + \dim_set:Nn \l_@@_tmpd_dim + { + \l_tmpb_dim - ( \doublerulesep + \arrayrulewidth ) + * ( \l_@@_multiplicity_int - 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 { \l_@@_multiplicity_int - 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 + \endpgfpicture + } +% \end{macrocode} +% +% \bigskip +% The following code is for the case of a dotted rule (with our system of +% rounded dots). +% 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}$ +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_hline_iv: + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \@@_qpoint:n { row - \int_use:N \l_@@_position_int } + \dim_set:Nn \l_@@_y_initial_dim { \pgf@y - 0.5 \l_@@_rule_width_dim } + \dim_set_eq:NN \l_@@_y_final_dim \l_@@_y_initial_dim + \@@_qpoint:n { col - \int_use:N \l_@@_local_start_int } + \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x + \int_compare:nNnT \l_@@_local_start_int = 1 + { + \dim_sub:Nn \l_@@_x_initial_dim \l_@@_left_margin_dim + \bool_if:NT \g_@@_NiceArray_bool + { \dim_sub:Nn \l_@@_x_initial_dim \arraycolsep } +% \end{macrocode} +% For reasons purely aesthetic, we do an adjustment in the case of a rounded +% bracket. The correction by |0.5 \l_@@_xdots_inter_dim| is \emph{ad hoc} for a +% better result. +% \begin{macrocode} + \tl_if_eq:NnF \g_@@_left_delim_tl ( + { \dim_add:Nn \l_@@_x_initial_dim { 0.5 \l_@@_xdots_inter_dim } } + } + \@@_qpoint:n { col - \int_eval:n { \l_@@_local_end_int + 1 } } + \dim_set_eq:NN \l_@@_x_final_dim \pgf@x + \int_compare:nNnT \l_@@_local_end_int = \c@jCol + { + \dim_add:Nn \l_@@_x_final_dim \l_@@_right_margin_dim + \bool_if:NT \g_@@_NiceArray_bool + { \dim_add:Nn \l_@@_x_final_dim \arraycolsep } + \tl_if_eq:NnF \g_@@_right_delim_tl ) + { \dim_gsub:Nn \l_@@_x_final_dim { 0.5 \l_@@_xdots_inter_dim } } + } + \CT@arc@ + \@@_draw_line: + \endpgfpicture + } +% \end{macrocode} +% +% \bigskip +% The following code is for the case when the user uses the key |tikz| (in the +% definition of a customized rule by using the key |custom-line|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_hline_v: + { + \begin { tikzpicture } + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \@@_qpoint:n { col - \int_use:N \l_@@_local_start_int } + \dim_set_eq:NN \l_tmpa_dim \pgf@x + \@@_qpoint:n { row - \int_use:N \l_@@_position_int } + \dim_set:Nn \l_tmpb_dim { \pgf@y - 0.5 \l_@@_rule_width_dim } + \@@_qpoint:n { col - \int_eval:n { \l_@@_local_end_int + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x + \exp_args:NV \tikzset \l_@@_tikz_rule_tl + \use:x { \exp_not:N \draw [ \l_@@_tikz_rule_tl ] } + ( \l_tmpa_dim , \l_tmpb_dim ) -- + ( \l_@@_tmpc_dim , \l_tmpb_dim ) ; + \end { tikzpicture } + } +% \end{macrocode} +% +% +% \bigskip +% The command |\@@_draw_hlines:| draws all the horizontal rules excepted in the +% blocks (even the virtual blocks 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 { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } + 1 2 + } + { + \bool_if:nTF { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } + { \int_eval:n { \c@iRow + 1 } } + \c@iRow + } + { + \tl_if_eq:NnF \l_@@_hlines_clist { all } + { \clist_if_in:NnT \l_@@_hlines_clist { ##1 } } + { \@@_hline:n { position = ##1 , total-width = \arrayrulewidth } } + } + } +% \end{macrocode} +% +% +% \medskip +% The command |\@@_Hline:| will be linked to |\Hline| in the environments of +% \pkg{nicematrix}. +% \begin{macrocode} +\cs_set:Npn \@@_Hline: { \noalign \bgroup \@@_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_remove_spaces:n + { + \peek_meaning: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 + { + \peek_meaning:NTF [ + { \@@_Hline_iv:nw { #1 } } + { \@@_Hline_iv:nw { #1 } [ ] } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set:Npn \@@_Hline_iv:nw #1 [ #2 ] + { + \@@_compute_rule_width:n { multiplicity = #1 , #2 } + \skip_vertical:n { \l_@@_rule_width_dim } + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { + \@@_hline:n + { + multiplicity = #1 , + position = \int_eval:n { \c@iRow + 1 } , + total-width = \dim_use:N \l_@@_rule_width_dim , + #2 + } + } + \egroup + } +% \end{macrocode} +% +% \subsubsection*{Customized rules defined by the final user} +% +% The final user can define a customized rule by using the key |custom-line| in +% |\NiceMatrixOptions|. That key takes in as value a list of \textsl{key=value} +% pairs. +% +% +% +% \medskip +% Among the keys avalaible in that list, there is the key |letter| to specify a +% letter that the final user will use in the preamble of the array. All the +% letters defined by this way by the final user for such customized rules are +% added in the set of keys |{NiceMatrix / ColumnTypes}|. That set of keys is +% used to store the characteristics of those types of rules for convenience: the +% keys of that set of keys won't never be used as keys by the final user (he +% will use, instead, letters in the preamble of its array). +% +% \begin{macrocode} +\keys_define:nn { NiceMatrix / ColumnTypes } { } +% \end{macrocode} +% +% +% \medskip +% The following command will create the customized rule (it is executed when the +% final user uses the key |custom-line|, for example in |\NiceMatrixOptions|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_custom_line:n #1 + { + \str_clear_new:N \l_@@_command_str + \str_clear_new:N \l_@@_ccommand_str + \str_clear_new:N \l_@@_letter_str + \keys_set_known:nnN { NiceMatrix / custom-line } { #1 } \l_@@_other_keys_tl +% \end{macrocode} +% If the final user only wants to draw horizontal rules, he does not need to +% specify a letter (for the vertical rules in the preamble of the array). On the +% other hand, if he only wants to draw vertical rules, he does not need to +% define a command (which is the tool to draw horizontal rules in the array). Of +% course, a definition of custom lines with no letter and no command would be point-less. +% +% \begin{macrocode} + \bool_lazy_all:nTF + { + { \str_if_empty_p:N \l_@@_letter_str } + { \str_if_empty_p:N \l_@@_command_str } + { \str_if_empty_p:N \l_@@_ccommand_str } + } + { \@@_error:n { No~letter~and~no~command } } + { \exp_args:NV \@@_custom_line_i:n \l_@@_other_keys_tl } + } +% \end{macrocode} +% +% +% \begin{macrocode} +\keys_define:nn { NiceMatrix / custom-line } + { + letter .str_set:N = \l_@@_letter_str , + letter .value_required:n = true , + command .str_set:N = \l_@@_command_str , + command .value_required:n = true , + ccommand .str_set:N = \l_@@_ccommand_str , + ccommand .value_required:n = true , + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_custom_line_i:n #1 + { +% \end{macrocode} +% The following flags will be raised when the keys |tikz|, |dotted| and |color| +% are used (in the |custom-line|). +% \begin{macrocode} + \bool_set_false:N \l_@@_tikz_rule_bool + \bool_set_false:N \l_@@_dotted_rule_bool + \bool_set_false:N \l_@@_color_bool +% \end{macrocode} +% \begin{macrocode} + \keys_set:nn { NiceMatrix / custom-line-bis } { #1 } + \bool_if:NT \l_@@_tikz_rule_bool + { + \IfPackageLoadedTF { tikz } + { } + { \@@_error:n { tikz~in~custom-line~without~tikz }} + \bool_if:NT \l_@@_color_bool + { \@@_error:n { color~in~custom-line~with~tikz } } + } + \bool_if:nT + { + \int_compare_p:nNn \l_@@_multiplicity_int > 1 + && \l_@@_dotted_rule_bool + } + { \@@_error:n { key~multiplicity~with~dotted } } + \str_if_empty:NF \l_@@_letter_str + { + \int_compare:nTF { \str_count:N \l_@@_letter_str != 1 } + { \@@_error:n { Several~letters } } + { + \exp_args:NnV \tl_if_in:NnTF + \c_@@_forbidden_letters_str \l_@@_letter_str + { \@@_error:n { Forbidden~letter } } + { +% \end{macrocode} +% The final user can, locally, redefine a letter of column type. That's +% compatible with the use of |\keys_define:nn|: the definition is local and may +% overwrite a previous definition. +% \begin{macrocode} + \keys_define:nx { NiceMatrix / ColumnTypes } + { + \l_@@_letter_str .code:n = + { \@@_v_custom_line:n { \exp_not:n { #1 } } } + } + } + } + } + \str_if_empty:NF \l_@@_command_str { \@@_h_custom_line:n { #1 } } + \str_if_empty:NF \l_@@_ccommand_str { \@@_c_custom_line:n { #1 } } + } +% \end{macrocode} +% +% +% \begin{macrocode} +\str_const:Nn \c_@@_forbidden_letters_str { lcrpmbVX|()[]!@<> } +% \end{macrocode} +% +% \medskip +% The previous command |\@@_custom_line_i:n| uses the following set of keys. +% However, the whole definition of the customized lines (as provided by the +% final user as argument of |custom-line|) will also be used further with +% other sets of keys (for instance |{NiceMatrix/Rules}|). That's why the +% following set of keys has some keys which are no-op. +% \begin{macrocode} +\keys_define:nn { NiceMatrix / custom-line-bis } + { + multiplicity .int_set:N = \l_@@_multiplicity_int , + multiplicity .initial:n = 1 , + multiplicity .value_required:n = true , + color .code:n = \bool_set_true:N \l_@@_color_bool , + color .value_required:n = true , + tikz .code:n = \bool_set_true:N \l_@@_tikz_rule_bool , + tikz .value_required:n = true , + dotted .code:n = \bool_set_true:N \l_@@_dotted_rule_bool , + dotted .value_forbidden:n = true , + total-width .code:n = { } , + total-width .value_required:n = true , + width .code:n = { } , + width .value_required:n = true , + sep-color .code:n = { } , + sep-color .value_required:n = true , + unknown .code:n = \@@_error:n { Unknown~key~for~custom-line } + } +% \end{macrocode} +% +% The following keys will indicate whether the keys |dotted|, |tikz| and |color| +% are used in the use of a |custom-line|. +% \begin{macrocode} +\bool_new:N \l_@@_dotted_rule_bool +\bool_new:N \l_@@_tikz_rule_bool +\bool_new:N \l_@@_color_bool +% \end{macrocode} +% +% \bigskip +% The following keys are used to determine the total width of the line +% (including the spaces on both sides of the line). The key |width| is +% deprecated and has been replaced by the key |total-width|. +% +% \begin{macrocode} +\keys_define:nn { NiceMatrix / custom-line-width } + { + multiplicity .int_set:N = \l_@@_multiplicity_int , + multiplicity .initial:n = 1 , + multiplicity .value_required:n = true , + tikz .code:n = \bool_set_true:N \l_@@_tikz_rule_bool , + total-width .code:n = \dim_set:Nn \l_@@_rule_width_dim { #1 } + \bool_set_true:N \l_@@_total_width_bool , + total-width .value_required:n = true , + width .meta:n = { total-width = #1 } , + dotted .code:n = \bool_set_true:N \l_@@_dotted_rule_bool , + } +% \end{macrocode} +% +% \bigskip +% The following command will create the command that the final user will use in +% its array to draw an horizontal rule (hence the `|h|` in the name) with the +% full width of the array. |#1| is the whole set of keys to pass to the command +% |\@@_hline:n| (which is in the internal |\CodeAfter|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_h_custom_line:n #1 + { +% \end{macrocode} +% We use |\cs_set:cpn| and not |\cs_new:cpn| because we want a local definition. +% Moreover, the command must \emph{not} be protected since it begins with |\noalign|. +% \begin{macrocode} + \cs_set:cpn { nicematrix - \l_@@_command_str } + { + \noalign + { + \@@_compute_rule_width:n { #1 } + \skip_vertical:n { \l_@@_rule_width_dim } + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { + \@@_hline:n + { + #1 , + position = \int_eval:n { \c@iRow + 1 } , + total-width = \dim_use:N \l_@@_rule_width_dim + } + } + } + } + \seq_put_left:NV \l_@@_custom_line_commands_seq \l_@@_command_str + } +\cs_generate_variant:Nn \@@_h_custom_line:nn { n V } +% \end{macrocode} +% +% \bigskip +% \bigskip +% The following command will create the command that the final user will use in +% its array to draw an horizontal rule on only some of the columns of the array +% (hence the letter |c| as in |\cline|). |#1| is the whole set of keys to pass +% to the command |\@@_hline:n| (which is in the internal |\CodeAfter|). +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_c_custom_line:n #1 + { +% \end{macrocode} +% Here, we need an expandable command since it begins with an |\noalign|. +% \begin{macrocode} + \exp_args:Nc \NewExpandableDocumentCommand + { nicematrix - \l_@@_ccommand_str } + { O { } m } + { + \noalign + { + \@@_compute_rule_width:n { #1 , ##1 } + \skip_vertical:n { \l_@@_rule_width_dim } + \clist_map_inline:nn + { ##2 } + { \@@_c_custom_line_i:nn { #1 , ##1 } { ####1 } } + } + } + \seq_put_left:NV \l_@@_custom_line_commands_seq \l_@@_ccommand_str + } +% \end{macrocode} +% The first argument is the list of key-value pairs characteristic of the line. +% The second argument is the specification of columns for the |\cline| with the +% syntax $a$-$b$. +% \begin{macrocode} +\cs_new_protected:Npn \@@_c_custom_line_i:nn #1 #2 + { + \str_if_in:nnTF { #2 } { - } + { \@@_cut_on_hyphen:w #2 \q_stop } + { \@@_cut_on_hyphen:w #2 - #2 \q_stop } + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { + \@@_hline:n + { + #1 , + start = \l_tmpa_tl , + end = \l_tmpb_tl , + position = \int_eval:n { \c@iRow + 1 } , + total-width = \dim_use:N \l_@@_rule_width_dim + } + } + } +\cs_generate_variant:Nn \@@_c_custom_line:nn { n V } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_compute_rule_width:n #1 + { + \bool_set_false:N \l_@@_tikz_rule_bool + \bool_set_false:N \l_@@_total_width_bool + \bool_set_false:N \l_@@_dotted_rule_bool + \keys_set_known:nn { NiceMatrix / custom-line-width } { #1 } + \bool_if:NF \l_@@_total_width_bool + { + \bool_if:NTF \l_@@_dotted_rule_bool + { \dim_set:Nn \l_@@_rule_width_dim { 2 \l_@@_xdots_radius_dim } } + { + \bool_if:NF \l_@@_tikz_rule_bool + { + \dim_set:Nn \l_@@_rule_width_dim + { + \arrayrulewidth * \l_@@_multiplicity_int + + \doublerulesep * ( \l_@@_multiplicity_int - 1 ) + } + } + } + } + } +% \end{macrocode} +% +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_v_custom_line:n #1 + { + \@@_compute_rule_width:n { #1 } +% \end{macrocode} +% In the following line, the |\dim_use:N| is mandatory since we do an expansion. +% \begin{macrocode} + \tl_gput_right:Nx \g_@@_preamble_tl + { \exp_not:N ! { \skip_horizontal:n { \dim_use:N \l_@@_rule_width_dim } } } + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { + \@@_vline:n + { + #1 , + position = \int_eval:n { \c@jCol + 1 } , + total-width = \dim_use:N \l_@@_rule_width_dim + } + } + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_custom_line:n + { letter = : , command = hdottedline , ccommand = cdottedline, dotted } +% \end{macrocode} +% +% \subsubsection*{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:nnnnn #1 #2 #3 #4 #5 + { + \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:nnnnn #1 #2 #3 #4 #5 + { + \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 } ) + || ( \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} +% +% \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 } ) + || ( \int_compare_p:nNn \l_tmpb_tl = { #4 + 1 } ) + } + } + { \bool_gset_false:N \g_tmpa_bool } + } +% \end{macrocode} +% +% \bigskip +% \section{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| 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 #7 + { + \int_compare:nNnT { #3 } < { \int_eval:n { #1 + 1 } } + { + \int_compare:nNnT { #1 } < { \int_eval:n { #5 + 1 } } + { + \int_compare:nNnT { #4 } < { \int_eval:n { #2 + 1 } } + { + \int_compare:nNnT { #2 } < { \int_eval:n { #6 + 1 } } + { \bool_set_true:N \l_tmpb_bool } + } + } + } + } +% \end{macrocode} +% +% +% \bigskip +% \section{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} +% +% +% +% \section{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 _ \int_eval:n { \@@_i: + 1 } _ max _ dim } + ) + / 2 + } + \dim_set_eq:cc { l_@@_row _ \int_eval:n { \@@_i: + 1 } _ 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 _ \int_eval:n { \@@_j: + 1 } _ min _ dim } + ) + / 2 + } + \dim_set_eq:cc { l_@@_column _ \int_eval:n { \@@_j: + 1 } _ 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} + \cs_if_exist_use:NF + \seq_map_pairwise_function:NNN + \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 +% \section{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_str t , + t .value_forbidden:n = true , + b .code:n = \str_set:Nn \l_@@_vpos_of_block_str b , + b .value_forbidden:n = true , + color .tl_set:N = \l_@@_color_tl , + color .value_required:n = true , + respect-arraystretch .bool_set:N = \l_@@_respect_arraystretch_bool , + respect-arraystretch .default: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 } + { + \int_compare:nNnTF { \char_value_catcode:n { 45 } } = { 13 } + \@@_Block_i_czech \@@_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} +% +% With \pkg{babel} with the key |czech|, the character |-| (hyphen) is active. +% That's why we need a special version. Remark that we could not use a +% preprocessor in the command |\@@_Block:| to do the job because the command +% |\@@_Block:| is defined with the command |\NewExpandableDocumentCommand|. +% \begin{macrocode} +{ + \char_set_catcode_active:N - + \cs_new:Npn \@@_Block_i_czech #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 +% \textsl{key=values} pairs, |#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_@@_pre_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:V \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 + { + \int_compare:nNnTF \c@iRow = 0 + \l_@@_code_for_first_row_tl + { + \int_compare:nNnT \c@iRow = \l_@@_last_row_int + \l_@@_code_for_last_row_tl + } + \g_@@_row_style_tl + } + \group_begin: + \bool_if:NF \l_@@_respect_arraystretch_bool + { \cs_set:Npn \arraystretch { 1 } } + \dim_zero:N \extrarowheight + #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 alignment 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_all:nTF + { + { \int_compare_p:nNn { #2 } = 1 } + { \dim_compare_p:n { \l_@@_col_width_dim >= \c_zero_dim } } + { ! \g_@@_rotate_bool } + } +% \end{macrocode} +% When the block is mono-column in a column with a fixed width (eg |p{3cm}|). +% \begin{macrocode} + { + \use:x + { + \exp_not:N \begin { minipage }% + [ \str_lowercase:V { \l_@@_vpos_of_block_str } ] + { \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 }% + [ \str_lowercase:V { \l_@@_vpos_of_block_str } ] + { @ { } \l_@@_hpos_block_str @ { } } + } + #5 + \end { tabular } + } + } + { + \c_math_toggle_token + \use:x + { + \exp_not:N \begin { array }% + [ \str_lowercase:V { \l_@@_vpos_of_block_str } ] + { @ { } \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 +% alignment 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 } } + { + \bool_if:NTF \l_@@_NiceTabular_bool + { + \group_begin: + \bool_if:NF \l_@@_respect_arraystretch_bool + { \cs_set:Npn \exp_not:N \arraystretch { 1 } } + \exp_not:n + { + \dim_zero:N \extrarowheight + #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 alignment 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_str ] + { @ { } \l_@@_hpos_block_str @ { } } + } + #5 + \end { tabular } + } + \group_end: + } + { + \group_begin: + \bool_if:NF \l_@@_respect_arraystretch_bool + { \cs_set:Npn \exp_not:N \arraystretch { 1 } } + \exp_not:n + { + \dim_zero:N \extrarowheight + #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_str ] + { @ { } \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 = + \IfPackageLoadedTF { tikz } + { \seq_put_right:Nn \l_@@_tikz_seq { { #1 } } } + { \@@_error:n { tikz~key~without~tikz } } , + tikz .value_required:n = true , + fill .code:n = + \tl_set_rescan:Nnn + \l_@@_fill_tl + { \char_set_catcode_other:N ! } + { #1 } , + fill .value_required:n = true , + draw .code:n = + \tl_set_rescan:Nnn + \l_@@_draw_tl + { \char_set_catcode_other:N ! } + { #1 } , + draw .default:n = default , + rounded-corners .dim_set:N = \l_@@_rounded_corners_dim , + rounded-corners .default:n = 4 pt , + color .code:n = + \@@_color:n { #1 } + \tl_set_rescan:Nnn + \l_@@_draw_tl + { \char_set_catcode_other:N ! } + { #1 } , + color .value_required:n = true , + borders .clist_set:N = \l_@@_borders_clist , + borders .value_required:n = true , + hvlines .meta:n = { vlines , hlines } , + vlines .bool_set:N = \l_@@_vlines_block_bool, + vlines .default:n = true , + hlines .bool_set:N = \l_@@_hlines_block_bool, + hlines .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_str t , + t .value_forbidden:n = true , + T .code:n = \str_set:Nn \l_@@_vpos_of_block_str T , + T .value_forbidden:n = true , + b .code:n = \str_set:Nn \l_@@_vpos_of_block_str b , + b .value_forbidden:n = true , + B .code:n = \str_set:Nn \l_@@_vpos_of_block_str B , + B .value_forbidden:n = true , + v-center .code:n = \str_set:Nn \l_@@_vpos_of_block_str { c } , + v-center .value_forbidden:n = true , + name .tl_set:N = \l_@@_block_name_str , + name .value_required:n = true , + name .initial:n = , + respect-arraystretch .bool_set:N = \l_@@_respect_arraystretch_bool , + respect-arraystretch .default:n = true , + transparent .bool_set:N = \l_@@_transparent_bool , + transparent .default:n = true , + transparent .initial:n = false , + 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 } + \@@_msg_redirect_name:nn { columns~not~used } { none } + } + { \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} +% +% +% \medskip +% |#1| is the first row of the block; +% |#2| is the first column of the block; +% |#3| is the last row of the block; +% |#4| is the last column of the block; +% |#5| is a list of \textsl{key=value} options; +% |#6| is the label +% \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: + \int_compare:nNnT { #1 } = { #3 } + { \str_set:Nn \l_@@_vpos_of_block_str { t } } + \keys_set:nn { NiceMatrix / Block / SecondPass } { #5 } +% \end{macrocode} +% +% \begin{macrocode} + \bool_if:NT \l_@@_vlines_block_bool + { + \tl_gput_right:Nx \g_nicematrix_code_after_tl + { + \@@_vlines_block:nnn + { \exp_not:n { #5 } } + { #1 - #2 } + { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } + } + } + \bool_if:NT \l_@@_hlines_block_bool + { + \tl_gput_right:Nx \g_nicematrix_code_after_tl + { + \@@_hlines_block:nnn + { \exp_not:n { #5 } } + { #1 - #2 } + { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } + } + } + \bool_if:nF + { + \l_@@_transparent_bool + || ( \l_@@_vlines_block_bool && \l_@@_hlines_block_bool ) + } + { +% \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:Nx \g_@@_pos_of_blocks_seq + { { #1 } { #2 } { #3 } { #4 } { \l_@@_block_name_str } } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} + \bool_lazy_and:nnT + { ! (\tl_if_empty_p:N \l_@@_draw_tl) } + { \l_@@_hlines_block_bool || \l_@@_vlines_block_bool } + { \@@_error:n { hlines~with~color } } +% \end{macrocode} +% \bigskip +% \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 + { + \tl_gput_right:Nx \g_@@_pre_code_before_tl + { + \exp_not:N \roundedrectanglecolor + \exp_args:NV \tl_if_head_eq_meaning:nNTF \l_@@_fill_tl [ + { \l_@@_fill_tl } + { { \l_@@_fill_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_@@_pre_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 - \int_eval:n { \l_@@_last_row_int + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y + \@@_qpoint:n { col - \int_eval:n { \l_@@_last_col_int + 1 } } + \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} + \@@_pgf_rect_node:nnnnn + { \@@_env: - #1 - #2 - block } + \l_tmpb_dim \l_tmpa_dim \l_@@_tmpd_dim \l_@@_tmpc_dim + \str_if_empty:NF \l_@@_block_name_str + { + \pgfnodealias + { \@@_env: - \l_@@_block_name_str } + { \@@_env: - #1 - #2 - block } + \str_if_empty:NF \l_@@_name_str + { + \pgfnodealias + { \l_@@_name_str - \l_@@_block_name_str } + { \@@_env: - #1 - #2 - block } + } + } +% \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 - \int_eval:n { \l_@@_last_col_int + 1 } } + \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. +% \begin{macrocode} + \bool_lazy_any:nTF + { + { \str_if_eq_p:Vn \l_@@_vpos_of_block_str { c } } + { \str_if_eq_p:Vn \l_@@_vpos_of_block_str { T } } + { \str_if_eq_p:Vn \l_@@_vpos_of_block_str { B } } + } +% \end{macrocode} +% \medskip +% \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 } + } +% \end{macrocode} +% \begin{macrocode} + \tl_set:Nx \l_tmpa_tl + { + \str_case:Vn \l_@@_vpos_of_block_str + { + c { + \str_case:Vn \l_@@_hpos_block_str + { + c { center } + l { west } + r { east } + } + + } + T { + \str_case:Vn \l_@@_hpos_block_str + { + c { north } + l { north~west } + r { north~east } + } + + } + B { + \str_case:Vn \l_@@_hpos_block_str + { + c { south} + l { south~west } + r { south~east } + } + + } + } + } +% \end{macrocode} +% \begin{macrocode} + \pgftransformshift + { + \pgfpointanchor + { + \@@_env: - #1 - #2 - block + \bool_if:NF \l_@@_hpos_of_block_cap_bool { - short } + } + { \l_tmpa_tl } + } + \pgfset + { + inner~xsep = \c_zero_dim , + inner~ysep = \l_@@_block_ysep_dim + } + \pgfnode + { rectangle } + { \l_tmpa_tl } + { \box_use_drop:N \l_@@_cell_box } { } { } + } +% \end{macrocode} +% +% \begin{macrocode} + { +% \end{macrocode} +% +% \begin{macrocode} + \pgfextracty \l_tmpa_dim + { + \@@_qpoint:n + { + row - \str_if_eq:VnTF \l_@@_vpos_of_block_str { b } { #3 } { #1 } + - base + } + } + \dim_sub:Nn \l_tmpa_dim { 0.5 \arrayrulewidth } % added 2023-02-21 +% \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} +% +% \begin{macrocode} + \endpgfpicture + \group_end: + } +% \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@ } + { \@@_color:V \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 - \int_eval:n { \l_tmpa_tl + 1 } } + \dim_set:Nn \l_tmpa_dim { \pgf@y } + \@@_qpoint:n { col - \int_eval:n { \l_tmpb_tl + 1 } } + \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 } + \dim_compare:nNnTF \l_@@_rounded_corners_dim = \c_zero_dim + { \pgfusepathqstroke } + { \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 |\@@_vlines_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 \@@_vlines_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:n + { + position = ##1 , + start = \l_@@_tmpc_tl , + end = \int_eval:n { \l_tmpa_tl - 1 } , + total-width = \dim_use:N \l_@@_line_width_dim % added 2022-08-06 + } + } + } + } +\cs_new_protected:Npn \@@_hlines_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_@@_tmpc_tl \l_tmpa_tl + { + \use:x + { + \@@_hline:n + { + position = ##1 , + start = \l_@@_tmpd_tl , + end = \int_eval:n { \l_tmpb_tl - 1 } , + total-width = \dim_use:N \l_@@_line_width_dim % added 2022-08-06 + } + } + } + } +% \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 } } + { + \tl_clear_new:N \l_@@_borders_tikz_tl + \keys_set:nV + { NiceMatrix / OnlyForTikzInBorders } + \l_@@_borders_clist + \@@_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 } } + \@@_stroke_borders_block_i: + } + } +% \end{macrocode} +% +% \begin{macrocode} +\hook_gput_code:nnn { begindocument } { . } + { + \cs_new_protected:Npx \@@_stroke_borders_block_i: + { + \c_@@_pgfortikzpicture_tl + \@@_stroke_borders_block_ii: + \c_@@_endpgfortikzpicture_tl + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_stroke_borders_block_ii: + { + \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 } + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn { NiceMatrix / OnlyForTikzInBorders } + { + tikz .code:n = + \cs_if_exist:NTF \tikzpicture + { \tl_set:Nn \l_@@_borders_tikz_tl { #1 } } + { \@@_error:n { tikz~in~borders~without~tikz } } , + tikz .value_required:n = true , + top .code:n = , + bottom .code:n = , + left .code:n = , + right .code:n = , + unknown .code:n = \@@_error:n { bad~border } + } +% \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 } + \tl_if_empty:NTF \l_@@_borders_tikz_tl + { + \pgfpathmoveto { \pgfpoint \pgf@x \l_tmpb_dim } + \pgfpathlineto { \pgfpoint \pgf@x \l_@@_tmpc_dim } + \pgfusepathqstroke + } + { + \use:x { \exp_not:N \draw [ \l_@@_borders_tikz_tl ] } + ( \pgf@x , \l_tmpb_dim ) -- ( \pgf@x , \l_@@_tmpc_dim ) ; + } + } +% \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 } + \tl_if_empty:NTF \l_@@_borders_tikz_tl + { + \pgfpathmoveto { \pgfpoint \l_tmpa_dim \pgf@y } + \pgfpathlineto { \pgfpoint \l_tmpb_dim \pgf@y } + \pgfusepathqstroke + } + { + \use:x { \exp_not:N \draw [ \l_@@_borders_tikz_tl ] } + ( \l_tmpa_dim , \pgf@y ) -- ( \l_tmpb_dim , \pgf@y ) ; + } + } +% \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 + ( \int_eval:n { #3 + 1 } -| \int_eval:n { #4 + 1 } ) ; + } + \end { tikzpicture } + } +% \end{macrocode} +% +% +% \section{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 +% \section{Automatic arrays} +% +% +% +% We will extract the potential keys |columns-type|, |l|, |c|, |r| and pass +% the other keys to the environment |{NiceArrayWithDelims}|. +% \begin{macrocode} +\keys_define:nn { NiceMatrix / Auto } + { + columns-type .code:n = \@@_set_preamble:Nn \l_@@_columns_type_tl { #1 } , + columns-type .value_required:n = true , + l .meta:n = { columns-type = l } , + r .meta:n = { columns-type = r } , + c .meta:n = { columns-type = c } , + delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , + delimiters / color .value_required:n = true , + delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , + delimiters / max-width .default:n = true , + delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , + delimiters .value_required:n = true , + } +% \end{macrocode} +% +% \begin{macrocode} +\NewDocumentCommand \AutoNiceMatrixWithDelims + { m m O { } > { \SplitArgument { 1 } { - } } m O { } m ! O { } } + { \@@_auto_nice_matrix:nnnnnn { #1 } { #2 } #4 { #6 } { #3 , #5 , #7 } } +% \end{macrocode} +% +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_auto_nice_matrix:nnnnnn #1 #2 #3 #4 #5 #6 + { +% \end{macrocode} +% The group is for the protection of the keys. +% \begin{macrocode} + \group_begin: + \bool_set_true:N \l_@@_Matrix_bool + \keys_set_known:nnN { NiceMatrix / Auto } { #6 } \l_tmpa_tl +% \end{macrocode} +% We nullify the command |\@@_transform_preamble:| because we will provide a +% preamble which is yet transformed (by using |\l_@@_columns_type_tl| which is +% yet nicematrix-ready). +% +% \begin{macrocode} + \cs_set_eq:NN \@@_transform_preamble: \prg_do_nothing: + \use:x + { + \exp_not:N \begin { NiceArrayWithDelims } { #1 } { #2 } + { * { #4 } { \exp_not:V \l_@@_columns_type_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 { #4 - 1 } { & } + \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\ + } + \prg_replicate:nn { #3 } + { + \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 { #4 - 1 } { { } #5 & } #5 + \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 { #4 - 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 } + { + \bool_gset_false:N \g_@@_NiceArray_bool + \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_gset_true:N \g_@@_NiceArray_bool + \AutoNiceMatrixWithDelims . . { #2 } { #4 } [ #1 , #3 , #5 ] + \group_end: + } +% \end{macrocode} +% +% +% \bigskip +% \section{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 + \tl_gput_right:Nn \g_@@_cell_after_hook_tl \@@_dotfill_i: + } +% \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_i: + { \dim_compare:nNnT { \box_wd:N \l_@@_cell_box } = \c_zero_dim \@@_old_dotfill } +% \end{macrocode} +% +% \bigskip +% \section{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_@@_pre_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} +% The last argument is for the name of the block. +% \begin{macrocode} + { } + } + } +% \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 other two 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 - \int_eval:n { #3 + 1 } } + \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y + \@@_qpoint:n { col - \int_eval:n { #4 + 1 } } + \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 } + { + \begin { minipage } { 20 cm } + \@@_math_toggle_token: #5 \@@_math_toggle_token: + \end { minipage } + } + { } + { } + \endpgfscope + \pgftransformshift { \pgfpoint \l_@@_tmpd_dim \l_tmpa_dim } + \pgfnode { rectangle } { north~east } + { + \begin { minipage } { 20 cm } + \raggedleft + \@@_math_toggle_token: #6 \@@_math_toggle_token: + \end { minipage } + } + { } + { } + \endpgfpicture + } +% \end{macrocode} +% +% +% +% +% \bigskip +% \section{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 \textsl{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_ii:n } +% \end{macrocode} +% +% \medskip +% However, in each cell of the environment, the command |\CodeAfter| will be +% linked to the following command |\@@_CodeAfter_ii:n| which begins +% with |\\|. +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_CodeAfter_i: { \\ \omit \@@_CodeAfter_ii:n } +% \end{macrocode} +% +% \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_ii:n #1 \end + { + \tl_gput_right:Nn \g_nicematrix_code_after_tl { #1 } + \@@_CodeAfter_iv:n + } +% \end{macrocode} +% +% We catch the argument of the command |\end| (in |#1|). +% \begin{macrocode} +\cs_new_protected:Npn \@@_CodeAfter_iv: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_ii:n + } + } +% \end{macrocode} +% +% +% +% \section{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_@@_pre_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 - \int_eval:n { \c@iRow + 1 } } + \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 + \@@_color:V \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} +% +% \section{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 } + { + delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , + delimiters / color .value_required: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 , + name .code:n = + \tl_if_empty:nTF { #1 } + { \@@_error:n { Invalid~name } } + { + \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 } } + } , + name .value_required:n = true , + 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 , + 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 + { + \tl_gput_right:Nx \g_@@_pre_code_after_tl + { + \SubMatrix { #1 } { #2 } { #3 } { #4 } + [ + delimiters / color = \l_@@_delimiters_color_tl , + hlines = \l_@@_submatrix_hlines_clist , + vlines = \l_@@_submatrix_vlines_clist , + extra-height = \dim_use:N \l_@@_submatrix_extra_height_dim , + left-xshift = \dim_use:N \l_@@_submatrix_left_xshift_dim , + right-xshift = \dim_use:N \l_@@_submatrix_right_xshift_dim , + slim = \bool_to_str:N \l_@@_submatrix_slim_bool , + #5 + ] + } + \@@_SubMatrix_in_code_before_i { #2 } { #3 } + } + } +% \end{macrocode} +% +% \begin{macrocode} +\NewDocumentCommand \@@_SubMatrix_in_code_before_i + { > { \SplitArgument { 1 } { - } } m > { \SplitArgument { 1 } { - } } m } + { \@@_SubMatrix_in_code_before_i:nnnn #1 #2 } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_SubMatrix_in_code_before_i:nnnn #1 #2 #3 #4 + { + \seq_gput_right:Nx \g_@@_submatrix_seq + { +% \end{macrocode} +% We use |\str_if_eq:nnTF| because it is fully expandable. +% \begin{macrocode} + { \str_if_eq:nnTF { #1 } { last } { \int_use:N \c@iRow } { #1 } } + { \str_if_eq:nnTF { #2 } { last } { \int_use:N \c@jCol } { #2 } } + { \str_if_eq:nnTF { #3 } { last } { \int_use:N \c@iRow } { #3 } } + { \str_if_eq:nnTF { #4 } { last } { \int_use:N \c@jCol } { #4 } } + } + } +% \end{macrocode} +% +% +% \bigskip +% In the pre-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} +\hook_gput_code:nnn { begindocument } { . } + { + \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} +% +% \medskip +% The following macro will compute |\l_@@_first_i_tl|, |\l_@@_first_j_tl|, +% |\l_@@_last_i_tl| and |\l_@@_last_j_tl| from the arguments of the command as +% provided by the user (for example |2-3| and |5-last|). +% \begin{macrocode} +\NewDocumentCommand \@@_compute_i_j:nn + { > { \SplitArgument { 1 } { - } } m > { \SplitArgument { 1 } { - } } m } + { \@@_compute_i_j:nnnn #1 #2 } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_compute_i_j:nnnn #1 #2 #3 #4 + { + \tl_set:Nn \l_@@_first_i_tl { #1 } + \tl_set:Nn \l_@@_first_j_tl { #2 } + \tl_set:Nn \l_@@_last_i_tl { #3 } + \tl_set:Nn \l_@@_last_j_tl { #4 } + \tl_if_eq:NnT \l_@@_first_i_tl { last } + { \tl_set:NV \l_@@_first_i_tl \c@iRow } + \tl_if_eq:NnT \l_@@_first_j_tl { last } + { \tl_set:NV \l_@@_first_j_tl \c@jCol } + \tl_if_eq:NnT \l_@@_last_i_tl { last } + { \tl_set:NV \l_@@_last_i_tl \c@iRow } + \tl_if_eq:NnT \l_@@_last_j_tl { last } + { \tl_set:NV \l_@@_last_j_tl \c@jCol } + } +% \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} + \@@_compute_i_j:nn { #2 } { #3 } + \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:nn { Construct~too~large } { \SubMatrix } } + { + \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 + { + \fp_to_dim:n + { + \pgf@y + + ( \box_ht:N \strutbox + \extrarowheight ) * \arraystretch + } + } % modified 6.13c + \@@_qpoint:n { row - \l_@@_last_i_tl - base } + \dim_set:Nn \l_@@_y_final_dim + { \fp_to_dim:n { \pgf@y - ( \box_dp:N \strutbox ) * \arraystretch } } + % modified 6.13c + \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_zero:N \nulldelimiterspace +% \end{macrocode} +% +% \bigskip +% We will draw the rules in the |\SubMatrix|. +% \begin{macrocode} + \group_begin: + \pgfsetlinewidth { 1.1 \arrayrulewidth } + \@@_set_CT@arc@:V \l_@@_rules_color_tl + \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 or 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 + \@@_color:V \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 + \@@_color:V \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 +% \section{Les commandes \textbackslash UnderBrace et \textbackslash +% OverBrace} +% +% The following commands will be linked to |\UnderBrace| and |\OverBrace| in the +% |\CodeAfter|. +% +% \begin{macrocode} +\NewDocumentCommand \@@_UnderBrace { O { } m m m O { } } + { + \peek_remove_spaces:n + { \@@_brace:nnnnn { #2 } { #3 } { #4 } { #1 , #5 } { under } } + } +% \end{macrocode} +% +% \begin{macrocode} +\NewDocumentCommand \@@_OverBrace { O { } m m m O { } } + { + \peek_remove_spaces:n + { \@@_brace:nnnnn { #2 } { #3 } { #4 } { #1 , #5 } { over } } + } +% \end{macrocode} +% +% \medskip +% \begin{macrocode} +\keys_define:nn { NiceMatrix / Brace } + { + left-shorten .bool_set:N = \l_@@_brace_left_shorten_bool , + left-shorten .default:n = true , + right-shorten .bool_set:N = \l_@@_brace_right_shorten_bool , + shorten .meta:n = { left-shorten , right-shorten } , + right-shorten .default:n = true , + yshift .dim_set:N = \l_@@_brace_yshift_dim , + yshift .value_required:n = true , + yshift .initial:n = \c_zero_dim , + color .tl_set:N = \l_tmpa_tl , + color .value_required:n = true , + unknown .code:n = \@@_error:n { Unknown~key~for~Brace } + } +% \end{macrocode} +% +% \medskip +% |#1| is the first cell of the rectangle (with the syntax $i$\verb+-|+$j$; +% |#2| is the last cell of the rectangle; +% |#3| is the label of the text; +% |#4| is the optional argument (a list of \textsl{key}-\textsl{value} pairs); +% |#5| is equal to |under| or |over|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_brace:nnnnn #1 #2 #3 #4 #5 + { + \group_begin: +% \end{macrocode} +% The four following token lists correspond to the position of the sub-matrix to +% which a brace will be attached. +% \begin{macrocode} + \@@_compute_i_j:nn { #1 } { #2 } + \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 } + { + \str_if_eq:nnTF { #5 } { under } + { \@@_error:nn { Construct~too~large } { \UnderBrace } } + { \@@_error:nn { Construct~too~large } { \OverBrace } } + } + { + \tl_clear:N \l_tmpa_tl + \keys_set:nn { NiceMatrix / Brace } { #4 } + \tl_if_empty:NF \l_tmpa_tl { \color { \l_tmpa_tl } } + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \bool_if:NT \l_@@_brace_left_shorten_bool + { + \dim_set_eq:NN \l_@@_x_initial_dim \c_max_dim + \int_step_inline:nnn \l_@@_first_i_tl \l_@@_last_i_tl + { + \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 } + } + } + } + \bool_lazy_or:nnT + { \bool_not_p:n \l_@@_brace_left_shorten_bool } + { \dim_compare_p:nNn \l_@@_x_initial_dim = \c_max_dim } + { + \@@_qpoint:n { col - \l_@@_first_j_tl } + \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x + } + \bool_if:NT \l_@@_brace_right_shorten_bool + { + \dim_set:Nn \l_@@_x_final_dim { - \c_max_dim } + \int_step_inline:nnn \l_@@_first_i_tl \l_@@_last_i_tl + { + \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 } + } + } + } + \bool_lazy_or:nnT + { \bool_not_p:n \l_@@_brace_right_shorten_bool } + { \dim_compare_p:nNn \l_@@_x_final_dim = { - \c_max_dim } } + { + \@@_qpoint:n { col - \int_eval:n { \l_@@_last_j_tl + 1 } } + \dim_set_eq:NN \l_@@_x_final_dim \pgf@x + } + \pgfset { inner~sep = \c_zero_dim } + \str_if_eq:nnTF { #5 } { under } + { \@@_underbrace_i:n { #3 } } + { \@@_overbrace_i:n { #3 } } + \endpgfpicture + } + \group_end: + } +% \end{macrocode} +% +% \medskip +% The argument is the text to put above the brace. +% \begin{macrocode} +\cs_new_protected:Npn \@@_overbrace_i:n #1 + { + \@@_qpoint:n { row - \l_@@_first_i_tl } + \pgftransformshift + { + \pgfpoint + { ( \l_@@_x_initial_dim + \l_@@_x_final_dim) / 2 } + { \pgf@y + \l_@@_brace_yshift_dim - 3 pt} + } + \pgfnode + { rectangle } + { south } + { + \vbox_top:n + { + \group_begin: + \everycr { } + \halign + { + \hfil ## \hfil \crcr + \@@_math_toggle_token: #1 \@@_math_toggle_token: \cr + \noalign { \skip_vertical:n { 3 pt } \nointerlineskip } + \c_math_toggle_token + \overbrace + { + \hbox_to_wd:nn + { \l_@@_x_final_dim - \l_@@_x_initial_dim } + { } + } + \c_math_toggle_token + \cr + } + \group_end: + } + } + { } + { } + } +% \end{macrocode} +% +% +% \medskip +% The argument is the text to put under the brace. +% \begin{macrocode} +\cs_new_protected:Npn \@@_underbrace_i:n #1 + { + \@@_qpoint:n { row - \int_eval:n { \l_@@_last_i_tl + 1 } } + \pgftransformshift + { + \pgfpoint + { ( \l_@@_x_initial_dim + \l_@@_x_final_dim) / 2 } + { \pgf@y - \l_@@_brace_yshift_dim + 3 pt } + } + \pgfnode + { rectangle } + { north } + { + \group_begin: + \everycr { } + \vbox:n + { + \halign + { + \hfil ## \hfil \crcr + \c_math_toggle_token + \underbrace + { + \hbox_to_wd:nn + { \l_@@_x_final_dim - \l_@@_x_initial_dim } + { } + } + \c_math_toggle_token + \cr + \noalign { \skip_vertical:n { 3 pt } \nointerlineskip } + \@@_math_toggle_token: #1 \@@_math_toggle_token: \cr + } + } + \group_end: + } + { } + { } + } +% \end{macrocode} +% +% \bigskip +% \section{The command \textbackslash ShowCellNames} +% +% \begin{macrocode} +\NewDocumentCommand \@@_ShowCellNames_CodeBefore { } + { + \dim_zero_new:N \g_@@_tmpc_dim + \dim_zero_new:N \g_@@_tmpd_dim + \dim_zero_new:N \g_@@_tmpe_dim + \int_step_inline:nn \c@iRow + { + \begin { pgfpicture } + \@@_qpoint:n { row - ##1 } + \dim_set_eq:NN \l_tmpa_dim \pgf@y + \@@_qpoint:n { row - \int_eval:n { ##1 + 1 } } + \dim_gset:Nn \g_tmpa_dim { ( \l_tmpa_dim + \pgf@y ) / 2 } + \dim_gset:Nn \g_tmpb_dim { \l_tmpa_dim - \pgf@y } + \bool_if:NTF \l_@@_in_code_after_bool + \end { pgfpicture } + \int_step_inline:nn \c@jCol + { + \hbox_set:Nn \l_tmpa_box + { \normalfont \Large \color { red ! 50 } ##1 - ####1 } + \begin { pgfpicture } + \@@_qpoint:n { col - ####1 } + \dim_gset_eq:NN \g_@@_tmpc_dim \pgf@x + \@@_qpoint:n { col - \int_eval:n { ####1 + 1 } } + \dim_gset:Nn \g_@@_tmpd_dim { \pgf@x - \g_@@_tmpc_dim } + \dim_gset_eq:NN \g_@@_tmpe_dim \pgf@x + \endpgfpicture + \end { pgfpicture } + \fp_set:Nn \l_tmpa_fp + { + \fp_min:nn + { + \fp_min:nn + { \dim_ratio:nn { \g_@@_tmpd_dim } { \box_wd:N \l_tmpa_box } } + { \dim_ratio:nn { \g_tmpb_dim } { \box_ht_plus_dp:N \l_tmpa_box } } + } + { 1.0 } + } + \box_scale:Nnn \l_tmpa_box { \fp_use:N \l_tmpa_fp } { \fp_use:N \l_tmpa_fp } + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \pgftransformshift + { + \pgfpoint + { 0.5 * ( \g_@@_tmpc_dim + \g_@@_tmpe_dim ) } + { \dim_use:N \g_tmpa_dim } + } + \pgfnode + { rectangle } + { center } + { \box_use:N \l_tmpa_box } + { } + { } + \endpgfpicture + } + } + } +% \end{macrocode} +% +% \begin{macrocode} +\NewDocumentCommand \@@_ShowCellNames { } + { + \bool_if:NT \l_@@_in_code_after_bool + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \pgfpathrectanglecorners + { \@@_qpoint:n { 1 } } + { + \@@_qpoint:n + { \int_eval:n { \int_max:nn \c@iRow \c@jCol + 1 } } + } + \pgfsetfillopacity { 0.75 } + \pgfsetfillcolor { white } + \pgfusepathqfill + \endpgfpicture + } + \dim_zero_new:N \g_@@_tmpc_dim + \dim_zero_new:N \g_@@_tmpd_dim + \dim_zero_new:N \g_@@_tmpe_dim + \int_step_inline:nn \c@iRow + { + \bool_if:NTF \l_@@_in_code_after_bool + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + } + { \begin { pgfpicture } } + \@@_qpoint:n { row - ##1 } + \dim_set_eq:NN \l_tmpa_dim \pgf@y + \@@_qpoint:n { row - \int_eval:n { ##1 + 1 } } + \dim_gset:Nn \g_tmpa_dim { ( \l_tmpa_dim + \pgf@y ) / 2 } + \dim_gset:Nn \g_tmpb_dim { \l_tmpa_dim - \pgf@y } + \bool_if:NTF \l_@@_in_code_after_bool + { \endpgfpicture } + { \end { pgfpicture } } + \int_step_inline:nn \c@jCol + { + \hbox_set:Nn \l_tmpa_box + { + \normalfont \Large \sffamily \bfseries + \bool_if:NTF \l_@@_in_code_after_bool + { \color { red } } + { \color { red ! 50 } } + ##1 - ####1 + } + \bool_if:NTF \l_@@_in_code_after_bool + { + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + } + { \begin { pgfpicture } } + \@@_qpoint:n { col - ####1 } + \dim_gset_eq:NN \g_@@_tmpc_dim \pgf@x + \@@_qpoint:n { col - \int_eval:n { ####1 + 1 } } + \dim_gset:Nn \g_@@_tmpd_dim { \pgf@x - \g_@@_tmpc_dim } + \dim_gset_eq:NN \g_@@_tmpe_dim \pgf@x + \bool_if:NTF \l_@@_in_code_after_bool + { \endpgfpicture } + { \end { pgfpicture } } + \fp_set:Nn \l_tmpa_fp + { + \fp_min:nn + { + \fp_min:nn + { \dim_ratio:nn { \g_@@_tmpd_dim } { \box_wd:N \l_tmpa_box } } + { \dim_ratio:nn { \g_tmpb_dim } { \box_ht_plus_dp:N \l_tmpa_box } } + } + { 1.0 } + } + \box_scale:Nnn \l_tmpa_box { \fp_use:N \l_tmpa_fp } { \fp_use:N \l_tmpa_fp } + \pgfpicture + \pgfrememberpicturepositiononpagetrue + \pgf@relevantforpicturesizefalse + \pgftransformshift + { + \pgfpoint + { 0.5 * ( \g_@@_tmpc_dim + \g_@@_tmpe_dim ) } + { \dim_use:N \g_tmpa_dim } + } + \pgfnode + { rectangle } + { center } + { \box_use:N \l_tmpa_box } + { } + { } + \endpgfpicture + } + } + } +% \end{macrocode} +% +% \bigskip +% \section{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:nnnn { nicematrix } { Unknown~key~for~package } + { + The~key~'\l_keys_key_str'~is~unknown. \\ + That~key~will~be~ignored. \\ + For~a~list~of~the~available~keys,~type~H~. + } + { + The~available~keys~are~(in~alphabetic~order):~ + footnote,~ + footnotehyper,~ + messages-for-Overleaf,~ + no-test-for-array,~ + renew-dots,~and + renew-matrix. + } +% \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 , + messages-for-Overleaf .bool_set:N = \c_@@_messages_for_Overleaf_bool , + footnote .bool_set:N = \c_@@_footnote_bool , + footnotehyper .bool_set:N = \c_@@_footnotehyper_bool , + no-test-for-array .bool_set:N = \c_@@_no_test_for_array_bool , + no-test-for-array .default:n = true , + 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.\\ + 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.\\ + 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} + \IfClassLoadeTF { beamer } + { \bool_set_false:N \c_@@_footnote_bool } + { + \IfPackageLoadedTF { 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} + \IfClassLoadedTF { beamer } + { \bool_set_false:N \c_@@_footnote_bool } + { + \IfPackageLoadedTF { 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 +% \section{About the package underscore} +% +% If the user loads the package \pkg{underscore}, it must be loaded +% \emph{before} the package \pkg{nicematrix}. If it is loaded after, we raise an +% error. +% +% \begin{macrocode} +\bool_new:N \l_@@_underscore_loaded_bool +\IfPackageLoadedTF { underscore } + { \bool_set_true:N \l_@@_underscore_loaded_bool } + { } +% \end{macrocode} +% +% \begin{macrocode} +\hook_gput_code:nnn { begindocument } { . } + { + \bool_if:NF \l_@@_underscore_loaded_bool + { + \IfPackageLoadedTF { underscore } + { \@@_error:n { underscore~after~nicematrix } } + { } + } + } +% \end{macrocode} +% +% \bigskip +% \section{Error messages of the package} +% +% \begin{macrocode} +\bool_if:NTF \c_@@_messages_for_Overleaf_bool + { \str_const:Nn \c_@@_available_keys_str { } } + { + \str_const:Nn \c_@@_available_keys_str + { For~a~list~of~the~available~keys,~type~H~. } + } +% \end{macrocode} +% +% \begin{macrocode} +\seq_new:N \g_@@_types_of_matrix_seq +\seq_gset_from_clist:Nn \g_@@_types_of_matrix_seq + { + NiceMatrix , + pNiceMatrix , bNiceMatrix , vNiceMatrix, BNiceMatrix, VNiceMatrix + } +\seq_gset_map_x:NNn \g_@@_types_of_matrix_seq \g_@@_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 +% triggered. This command raises an error but also tries 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 \g_@@_types_of_matrix_seq \g_@@_name_env_str + { + \int_compare:nNnTF \l_@@_last_col_int = { -2 } + { \@@_fatal:n { too~much~cols~for~matrix } } + { + \int_compare:nNnTF \l_@@_last_col_int = { -1 } + { \@@_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 } } + } + } + } + { + \IfPackageLoadedTF { tabularx } + { + \str_if_eq:VnTF \g_@@_name_env_str { NiceTabularX } + { + \int_compare:nNnTF \c@iRow = \c_zero_int + { \@@_fatal:n { X~columns~with~tabularx } } + { + \@@_fatal:nn { too~much~cols~for~array } + { + However,~this~message~may~be~erroneous:~ + maybe~you~have~used~X~columns~while~'tabularx'~is~loaded,~ + ~which~is~forbidden~(however,~it's~still~possible~to~use~ + X~columns~in~{NiceTabularX}). + } + } + } + { \@@_fatal:nn { too~much~cols~for~array } { } } + } + { \@@_fatal:nn { 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 { negative~weight } + { + Negative~weight.\\ + The~weight~of~the~'X'~columns~must~be~positive~and~you~have~used~ + the~value~'\int_use:N \l_@@_weight_int'.\\ + The~absolute~value~will~be~used. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { last~col~not~used } + { + Column~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 { too~much~cols~for~matrix~with~last~col } + { + Too~much~columns.\\ + In~the~row~\int_eval:n { \c@iRow },~ + 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 } + { + Too~much~columns.\\ + In~the~row~\int_eval:n { \c@iRow },~ + 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~(excepted~the~potential~exterior~ + columns)~is~fixed~by~the~LaTeX~counter~'MaxMatrixCols'.~ + Its~current~value~is~\int_use:N \c@MaxMatrixCols\ (use~ + \token_to_str:N \setcounter\ to~change~that~value).~ + This~error~is~fatal. + } +% \end{macrocode} +% +% \medskip +% \begin{macrocode} +\@@_msg_new:nn { too~much~cols~for~array } + { + Too~much~columns.\\ + In~the~row~\int_eval:n { \c@iRow },~ + ~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).~#1 + This~error~is~fatal. + } +% \end{macrocode} +% +% \medskip +% \begin{macrocode} +\@@_msg_new:nn { X~columns~with~tabularx } + { + There~is~a~problem.\\ + You~have~probably~used~X~columns~in~your~environment~{\g_@@_name_env_str}.~ + That's~not~allowed~because~'tabularx'~is~loaded~(however,~you~can~use~X~columns~ + in~an~environment~{NiceTabularX}).\\ + This~error~is~fatal. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { columns~not~used } + { + 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.\\ + The~columns~you~did~not~used~won't~be~created.\\ + We~won't~have~similar~error~till~the~end~of~the~document. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { in~first~col } + { + Erroneous~use.\\ + You~can't~use~the~command~#1 in~the~first~column~(number~0)~of~the~array.\\ + That~command~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { in~last~col } + { + Erroneous~use.\\ + You~can't~use~the~command~#1 in~the~last~column~(exterior)~of~the~array.\\ + That~command~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { in~first~row } + { + Erroneous~use.\\ + You~can't~use~the~command~#1 in~the~first~row~(number~0)~of~the~array.\\ + That~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.\\ + That~command~will~be~ignored. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { caption~outside~float } + { + Key~caption~forbidden.\\ + You~can't~use~the~key~'caption'~because~you~are~not~in~a~floating~ + environment.~This~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { short-caption~without~caption } + { + You~should~not~use~the~key~'short-caption'~without~'caption'.~ + However,~your~'short-caption'~will~be~used~as~'caption'. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { double~closing~delimiter } + { + Double~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 } + { + Double~delimiter.\\ + You~can't~put~a~second~delimiter~"#1"~just~after~a~first~opening~ + delimiter.~That~delimiter~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { bad~option~for~line-style } + { + Bad~line~style.\\ + Since~you~haven't~loaded~Tikz,~the~only~value~you~can~give~to~'line-style'~ + is~'standard'.~That~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Identical~notes~in~caption } + { + Identical~tabular~notes.\\ + You~can't~put~several~notes~with~the~same~content~in~ + \token_to_str:N \caption\ (but~you~can~in~the~main~tabular).\\ + If~you~go~on,~the~output~will~probably~be~erroneous. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { tabularnote~below~the~tabular } + { + \token_to_str:N \tabularnote\ forbidden\\ + You~can't~use~\token_to_str:N \tabularnote\ in~the~caption~ + of~your~tabular~because~the~caption~will~be~composed~below~ + the~tabular.~If~you~want~the~caption~above~the~tabular~use~the~ + key~'caption-above'~in~\token_to_str:N \NiceMatrixOptions.\\ + Your~\token_to_str:N \tabularnote\ will~be~discarded~and~ + no~similar~error~will~raised~in~this~document. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Unknown~key~for~rules } + { + Unknown~key.\\ + There~is~only~two~keys~available~here:~width~and~color.\\ + You~key~'\l_keys_key_str'~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~custom-line } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~in~a~'custom-line'.~ + It~you~go~on,~you~will~probably~have~other~errors. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + ccommand,~ + color,~ + command,~ + dotted,~ + letter,~ + multiplicity,~ + sep-color,~ + tikz,~and~total-width. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~xdots } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~a~command~for~drawing~dotted~rules.\\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + 'color',~ + 'inter',~ + 'line-style',~ + 'radius',~ + 'shorten',~ + 'shorten-end'~and~'shorten-start'. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { Unknown~key~for~rowcolors } + { + Unknown~key.\\ + As~for~now,~there~is~only~two~keys~available~here:~'cols'~and~'respect-blocks'~ + (and~you~try~to~use~'\l_keys_key_str')\\ + That~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { label~without~caption } + { + You~can't~use~the~key~'label'~in~your~'{NiceTabular}'~because~ + you~have~not~used~the~key~'caption'.~The~key~'label'~will~be~ignored. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { W~warning } + { + Line~\msg_line_number:.~The~cell~is~too~wide~for~your~column~'W'~ + (row~\int_use:N \c@iRow). + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Construct~too~large } + { + Construct~too~large.\\ + Your~command~\token_to_str:N #1 + can't~be~drawn~because~your~matrix~is~too~small.\\ + That~command~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { underscore~after~nicematrix } + { + Problem~with~'underscore'.\\ + The~package~'underscore'~should~be~loaded~before~'nicematrix'.~ + You~can~go~on~but~you~won't~be~able~to~write~something~such~as:\\ + '\token_to_str:N \Cdots\token_to_str:N _{n~\token_to_str:N \text{~times}}'. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { ampersand~in~light-syntax } + { + Ampersand~forbidden.\\ + You~can't~use~an~ampersand~(\token_to_str:N &)~to~separate~columns~because~ + ~the~key~'light-syntax'~is~in~force.~This~error~is~fatal. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { double-backslash~in~light-syntax } + { + Double~backslash~forbidden.\\ + You~can't~use~\token_to_str:N + \\~to~separate~rows~because~the~key~'light-syntax'~ + is~in~force.~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 { hlines~with~color } + { + Incompatible~keys.\\ + You~can't~use~the~keys~'hlines',~'vlines'~or~'hvlines'~for~a~ + '\token_to_str:N \Block'~when~the~key~'color'~or~'draw'~is~used.\\ + Maybe~it~will~possible~in~future~version.\\ + Your~key~will~be~discarded. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { bad~value~for~baseline } + { + 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'~or~of~ + the~form~'line-i'.\\ + A~value~of~1~will~be~used. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { ragged2e~not~loaded } + { + You~have~to~load~'ragged2e'~in~order~to~use~the~key~'\l_keys_key_str'~in~ + your~column~'\l_@@_vpos_col_str'~(or~'X').~The~key~'\str_lowercase:V + \l_keys_key_str'~will~be~used~instead. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Invalid~name } + { + Invalid~name.\\ + You~can't~give~the~name~'\l_keys_value_tl'~to~a~\token_to_str:N + \SubMatrix\ of~your~\@@_full_name_env:.\\ + A~name~must~be~accepted~by~the~regular~expression~[A-Za-z][A-Za-z0-9]*.\\ + This~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Wrong~line~in~SubMatrix } + { + Wrong~line.\\ + 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.~It~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Impossible~delimiter } + { + 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'. } \\ + 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.~ + That~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { key~multiplicity~with~dotted } + { + Incompatible~keys. \\ + You~have~used~the~key~'multiplicity'~with~the~key~'dotted'~ + in~a~'custom-line'.~They~are~incompatible. \\ + The~key~'multiplicity'~will~be~discarded. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { empty~environment } + { + Empty~environment.\\ + Your~\@@_full_name_env:\ is~empty.~This~error~is~fatal. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { No~letter~and~no~command } + { + Erroneous~use.\\ + Your~use~of~'custom-line'~is~no-op~since~you~don't~have~used~the~ + key~'letter'~(for~a~letter~for~vertical~rules)~nor~the~keys~'command'~or~ + ~'ccommand'~(to~draw~horizontal~rules).\\ + However,~you~can~go~on. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Forbidden~letter } + { + Forbidden~letter.\\ + You~can't~use~the~letter~'\l_@@_letter_str'~for~a~customized~line.\\ + It~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Several~letters } + { + Wrong~name.\\ + You~must~use~only~one~letter~as~value~for~the~key~'letter'~(and~you~ + have~used~'\l_@@_letter_str').\\ + It~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Delimiter~with~small } + { + Delimiter~forbidden.\\ + 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 } + { + Unknown~cell.\\ + Your~command~\token_to_str:N\line\{#1\}\{#2\}~in~ + the~\token_to_str:N \CodeAfter\ of~your~\@@_full_name_env:\ + can't~be~executed~because~a~cell~doesn't~exist.\\ + This~command~\token_to_str:N \line\ will~be~ignored. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nnn { Duplicate~name~for~SubMatrix } + { + Duplicate~name.\\ + The~name~'#1'~is~already~used~for~a~\token_to_str:N \SubMatrix\ + in~this~\@@_full_name_env:.\\ + This~key~will~be~ignored.\\ + \bool_if:NF \c_@@_messages_for_Overleaf_bool + { 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 } + { + Erroneous~use.\\ + 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:.\\ + This~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Hdotsfor~in~col~0 } + { + Erroneous~use.\\ + 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 } + { + Bad~corner.\\ + #1~is~an~incorrect~specification~for~a~corner~(in~the~key~ + 'corners').~The~available~values~are:~NW,~SW,~NE~and~SE.\\ + This~specification~of~corner~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { bad~border } + { + Bad~border.\\ + \l_keys_key_str\space~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~(and~you~can~ + also~use~the~key~'tikz' + \IfPackageLoadedTF { tikz } + { } + {~if~you~load~the~LaTeX~package~'tikz'}).\\ + This~specification~of~border~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { tikz~key~without~tikz } + { + Tikz~not~loaded.\\ + You~can't~use~the~key~'tikz'~for~the~command~'\token_to_str:N + \Block'~because~you~have~not~loaded~tikz.~ + This~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { last-col~non~empty~for~NiceArray } + { + Erroneous~use.\\ + 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 } + { + Erroneous~use.\\ + 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 } + { + Block~too~large.\\ + 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 } + { + Block~too~large.\\ + 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:.\\ + This~block~and~maybe~others~will~be~ignored. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nn { unknown~column~type } + { + Bad~column~type.\\ + The~column~type~'#1'~in~your~\@@_full_name_env:\ + is~unknown. \\ + This~error~is~fatal. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { unknown~column~type~S } + { + Bad~column~type.\\ + The~column~type~'S'~in~your~\@@_full_name_env:\ is~unknown. \\ + If~you~want~to~use~the~column~type~'S'~of~siunitx,~you~should~ + load~that~package. \\ + This~error~is~fatal. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { tabularnote~forbidden } + { + Forbidden~command.\\ + You~can't~use~the~command~\token_to_str:N\tabularnote\ + ~here.~This~command~is~available~only~in~ + \{NiceTabular\},~\{NiceTabular*\}~and~\{NiceTabularX\}~or~in~ + the~argument~of~a~command~\token_to_str:N \caption\ included~ + in~an~environment~{table}. \\ + This~command~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { borders~forbidden } + { + Forbidden~key.\\ + 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.\\ + This~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { bottomrule~without~booktabs } + { + booktabs~not~loaded.\\ + You~can't~use~the~key~'tabular/bottomrule'~because~you~haven't~ + loaded~'booktabs'.\\ + This~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { enumitem~not~loaded } + { + enumitem~not~loaded.\\ + You~can't~use~the~command~\token_to_str:N\tabularnote\ + ~because~you~haven't~loaded~'enumitem'.\\ + All~the~commands~\token_to_str:N\tabularnote\ will~be~ + ignored~in~the~document. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { tikz~in~custom-line~without~tikz } + { + Tikz~not~loaded.\\ + You~have~used~the~key~'tikz'~in~the~definition~of~a~ + customized~line~(with~'custom-line')~but~tikz~is~not~loaded.~ + You~can~go~on~but~you~will~have~another~error~if~you~actually~ + use~that~custom~line. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { tikz~in~borders~without~tikz } + { + Tikz~not~loaded.\\ + You~have~used~the~key~'tikz'~in~a~key~'borders'~(of~a~ + command~'\token_to_str:N\Block')~but~tikz~is~not~loaded.~ + That~key~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { color~in~custom-line~with~tikz } + { + Erroneous~use.\\ + In~a~'custom-line',~you~have~used~both~'tikz'~and~'color',~ + which~is~forbidden~(you~should~use~'color'~inside~the~key~'tikz').~ + The~key~'color'~will~be~discarded. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Wrong~last~row } + { + Wrong~number.\\ + 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 } + { + Nested~environments.\\ + Environments~of~nicematrix~can't~be~nested.\\ + This~error~is~fatal. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Outside~math~mode } + { + 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 } + { + Bad~name.\\ + The~value~of~key~'\l_keys_key_str'~must~be~of~length~1.\\ + It~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { TabularNote~in~CodeAfter } + { + Environment~{TabularNote}~forbidden.\\ + You~must~use~{TabularNote}~at~the~end~of~your~{NiceTabular}~ + but~*before*~the~\token_to_str:N \CodeAfter.\\ + This~environment~{TabularNote}~will~be~ignored. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { varwidth~not~loaded } + { + varwidth~not~loaded.\\ + You~can't~use~the~column~type~'V'~because~'varwidth'~is~not~ + loaded.\\ + Your~column~will~behave~like~'p'. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknow~key~for~RulesBis } + { + Unkown~key.\\ + Your~key~'\l_keys_key_str'~is~unknown~for~a~rule.\\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + color,~ + dotted,~ + multiplicity,~ + sep-color,~ + tikz,~and~total-width. + } + +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~Block } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~command~\token_to_str:N + \Block.\\ It~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~b,~B,~borders,~c,~draw,~fill,~ + hlines,~hvlines,~l,~line-width,~name,~rounded-corners,~r,~respect-arraystretch,~ + t,~T,~tikz,~transparent~and~vlines. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nn { Version~of~siunitx~too~old } + { + siunitx~too~old.\\ + You~can't~use~'S'~columns~because~your~version~of~'siunitx'~ + is~too~old.~You~need~at~least~v~3.0.38~and~your~log~file~says:~"siunitx,~ + \use:c { ver @ siunitx.sty }". \\ + This~error~is~fatal. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~Brace } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~commands~\token_to_str:N + \UnderBrace\ and~\token_to_str:N \OverBrace.\\ + It~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~color,~left-shorten,~ + right-shorten,~shorten~(which~fixes~both~left-shorten~and~ + right-shorten)~and~yshift. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~CodeAfter } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown.\\ + It~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + 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~CodeBefore } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown.\\ + It~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + create-cell-nodes,~ + delimiters/color~and~ + sub-matrix~(several~subkeys). + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~SubMatrix } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown.\\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + 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 } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown.\\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + bottomrule,~ + code-after,~ + code-before,~ + detect-duplicates,~ + enumitem-keys,~ + enumitem-keys-para,~ + para,~ + label-in-list,~ + label-in-tabular~and~ + style. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~RowStyle } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~command~ + \token_to_str:N \RowStyle. \\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + 'bold',~ + 'cell-space-top-limit',~ + 'cell-space-bottom-limit',~ + 'cell-space-limits',~ + 'color',~ + 'nb-rows'~and~ + 'rowcolor'. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~NiceMatrixOptions } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~command~ + \token_to_str:N \NiceMatrixOptions. \\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + allow-duplicate-names,~ + caption-above,~ + 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,~ + custom-key,~ + create-extra-nodes,~ + create-medium-nodes,~ + create-large-nodes,~ + delimiters~(several~subkeys),~ + end-of-row,~ + first-col,~ + first-row,~ + hlines,~ + hvlines,~ + hvlines-except-borders,~ + last-col,~ + last-row,~ + left-margin,~ + light-syntax,~ + matrix/columns-type,~ + notes~(several~subkeys),~ + nullify-dots,~ + pgf-node-code,~ + renew-dots,~ + renew-matrix,~ + respect-arraystretch,~ + right-margin,~ + rules~(with~the~subkeys~'color'~and~'width'),~ + small,~ + sub-matrix~(several~subkeys),~ + vlines,~ + xdots~(several~subkeys). + } +% \end{macrocode} +% +% For `|{NiceArray}|`, the set of keys is the same as for |{NiceMatrix}| +% excepted that there is no |l| and |r|. +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~NiceArray } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~environment~ + \{NiceArray\}. \\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + 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,~ + hvlines-except-borders,~ + last-col,~ + last-row,~ + left-margin,~ + light-syntax,~ + name,~ + nullify-dots,~ + pgf-node-code,~ + renew-dots,~ + respect-arraystretch,~ + right-margin,~ + rules~(with~the~subkeys~'color'~and~'width'),~ + small,~ + t,~ + vlines,~ + xdots/color,~ + xdots/shorten-start,~ + xdots/shorten-end,~ + 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 no |l| and |r|). +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~NiceMatrix } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~ + \@@_full_name_env:. \\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + 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-type,~ + columns-width,~ + corners,~ + create-extra-nodes,~ + create-medium-nodes,~ + create-large-nodes,~ + extra-left-margin,~ + extra-right-margin,~ + first-col,~ + first-row,~ + hlines,~ + hvlines,~ + hvlines-except-borders,~ + l,~ + last-col,~ + last-row,~ + left-margin,~ + light-syntax,~ + name,~ + nullify-dots,~ + pgf-node-code,~ + r,~ + renew-dots,~ + respect-arraystretch,~ + right-margin,~ + rules~(with~the~subkeys~'color'~and~'width'),~ + small,~ + t,~ + vlines,~ + xdots/color,~ + xdots/shorten-start,~ + xdots/shorten-end,~ + xdots/shorten~and~ + xdots/line-style. + } +% \end{macrocode} +% +% \begin{macrocode} +\@@_msg_new:nnn { Unknown~key~for~NiceTabular } + { + Unknown~key.\\ + The~key~'\l_keys_key_str'~is~unknown~for~the~environment~ + \{NiceTabular\}. \\ + That~key~will~be~ignored. \\ + \c_@@_available_keys_str + } + { + The~available~keys~are~(in~alphabetic~order):~ + b,~ + baseline,~ + c,~ + caption,~ + 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,~ + custom-line,~ + create-extra-nodes,~ + create-medium-nodes,~ + create-large-nodes,~ + extra-left-margin,~ + extra-right-margin,~ + first-col,~ + first-row,~ + hlines,~ + hvlines,~ + hvlines-except-borders,~ + label,~ + last-col,~ + last-row,~ + left-margin,~ + light-syntax,~ + name,~ + notes~(several~subkeys),~ + nullify-dots,~ + pgf-node-code,~ + renew-dots,~ + respect-arraystretch,~ + right-margin,~ + rounded-corners,~ + rules~(with~the~subkeys~'color'~and~'width'),~ + short-caption,~ + t,~ + tabularnote,~ + vlines,~ + xdots/color,~ + xdots/shorten-start,~ + xdots/shorten-end,~ + xdots/shorten~and~ + xdots/line-style. + } +% \end{macrocode} +% +% +% \begin{macrocode} +\@@_msg_new:nnn { Duplicate~name } + { + 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'.\\ + \c_@@_available_keys_str + } + { + 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 } + { + Erroneous~use.\\ + You~can't~give~the~value~'auto'~to~the~key~'columns-width'~here.~ + That~key~will~be~ignored. + } +% \end{macrocode} +% +% \newpage +% \tableofcontents +% +% \endinput +% Local Variables: +% TeX-fold-mode: t +% TeX-fold-preserve-comments: nil +% fill-column: 80 +% End: + + diff --git a/macros/latex/contrib/nicematrix/nicematrix-code.pdf b/macros/latex/contrib/nicematrix/nicematrix-code.pdf new file mode 100644 index 0000000000..6cc99d6835 Binary files /dev/null and b/macros/latex/contrib/nicematrix/nicematrix-code.pdf differ diff --git a/macros/latex/contrib/nicematrix/nicematrix-french.pdf b/macros/latex/contrib/nicematrix/nicematrix-french.pdf index efad4b58ef..fcc05694fd 100644 Binary files a/macros/latex/contrib/nicematrix/nicematrix-french.pdf and b/macros/latex/contrib/nicematrix/nicematrix-french.pdf differ diff --git a/macros/latex/contrib/nicematrix/nicematrix-french.tex b/macros/latex/contrib/nicematrix/nicematrix-french.tex index 920c184433..1b5bf2b9df 100644 --- a/macros/latex/contrib/nicematrix/nicematrix-french.tex +++ b/macros/latex/contrib/nicematrix/nicematrix-french.tex @@ -17,6 +17,8 @@ \usepackage{siunitx} \usepackage{verbatim} \usepackage{caption} +\usepackage{tocloft} +\setlength{\cftsubsecnumwidth}{3em} % for the numbers of subsections of the TOC % On utilise \MakeShortVerb de shortvrb et pas \DefineShortVerb de fancyvrb % car on ne veut pas que le contenu des petits Ă©lĂ©ments en verbatim soit coloriĂ© @@ -42,18 +44,6 @@ \usepackage{tcolorbox} \usepackage{adjustbox} \usepackage[auto-lang=false]{lipsum} -\usepackage[hyperfootnotes = false]{hyperref} - -\hypersetup - { - pdfinfo = - { - Title = L’extension nicematrix , - Subject = Une extension LaTeX , - Author = F. Pantigny - } - } - \NewDocumentEnvironment {scope} {} {} {} @@ -67,6 +57,26 @@ \NewDocumentCommand{\Definition}{m} {{\setlength{\fboxsep}{1pt}\colorbox{gray!20}{\ttfamily \vphantom{gl}#1}}} +\usepackage{makeidx} +\makeindex + +\NewDocumentCommand{\indexcommand}{m}{\index{#1@\texttt{\textbackslash #1}}} + +\NewDocumentCommand{\indexenv}{m}{\index{#1@\texttt{\{#1\}}}} + + +\usepackage[hyperfootnotes = false]{hyperref} + +\hypersetup + { + pdfinfo = + { + Title = L’extension nicematrix , + Subject = Une extension LaTeX , + Author = F. Pantigny + } + } + \begin{document} @@ -155,7 +165,7 @@ utiliser pour dĂ©velopper de nouvelles fonctionnalitĂ©s. Comme toujours avec pour Ăªtre utilisĂ©es Ă  la compilation suivante. C'est pourquoi l'utilisation de \pkg{nicematrix} nĂ©cessite \textbf{plusieurs compilations successives}.\footnote{Si vous utilisez Overleaf, Overleaf effectue - automatiquement le nombre de compilations nĂ©cessaire.} + automatiquement un nombre de compilations suffisant.} \medskip La plupart des fonctionnalitĂ©s de \pkg{nicematrix} sont accessibles sans avoir Ă  @@ -163,6 +173,7 @@ utiliser explicitement \textsc{pgf} ou TikZ (ce dernier n'est d'ailleurs pas chargĂ© par dĂ©faut). \medskip +\indexcommand{NiceMatrixOptions} Une commande|\NiceMatrixOptions| est fournie pour rĂ©gler les options (la portĂ©e des options fixĂ©es par cette commande est le groupe TeX courant : elles sont semi-globales). @@ -172,6 +183,23 @@ semi-globales). \section{Les environnements de cette extension} + +\indexenv{NiceTabular} +\indexenv{NiceTabular*} +\indexenv{NiceArray} +\indexenv{pNiceArray} +\indexenv{bNiceArray} +\indexenv{BNiceArray} +\indexenv{vNiceArray} +\indexenv{VNiceArray} +\indexenv{NiceMatrix} +\indexenv{pNiceMatrix} +\indexenv{bNiceMatrix} +\indexenv{BNiceMatrix} +\indexenv{vNiceMatrix} +\indexenv{VNiceMatrix} + + L'extension \pkg{nicematrix} dĂ©finit les nouveaux environnements suivants : \medskip @@ -227,6 +255,9 @@ crochets, une liste optionnelle de paires de la forme \textsl{clĂ©=valeur}. \section{L'espace vertical entre les rangĂ©es} \label{cell-space} +\index{cell-space-top-limit} +\index{cell-space-bottom-limit} +\index{cell-space-limits} Il est bien connu que certaines rangĂ©es des tableaux crĂ©Ă©s par dĂ©faut avec LaTeX sont trop proches l'une de l'autre. On en donne ci-dessous un exemple @@ -248,7 +279,7 @@ $\begin{pmatrix} En s'inspirant de l'extension \pkg{cellspace} qui traite de ce problème, l'extension \pkg{nicematrix} propose deux clĂ©s |cell-space-top-limit| et |cell-space-bottom-limit| qui sont similaires aux deux paramètres -|\cellspacetoplimit| et |\cellspacebottomlimit| proposĂ©s par \pkg{cellspace}. +|\cellspacetoplimit| et |\cellspacebottomlimit| proposĂ©s par \pkg{cellspace}.\index{cellspace@\pkg{cellspace} (extension)} Il existe aussi une clĂ© |cell-space-limits| pour rĂ©gler simultanĂ©ment les deux paramètres. @@ -284,6 +315,8 @@ $\begin{pNiceMatrix} \medskip \section{La clĂ© baseline} +\index{baseline (clĂ© pour un environnement)} + L'extension \pkg{nicematrix} propose une option |baseline| pour la position verticale des tableaux. Cette option |baseline| prend comme valeur un entier qui indique le numĂ©ro de rangĂ©e dont la ligne de base servira de ligne de base pour @@ -420,6 +453,8 @@ $A=\begin{pNiceArray}{cc|cc}~emphase#[baseline=line-3]@ \section{Les blocs} \label{Block} +\index{Blocs@\textbf{Blocs dans les tableaux}|(} +\indexcommand{Block} \subsection{Cas gĂ©nĂ©ral} @@ -499,52 +534,63 @@ $\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] La commande |\Block| accepte en premier argument optionnel (entre crochets) une liste de couples \textsl{clĂ©=valeur}. Les clĂ©s sont les suivantes : \begin{itemize} -\item la clĂ© \Definition{fill} prend en argument une couleur et remplit le bloc +\item \index{fill (clĂ© de \texttt{\textbackslash Block})} +la clĂ© \Definition{fill} prend en argument une couleur et remplit le bloc avec cette couleur ; -\item la clĂ© \Definition{draw} prend en argument une couleur et trace le cadre +\item \index{draw (clĂ© de \texttt{\textbackslash Block})} +la clĂ© \Definition{draw} prend en argument une couleur et trace le cadre avec cette couleur (la valeur par dĂ©faut de cette clĂ© est la couleur courante des filets du tableau) ; -\item la clĂ© \Definition{color} prend en argument une couleur et l'applique au +\item \index{color!clĂ© de \texttt{\textbackslash Block}} +la clĂ© \Definition{color} prend en argument une couleur et l'applique au contenu et trace Ă©galement le cadre avec cette couleur ; -\item les clĂ©s \Definition{hlines}, \Definition{vlines} et \Definition{hvlines} +\item \index{vlines!clĂ© de \texttt{\textbackslash Block}} \index{hvlines!clĂ© de + \texttt{\textbackslash Block}} \index{hlines!clĂ© de \texttt{\textbackslash Block}} +les clĂ©s \Definition{hlines}, \Definition{vlines} et \Definition{hvlines} tracent les filets correspondants dans le bloc\footnote{NĂ©anmoins, les filets ne sont pas tracĂ©s dans les sous-blocs du bloc, conformĂ©ment Ă  l'esprit de \pkg{nicematrix}: les filets ne sont pas tracĂ©s dans les blocs (cf. section~\ref{rules} p.~\pageref{rules}).} ; -\item la clĂ© \Definition{line-width} fixe la largeur utilisĂ©e pour tracer les +\item \index{line-width (clĂ© de \texttt{\textbackslash Block})} +la clĂ© \Definition{line-width} fixe la largeur utilisĂ©e pour tracer les filets (n'a d'intĂ©rĂªt que si |draw|, |hvlines|, |hlines| ou |vlines| est utilisĂ©e) ; -\item la clĂ© \Definition{rounded-corners} impose des coins arrondis (pour le +\item \index{rounded-corners!clĂ© de \texttt{\textbackslash Block}} \index{Coins arrondis!pour un bloc} +la clĂ© \Definition{rounded-corners} impose des coins arrondis (pour le cadre dessinĂ© par |draw| et le fond dessinĂ© par |fill|) avec un rayon Ă©gal Ă  la valeur de cette clĂ© (la valeur par dĂ©faut est 4~pt\footnote{Cette valeur par dĂ©faut est la valeur initiale des \emph{rounded corners} de TikZ.}) ; -\item quand la clĂ© \Definition{tikz} est utilisĂ©e, le chemin TikZ correspondant +\item \index{tikzz@tikz!clĂ© de \texttt{\textbackslash Block}} +quand la clĂ© \Definition{tikz} est utilisĂ©e, le chemin TikZ correspondant au rectangle dĂ©limitant le bloc est exĂ©cutĂ© avec TikZ\footnote{TikZ doit Ăªtre chargĂ© prĂ©alablement (par dĂ©faut, \pkg{nicematrix} ne charge que \textsc{pgf}), faute de quoi, une erreur sera levĂ©e.} en utilisant comme options la valeur de cette clĂ© |tikz| (qui doit donc Ăªtre une liste de clĂ©s TikZ applicables Ă  un chemin de TikZ). Pour des exemples d'utilisation de cette clĂ© |tikz|, voir p.~\pageref{tikz-key-examples} ; -\item la clĂ© \Definition{name} donne un nom au nÅ“ud TikZ rectangulaire +\item \index{name!clĂ© de \texttt{\textbackslash Block}} +la clĂ© \Definition{name} donne un nom au nÅ“ud TikZ rectangulaire correspondant au bloc ; on peut utiliser ce nom avec TikZ dans le |\CodeAfter| (cf.~p.~\pageref{code-after}); -\item la clĂ© \Definition{respect-arraystretch} Ă©vite la remise Ă  $1$ de +\item \index{respect-arraystretch (clĂ© de \texttt{\textbackslash Block})} +la clĂ© \Definition{respect-arraystretch} Ă©vite la remise Ă  $1$ de |\arraystretch| en dĂ©but de bloc (qui a lieu par dĂ©faut) ; -\item la clĂ© \Definition{borders} permet de ne tracer que certaines des bordures +\item \index{borders (clĂ© de \texttt{\textbackslash Block})} \index{tikzz@tikz!clĂ© de «borders» de \texttt{\textbackslash Block}} +la clĂ© \Definition{borders} permet de ne tracer que certaines des bordures du bloc : cette clĂ© prend comme valeur une liste d'Ă©lĂ©ments parmi les suivants : |left|, |right|, |top| et |bottom| ; on peut en fait, dans la liste qui est la valeur de la clĂ© |borders| mettre une entrĂ©e de la forme |tikz={|\textsl{liste}|}| oĂ¹ \textsl{liste} est une liste de couples \textsl{clĂ©=valeur} de TikZ spĂ©cifiant les caractĂ©ristiques graphiques des traits qui seront dessinĂ©s (pour un exemple, voir p.~\pageref{tiretes}). - -\item \colorbox{yellow!50}{\textbf{Nouveau 6.15}}\par\nobreak Par dĂ©faut, les -filets ne sont pas tracĂ©s dans les blocs (voir Ă  ce sujet la partie sur les -filets, section~\ref{rules} p.~\pageref{rules}). NĂ©anmoins, si la clĂ© -\Definition{transparent} est utilisĂ©e, les filets seront tracĂ©s. Pour un +\item \index{transparent (clĂ© de \texttt{\textbackslash Block})} +Par dĂ©faut, les filets ne sont pas tracĂ©s dans les blocs (voir Ă  ce sujet +la partie sur les filets, section~\ref{rules} p.~\pageref{rules}). NĂ©anmoins, si +la clĂ© \Definition{transparent} est utilisĂ©e, les filets seront tracĂ©s. Pour un example, voir la section~\ref{tikz-key-examples}, -page~\pageref{tikz-key-examples}. +page~\pageref{tikz-key-examples}. Attention : cette clĂ© n'implique pas du tout +que le contenu du bloc sera transparent. \end{itemize} @@ -818,8 +864,10 @@ Concernant le positionnement vertical, la commande |\Block| admet les clĂ©s \texttt{c} est dĂ©jĂ  prise pour le positionnement horizontal.}, |t|, |b|, |T| et~|B|. + \begin{itemize} -\item Avec la clĂ© |v-center|, le contenu du bloc est centrĂ© verticalement. +\item \index{v-center (clĂ© de \texttt{\textbackslash Block)})} +Avec la clĂ© |v-center|, le contenu du bloc est centrĂ© verticalement. \item Avec la clĂ© |t|, la ligne de base du contenu du bloc est alignĂ©e avec la ligne de base de la première rangĂ©e concernĂ©e par le bloc. @@ -934,10 +982,11 @@ text & text \\ \end{scope} - +\index{Blocs@\textbf{Blocs dans les tableaux}|)} \section{Les filets horizontaux et verticaux} \label{rules} +\index{Filets@\textbf{Filets dans les tableaux}|(} Les techniques habituelles pour tracer des filets peuvent Ăªtre utilisĂ©es dans les environnements de \pkg{nicematrix}, Ă  l'exception de |\vline|. Il y a @@ -980,6 +1029,7 @@ cf.~p.~\pageref{exterior}). \medskip +\index{booktabs@\pkg{booktabs} (extension)} Si vous utilisez \pkg{booktabs} (qui fournit |\toprule|, |\midrule|, |\bottomrule|, etc.) et que vous tenez absolument Ă  mettre des filets verticaux (ce qui est contraire Ă  l'esprit Ă  \pkg{booktabs}), vous constaterez que les @@ -1017,6 +1067,7 @@ Il reste nĂ©anmoins possible de dĂ©finir un spĂ©cificateur, nommĂ© par exemple \subsubsection{La commande \textbackslash cline} \label{remark-cline} +\index{cline@\texttt{\textbackslash cline} (commande de LaTeX)} Les traits verticaux et horizontaux que l'on insère avec |\hline| et le spĂ©cificateur de colonne «\verb+|+» de \pkg{array} rendent le tableau plus large @@ -1048,6 +1099,7 @@ A&B&C&D \\ \end{scope} \medskip +\index{standard-cline} Dans les environnements de \pkg{nicematrix}, cette situation est corrigĂ©e (il est nĂ©anmoins possible de revenir au comportement par dĂ©faut de |\cline| avec la clĂ© |standard-cline|). @@ -1079,6 +1131,11 @@ Dans les environnements de \pkg{nicematrix}, une instruction \subsection{L'Ă©paisseur et la couleur des filets} +\indexcommand{arrayrulewidth} +\index{Couleur!des filets} +\index{width!sous-clĂ© de «rules»} +\index{rules (clĂ© pour un environnement)} + Les environnements de \pkg{nicematrix} proposent une clĂ© |rules/width| pour fixer la largeur (on devrait plutĂ´t dire l'Ă©paisseur) des filets dans l'environnement. En fait, cette clĂ© ne fait que fixer la valeur du paramètre @@ -1089,6 +1146,7 @@ On sait que \pkg{colortbl} propose la commande |\arrayrulecolor| pour spĂ©cifier la couleur de ces filets. \smallskip +\indexcommand{arrayrulecolor} Avec \pkg{nicematrix}, il est possible de spĂ©cifier une couleur mĂªme si \pkg{colortbl} n'est pas chargĂ©. Par souci de compatibilitĂ©, la commande est nommĂ©e Ă©galement |\arrayrulecolor|. Les environnements de \pkg{nicematrix} @@ -1122,13 +1180,16 @@ muguet & dahlia & souci \\ \medskip \subsection{Les outils de nicematrix pour tracer des filets} + + Les outils proposĂ©s par \pkg{nicematrix} pour tracer des filets sont les suivants : \begin{itemize} \item les clĂ©s |hlines|, |vlines|, |hvlines| et |hvlines-except-borders|; \item le spĂ©cificateur «\verb+|+» dans le prĂ©ambule (pour les environnements Ă  prĂ©ambule) ; -\item la commande |\Hline|. +\item \indexcommand{Hline} +la commande |\Hline|. \end{itemize} \medskip @@ -1160,6 +1221,11 @@ de ces clĂ©s, voir |custom-line| p.~\pageref{custom-line}. \medskip \subsubsection{Les clĂ©s hlines et vlines} +\index{hlines|see{Filets}} +\index{hlines!clĂ© pour un environnement} +\index{vlines|see{Filets}} +\index{vlines!clĂ© pour un environnement} + \medskip Les clĂ©s |hlines| et |vlines| (qui, bien sĂ»r, tracent des filets horizontaux et verticaux) prennent comme valeur une liste de numĂ©ros qui sont les numĂ©ros des @@ -1188,6 +1254,9 @@ $\begin{pNiceMatrix}[vlines,rules/width=0.2pt] \subsubsection{Les clĂ©s hvlines et hvlines-except-borders} \label{hvlines} +\index{hvlines|see{Filets}} +\index{hvlines!clĂ© pour un environnement} +\index{hvlines-except-borders} La clĂ© |hvlines|, qui ne prend pas de valeur, est la conjonction des clĂ©s |hlines| et |vlines|. @@ -1228,6 +1297,9 @@ tcolorbox» p.~\pageref{tcolorbox}. \subsubsection{Les coins (vides)} \label{corners} +\index{Coins (les --- vides)} +\index{corners (clĂ© d'un environnement)} + Les quatre coins d'un tableau seront notĂ©s |NW|, |SW|, |NE| et |SE| (\emph{north west}, \emph{south west}, \emph{north east} et \emph{south east} en anglais). @@ -1241,6 +1313,7 @@ rectangle entièrement constituĂ© de cases vides partant de ce coin.\footnote{Po une «case vide» est donnĂ©e plus loin (cf. p.~\pageref{empty-cells}).} \smallskip +\indexcommand{NotEmpty} On peut nĂ©anmoins imposer Ă  une case sans contenu d'Ăªtre considĂ©rĂ©e comme non vide par \pkg{nicematrix} avec la commande |\NotEmpty|. @@ -1340,6 +1413,8 @@ dans les coins (cf.~p.~\pageref{color-in-code-before}). \subsection{La commande \textbackslash diagbox} +\indexcommand{diagbox} + La commande |\diagbox| (inspirĂ©e par l'extension \pkg{diagbox}) permet, quand elle est utilisĂ©e dans une case, de couper cette case selon une diagonale descendante. @@ -1369,6 +1444,11 @@ Cette commande |\diagbox| peut aussi Ăªtre utilisĂ©e dans un |\Block|. \subsection{Commandes pour filets personnalisĂ©s} \label{custom-line} +\index{command (clĂ© de «custom-line»)} +\index{ccommand (clĂ© de «custom-line»)} +\index{letter (clĂ© de «custom-line»)} +\index{custom-line|(} + Il est possible de dĂ©finir des commandes et des lettres pour des filets personnalisĂ©s avec la clĂ© |custom-line|, utilisable dans |\NiceMatrixOptions| ou @@ -1411,6 +1491,9 @@ Il est possible de spĂ©cifier des filets multiples, colorĂ©s avec une couleur entre les filets (comme on peut le faire avec \pkg{colortbl} par exemple). \begin{itemize} +\index{multiplicity (clĂ© de «custom-line»)} +\index{color!clĂ© de «custom-line»} +\index{sep-color (clĂ© de «custom-line»)} \item la clĂ© |multiplicity| indique le nombre de traits successifs qui seront tracĂ©s : par exemple, une valeur de~$2$ va crĂ©er des filets doubles comme crĂ©Ă©s en standard par |\hline\hline| ou bien \verb+||+ dans le prĂ©ambule d'un @@ -1458,6 +1541,9 @@ Produit C & 5 & 4 & 1 \\ \item \emph{Deuxième possibilitĂ©}\par\nobreak +\index{tikzz@tikz!clĂ© de «custom-line»} +\index{total-width (clĂ© de «custom-line»)} + On peut utiliser la clĂ© |tikz| (si TikZ est chargĂ©, \pkg{nicematrix} ne chargeant par dĂ©faut que \textsc{pgf}). Dans ce cas-lĂ , le filet est tracĂ© directement avec TikZ en utilisant comme paramètres la valeur de la clĂ© |tikz| @@ -1511,6 +1597,9 @@ sept & huit & neuf \medskip \item \emph{Troisième possibilitĂ©} : la clĂ© |dotted|\par\nobreak \label{dotted} +\index{dotted (clĂ© de «custom-line»)} +\indexcommand{hdottedline} +\indexcommand{cdottedline} Comme on le voit dans l'exemple prĂ©cĂ©dent, les pointillĂ©s tracĂ©s par la clĂ© |dotted| de TikZ ne sont pas ronds. C'est pourquoi l'extension \pkg{nicematrix} @@ -1587,13 +1676,17 @@ $\begin{pNiceArray}{cccc:c} \end{pNiceArray}$ \end{itemize} - - +\index{custom-line|)} +\index{Filets@\textbf{Filets dans les tableaux}|)} \section{Les couleurs des rangĂ©es et des colonnes} +\index{Couleur!de fond pour les cases} + \subsection{Utilisation de colortbl} +\index{colortbl@\pkg{colortbl} (extension)} + Rappelons que l'extension \pkg{colortbl} peut Ăªtre chargĂ©e directement par |\usepackage{colortbl}| ou en chargeant l'extension \pkg{xcolor} avec l'option |table| : |\usepackage[table]{xcolor}|. @@ -1637,6 +1730,9 @@ inconvĂ©nients. \subsection{Les outils de nicematrix dans le \textbackslash CodeBefore} \label{color-in-code-before} +\index{code-before!clĂ© pour un environnement} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}} +\index{Body@\texttt{\textbackslash Body}|see{\texttt{\textbackslash CodeBefore}}} L'extension \pkg{nicematrix} propose des outils (indĂ©pendants de \pkg{colortbl}) pour tracer d'abord les rectangles colorĂ©s, puis le contenu des cases et les @@ -1644,8 +1740,7 @@ filets. Cette manière de faire est plus dans l'esprit du «modèle du peintre» formats PostScript et \textsc{pdf} et convient donc mieux aux lecteurs de \textsc{pdf}. L'inconvĂ©nient est qu'elle nĂ©cessite plusieurs compilations successives.\footnote{Si vous utilisez Overleaf, Overleaf effectue - automatiquement le nombre de - compilations nĂ©cessaire.} + automatiquement un nombre de compilations suffisant.} \medskip L'extension \pkg{nicematrix} fournit une clĂ© |code-before| pour du code qui sera @@ -1666,7 +1761,7 @@ peut placer le contenu de ce |code-before| entre les mots-clĂ©s |\CodeBefore| et L'argument optionnel entre crochets est une liste de couples \textsl{clĂ©=valeur} qui seront prĂ©sentĂ©es au fur et Ă  mesure. \footnote{Les clĂ©s disponibles sont \texttt{create-cell-nodes}, \texttt{sub-matrix} (et ses sous-clĂ©s) et - \texttt{delimiters-color}.} + \texttt{delimiters/color}.} \smallskip De nouvelles commandes sont disponibles dans ce |\CodeBefore|: |\cellcolor|, @@ -1676,6 +1771,20 @@ De nouvelles commandes sont disponibles dans ce |\CodeBefore|: |\cellcolor|, position des filets Ă©ventuels sont Ă©galement accessibles : cf. p.~\pageref{nodes-i}.} \label{code-before} +\index{cellcolor@\texttt{\textbackslash cellcolor}!commande du + \texttt{\textbackslash CodeBefore}} +\index{rectanglecolor@\texttt{\textbackslash rectanglecolor} (commande du + \texttt{\textbackslash CodeBefore})} +\index{rowcolor@\texttt{\textbackslash rowcolor}!commande du \texttt{\textbackslash CodeBefore}} +\index{columncolor@\texttt{\textbackslash columncolor}!commande du + \texttt{\textbackslash CodeBefore}} +\index{rowcolors@\texttt{\textbackslash rowcolors} (commande du \texttt{\textbackslash CodeBefore})} +\index{rowlistcolor@\texttt{\textbackslash rowlistcolors} (commande du + \texttt{\textbackslash CodeBefore})} +\index{chessboardcolors@\texttt{\textbackslash chessboardcolors}!(commande + du \texttt{\textbackslash CodeBefore})} +\index{arraycolor@\texttt{\textbackslash arraycolor} (commande du \texttt{\textbackslash + CodeBefore)}} \medskip @@ -1695,7 +1804,9 @@ par une virgule) : \begin{itemize} \item le modèle colorimĂ©trique (|RGB|, |rgb|, |HTML|, etc.) comme spĂ©cifiĂ© par l'extension \pkg{xcolor} ; -\item \colorbox{yellow!50}{\textbf{Nouveau 6.18}} +\item \index{opacity (clĂ© des commandes comme\newline \texttt{\textbackslash + rowcolor}, etc.)} +\colorbox{yellow!50}{\textbf{Nouveau 6.18}} une spĂ©cification d'opacitĂ© selon la forme \texttt{opacity = \textsl{valeur}}. \end{itemize} @@ -1878,6 +1989,9 @@ La commande |\rowcolors| accepte une liste de couples \textsl{clĂ©=valeur} comme argument optionnel en dernière position (l'argument optionnel en première position correspond Ă  l'espace colorimĂ©trique). Les clĂ©s disponibles sont |cols|, |restart| et |respect-blocks|. +\index{cols (clĂ© de \texttt{\textbackslash rowcolors} du \texttt{\textbackslash CodeBefore})} +\index{restart (clĂ© de \texttt{\textbackslash rowcolors} du \texttt{\textbackslash CodeBefore})} +\index{respect-blocks (clĂ© de \texttt{\textbackslash rowcolors} du\newline \texttt{\textbackslash CodeBefore})} \begin{itemize} \item La clĂ© |cols| dĂ©crit un ensemble de colonnes sur lesquelles portera l'effet de |\rowcolors|. Cet ensemble de colonnes est une liste d'intervalles de @@ -1888,13 +2002,11 @@ premier argument de |\rowcolors| recommence avec la mĂªme couleur.\footnote{Autrement, la couleur d'une rangĂ©e ne dĂ©pend que de la paritĂ© de son numĂ©ro absolu.} - \item Avec la clĂ© |respect-blocks|, qui est de type boolĂ©en, les «rangĂ©es» colorĂ©es alternativement peuvent s'Ă©tendre sur plusieurs rangĂ©es rĂ©elles du tableau pour englober les blocs (crĂ©Ă©s par la commande |\Block| : cf.~p.~\pageref{Block}). \end{itemize} - \medskip \begin{scope} \hfuzz=10cm @@ -1965,11 +2077,6 @@ Henri & 14 \\ \end{NiceTabular} \end{scope} - - - - - \medskip \item L'extension \pkg{nicematrix} propose aussi une commande \Definition{\textbackslash rowlistcolors}. Cette commande gĂ©nĂ©ralise la commande |\rowcolors|: au lieu de @@ -2014,6 +2121,9 @@ avec |\resetcolorseries|\footnote{Pour l'initialisation, on a tableau : cf~p.~\pageref{iRow}. Cela permet un ajustement de la gradation des couleurs Ă  la taille du tableau.}). +\index{definecolorseries@\texttt{\textbackslash definecolorseries} (commande de \pkg{xcolor})} +\index{resetcolorseries@\texttt{\textbackslash resetcolorseries} (commande de \pkg{xcolor})} + \smallskip \begin{BVerbatim}[boxwidth=12cm,baseline=c] \begin{NiceTabular}{c} @@ -2055,6 +2165,7 @@ colorient pas les cases qui sont dans les «coins». Dans l'exemple suivant, on utilise la clĂ© |corners| pour demander de considĂ©rer le coin \emph{north east} (NE). \medskip +\index{corners (clĂ© d'un environnement)|textit} \begin{scope} \hfuzz=11cm \begin{BVerbatim}[boxwidth=9cm,baseline=c] @@ -2087,14 +2198,13 @@ utilise la clĂ© |corners| pour demander de considĂ©rer le coin \emph{north east} \end{NiceTabular} \end{scope} - - -\medskip +\bigskip On remarquera que ces commandes sont compatibles avec les commandes de \pkg{booktabs} (|\toprule|, |\midrule|, |\bottomrule|, etc). NĂ©anmoins, l'extension \pkg{booktabs} n'est \emph{pas} chargĂ©e par \pkg{nicematrix}. \medskip +\index{rotate@\texttt{\textbackslash rotate}|textit} \begin{scope} \hfuzz=10cm \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] @@ -2139,6 +2249,8 @@ spĂ©cial & 12 & 12 & 0.5 & 70 \\ \end{NiceTabular} \end{scope} +\index{S (les colonnes S de \pkg{siunitx})|textit} + \medskip On a utilisĂ© le type de colonne |S| de \pkg{siunitx}. @@ -2146,6 +2258,11 @@ On a utilisĂ© le type de colonne |S| de \pkg{siunitx}. \subsection{Outils de coloriage avec la syntaxe de colortbl} \label{colortbl-like} +\index{colortbl-like} +\index{cellcolor@\texttt{\textbackslash cellcolor}!commande en tableau} +\index{rowcolor@\texttt{\textbackslash rowcolor}!commande en tableau} +\index{columncolor@\texttt{\textbackslash columncolor}!commande dans le + prĂ©ambule d'un environnement} On peut accĂ©der aux outils de coloriage prĂ©cĂ©dents avec une syntaxe proche de celle proposĂ©e par \pkg{colortbl} (mĂªme si \pkg{colortbl} n'est pas chargĂ©). On @@ -2202,6 +2319,11 @@ Dupont & Chantal & 15 janvier 1998 \\ \section{La commande \textbackslash RowStyle} \label{RowStyle} +\indexcommand{RowStyle} +\index{cell-space-top-limit} +\index{cell-space-bottom-limit} +\index{cell-space-limits} + La commande |\RowStyle| prend en argument des instructions de mise en forme qui seront appliquĂ©es Ă  chacune des cases restantes sur la rangĂ©e en cours. @@ -2210,20 +2332,25 @@ seront appliquĂ©es Ă  chacune des cases restantes sur la rangĂ©e en cours. Elle prend aussi en premier argument optionnel, entre crochets, une liste de couples \textsl{clĂ©=valeur}. \begin{itemize} -\item La clĂ© |nb-rows| indique le nombre de rangĂ©es consĂ©cutives concernĂ©es par +\item \index{nb-rows (clĂ© de \texttt{\textbackslash RowStyle})} +La clĂ© |nb-rows| indique le nombre de rangĂ©es consĂ©cutives concernĂ©es par les spĂ©cifications de cette commande (une valeur |*| signifie que toutes les rangĂ©es restantes seront concernĂ©es). \item Les clĂ©s |cell-space-top-limit|, |cell-space-bottom-limit| et |cell-space-limits| sont disponibles avec le mĂªme effet que les clĂ©s globales de mĂªme nom (cf. p.~\pageref{cell-space}). -\item La clĂ© |rowcolor| fixe la couleur de fond et la clĂ© |color| fixe la +\item +\index{rowcolor (clĂ© de \texttt{\textbackslash RowStyle})} +\index{color!clĂ© de \texttt{\textbackslash RowStyle}} +La clĂ© |rowcolor| fixe la couleur de fond et la clĂ© |color| fixe la couleur du texte.\footnote{La clĂ© |color| utilise la commande |\color| mais insère aussi une instruction |\leavevmode| devant. Cela Ă©vite un espace vertical parasite dans les cases qui correspondent Ă  des colonnes de type |p|, |b|, |m|, |X| et |V| (qui dĂ©butent en mode vertical).} -\item La clĂ© |bold| impose des caractères gras aux Ă©lĂ©ments de la rangĂ©e, qu'ils +\item \index{bold (clĂ© de \texttt{\textbackslash RowStyle})} +La clĂ© |bold| impose des caractères gras aux Ă©lĂ©ments de la rangĂ©e, qu'ils soient en mode texte ou bien en mode mathĂ©matique. \end{itemize} @@ -2238,6 +2365,7 @@ premier & deuxième & troisième & quatrième \\ I & II & III & IV \end{NiceTabular} \end{BVerbatim} +\index{rotate@\texttt{\textbackslash rotate}|textit} \begin{NiceTabular}{cccc} \hline \RowStyle[cell-space-limits=3pt]{\rotate} @@ -2253,6 +2381,7 @@ La commande |\rotate| est prĂ©sentĂ©e p.~\pageref{rotate}. \section{La largeur des colonnes} \label{width} +\index{Largeur@\textbf{Largeur des colonnes}|(} \subsection{Techniques de base} @@ -2276,6 +2405,7 @@ Rio & Tokyo & Oslo \medskip +\index{columns-width} Dans les environnements de \pkg{nicematrix}, il est aussi possible de fixer la largeur \emph{minimale} de toutes les colonnes (Ă  l'exception des Ă©ventuelles colonnes extĂ©rieures: cf. p.~\pageref{exterior}) directement avec l'option @@ -2353,6 +2483,8 @@ c & d \medskip +\index{NiceMatrixBlock@\texttt{\{NiceMatrixBlock\}}} +\index{auto-columns-width!(clĂ© de \texttt{\{NiceMatrixBlock\}})} Mais il est aussi possible de fixer une zone dans laquelle toutes les matrices auront leurs colonnes de la mĂªme largeur, Ă©gale Ă  la largeur de la case la plus large de toutes les matrices de la zone. Cette construction utilise @@ -2390,8 +2522,11 @@ $\begin{array}{c} \subsection{Les colonnes X} - \label{colonne-X} +\index{tabularx@\pkg{tabularx} (extension)} +\index{NiceTabularX@\texttt{\{NiceTabularX\}}} +\index{X (les colonnes X)} +\index{width!clĂ© de \texttt{\{NiceTabular\}}} L'environnement |{NiceTabular}| propose aussi des colonnes |X| similaires Ă  celles proposĂ©es par l'environnement |{tabularx}| de l'extension Ă©ponyme. @@ -2447,6 +2582,8 @@ Un texte plus court. & Un texte plus court. \subsection{Les colonnes V de varwidth} \label{varwidth} +\index{varwidth@\pkg{varwidth} (extension)} +\index{V (les colonnes V de \pkg{varwidth})} Rappelons d'abord le fonctionnement d'un environnement |{varwidth}| de l'extension Ă©ponyme \pkg{varwidth}. Un tel environnement est similaire Ă  @@ -2537,9 +2674,16 @@ Remarquons que l'extension \pkg{varwidth} a quelques problèmes (au moins dans s version 0.92). Par exemple, avec LuaLaTeX, elle ne fonctionne pas si le contenu commence par une instruction |\color|. +\index{Largeur@\textbf{Largeur des colonnes}|)} \medskip \section{Les rangĂ©es et colonnes extĂ©rieures} + +\index{first-row} +\index{last-row} +\index{first-col} +\index{last-col} + Les environnements de \pkg{nicematrix} permettent de composer des rangĂ©es et des colonnes «extĂ©rieures» grĂ¢ce aux options |first-row|, |last-row|, |first-col| et |last-col|. C'est particulièrement intĂ©ressant pour les matrices (mathĂ©matiques). @@ -2611,9 +2755,11 @@ C'est ce que nous ferons dans la suite. \end{itemize} - - \medskip +\index{code-for-first-row} +\index{code-for-first-col} +\index{code-for-last-row} +\index{code-for-last-col} On peut contrĂ´ler l'apparence de ces rangĂ©es et colonnes avec les options |code-for-first-row|, |code-for-last-row|, |code-for-first-col| et |code-for-last-col|. Ces options sont des listes de tokens qui seront insĂ©rĂ©es @@ -2678,9 +2824,19 @@ p.~\pageref{sub-matrix}). + \section{Les lignes en pointillĂ©s continues} \label{Cdots} +\index{PointillĂ©s@\textbf{PointillĂ©s (lignes en ---)}|(} +\index{Lignes en pointillĂ©s|see{PointillĂ©s}} +\indexcommand{Ldots} +\indexcommand{Cdots} +\index{Ddots@\texttt{\textbackslash Ddots}|textbf} +\index{Iddots@\texttt{\textbackslash Iddots}|textbf} +\indexcommand{Vdots} +\index{mathdots@\pkg{mathdots} (extension)} +\index{xdots (et ses sous-clĂ©s)} Ă€ l'intĂ©rieur des environnements de l'extension \pkg{nicematrix}, de nouvelles commandes sont dĂ©finies : |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots| et |\Iddots|. @@ -2796,6 +2952,7 @@ horizontal.\footnote{Dans \pkg{nicematrix}, il faut utiliser |\hspace*| et non |{NiceArray}| (ou une de ses variantes) avec une colonne de type~|w| ou |W|: cf. p.~\pageref{width}} +\indexcommand{Hspace} Toutefois, une commande~|\hspace*| pourrait interfĂ©rer dans la construction des lignes en pointillĂ©s. C'est pourquoi l'extension \pkg{nicematrix} fournit une commande~|\Hspace| qui est une variante de |\hspace| transparente pour la @@ -2817,6 +2974,8 @@ $\begin{bNiceMatrix} \subsection{L'option nullify-dots} +\index{nullify-dots} + ConsidĂ©rons la matrice suivante qui a Ă©tĂ© composĂ©e classiquement avec l'environnement |{pmatrix}| de \pkg{amsmath}.\par\nobreak @@ -2891,6 +3050,9 @@ horizontalement mais aussi verticalement. \subsection{Les commandes \textbackslash Hdotsfor et \textbackslash Vdotsfor} +\indexcommand{Hdotsfor} +\indexcommand{Vdotsfor} + Certaines personnes utilisent habituellement la commande |\hdotsfor| de l'extension \pkg{amsmath} pour tracer des lignes en pointillĂ©s horizontales dans une matrice. Dans les environnements de \pkg{nicematrix}, il convient d'utiliser @@ -2985,6 +3147,9 @@ C[a_n^{(p)},a_1] & \Cdots & C[a_n^{(p)},a_n] & & C[a_n^{(p)},a_1^{(p)}] & \Cdots \subsection{Comment crĂ©er les lignes en pointillĂ©s de manière transparente} +\index{renew-matrix} +\index{renew-dots} + Si on a un document dĂ©jĂ  tapĂ© qui contient un grand nombre de matrices avec des points de suspension, on peut souhaiter utiliser les lignes pointillĂ©es de \pkg{nicematrix} sans avoir Ă  modifier chaque matrice. Pour cela, @@ -3061,8 +3226,15 @@ $\begin{bNiceMatrix} \subsection{Personnalisation des lignes en pointillĂ©s} - \label{customization} +\index{color!clĂ© pour les lignes pointillĂ©es} +\index{radius (clĂ© pour les lignes pointillĂ©es)} +\index{inter (clĂ© pour les lignes pointillĂ©es)} +\index{line-style (clĂ© pour les lignes pointillĂ©es)} +\index{shorten (clĂ© pour les lignes pointillĂ©es)} +\index{shorten-end (clĂ© pour les lignes pointillĂ©es)} +\index{shorten-start (clĂ© pour les lignes pointillĂ©es)} + Les lignes pointillĂ©es tracĂ©es par |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, |\Iddots|, |\Hdotsfor| et |\Vdotsfor| (ainsi que par la commande |\line| dans le |\CodeAfter| dĂ©crite p.~\pageref{line-in-code-after}) peuvent Ăªtre paramĂ©trĂ©es @@ -3217,8 +3389,12 @@ $\begin{bNiceMatrix}[margin,hvlines] 0 & \Cdots& 0 & 0 \end{bNiceMatrix}$ +\index{PointillĂ©s@\textbf{PointillĂ©s (lignes en ---)}|)} + \section{DĂ©limiteurs dans le prĂ©ambule de l'environnement} +\index{blkarray@\pkg{blkarray} (extension)} + \colorbox{yellow!50}{\textbf{ModifiĂ© 6.16}}\enskip Pour les environnements Ă  prĂ©ambule (|{NiceArray}|, |{pNiceArray}|, etc.), il est possible de placer des dĂ©limiteurs verticaux directement dans le prĂ©ambule.\footnote{Cette syntaxe est @@ -3226,6 +3402,10 @@ dĂ©limiteurs verticaux directement dans le prĂ©ambule.\footnote{Cette syntaxe es \label{delimiters-in-preamble}% \smallskip +\index{left@\texttt{\textbackslash left} : utilisĂ© par \pkg{nicematrix}\newline pour des + dĂ©limiteurs\newline dans les prĂ©ambules} +\index{right@\texttt{\textbackslash right} : utilisĂ© par \pkg{nicematrix}\newline pour des + dĂ©limiteurs\newline dans les prĂ©ambules} Les dĂ©limiteurs ouvrants doivent Ăªtre prĂ©cĂ©dĂ©s du mot-clĂ© |\left| et les dĂ©limiteurs fermants du mot-clĂ© |\right|. Les mots-clĂ©s |\left| et |\right| n'ont pas d'obligation Ă  Ăªtre utilisĂ©s par paires. @@ -3293,12 +3473,16 @@ p.~\pageref{sub-matrix}. \section{Le \textbackslash CodeAfter} +\index{CodeAfter@\texttt{\textbackslash CodeAfter}|(} +\index{code-after} + \label{code-after} On a prĂ©sentĂ© p.~\pageref{code-before} la clĂ© |code-before|. Il existe en fait une clĂ© similaire |code-after| qui peut Ăªtre utilisĂ©e pour indiquer du code qui sera exĂ©cutĂ© \emph{après} la construction du tableau. \medskip +\index{sub-matrix (clĂ© de \texttt{\textbackslash CodeAfter}, avec sous-clĂ©s)} Pour amĂ©liorer la lisibilitĂ© du code, une syntaxe alternative est proposĂ©e : on peut spĂ©cifier les instructions du |code-after| Ă  la fin de l'environnement, après le mot-clĂ© |\CodeAfter|. Bien que ce soit un mot-clĂ©, |\CodeAfter| accepte @@ -3322,6 +3506,7 @@ ces commandes. \subsection{La commande \textbackslash line dans le \textbackslash CodeAfter} \label{line-in-code-after} +\index{line@\texttt{\textbackslash line} (commande du \texttt{\textbackslash CodeAfter})} La commande |\line| permet de tracer directement des lignes en pointillĂ©s entre les cases. Elle prend deux arguments correspondant aux cases ou blocs Ă  relier. Chacun de ces deux arguments peut Ăªtre : @@ -3389,6 +3574,9 @@ autres lignes diagonales (par dĂ©faut, les lignes tracĂ©es par |\Ddots| sont CodeAfter (et le \textbackslash CodeBefore)} \label{sub-matrix} +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})|textbf} La commande |\SubMatrix| permet de positionner des dĂ©limiteurs sur une partie du tableau, partie qui est considĂ©rĂ©e comme une sous-matrice. La commande @@ -3496,25 +3684,36 @@ $\begin{bNiceMatrix}[right-margin=1em] Les clĂ©s disponibles pour la commande |\SubMatrix| sont les suivantes : % \begin{itemize} -\item \Definition{left-xshift} et \Definition{right-xshift} dĂ©placent +\item +\index{left-xshift (clĂ© de \texttt{\textbackslash SubMatrix})} +\index{right-xshift (clĂ© de \texttt{\textbackslash SubMatrix})} +\index{xshift (clĂ© de \texttt{\textbackslash SubMatrix})} +\Definition{left-xshift} et \Definition{right-xshift} dĂ©placent horizontalement les dĂ©limiteurs (il existe aussi la clĂ© \Definition{xshift} qui permet de rĂ©gler simultanĂ©ment ces deux clĂ©s) ; -\item \Definition{extra-height} ajoute une quantitĂ© Ă  la hauteur totale des +\item \index{extra-height (clĂ© de \texttt{\textbackslash SubMatrix})} +\Definition{extra-height} ajoute une quantitĂ© Ă  la hauteur totale des dĂ©limiteurs (hauteur~|\ht| + profondeur |\dp|) ; -\item \Definition{delimiters/color} permet de fixer la couleur des dĂ©limiteurs (cette clĂ© +\item \index{delimiters!---/color pour \texttt{\textbackslash SubMatrix}} +\Definition{delimiters/color} permet de fixer la couleur des dĂ©limiteurs (cette clĂ© est Ă©galement disponible dans |\NiceMatrixOptions| et au niveau des environnements Ă  dĂ©limiteurs ou comme option de |\CodeAfter|) ; -\item \Definition{slim} qui est une clĂ© boolĂ©enne : lorsqu'elle est utilisĂ©e la position +\item \index{slim (clĂ© de \texttt{\textbackslash SubMatrix})} +\Definition{slim} qui est une clĂ© boolĂ©enne : lorsqu'elle est utilisĂ©e la position horizontale des dĂ©limiteurs est calculĂ©e uniquement sur le contenu des cases de la sous-matrice alors, que, dans le cas gĂ©nĂ©ral, elle est calculĂ©e sur le contenu des cases des colonnes mises en jeu (voir exemple ci-dessous) ; -\item \Definition{vlines} contient une liste de numĂ©ros de filets verticaux Ă  tracer dans +\item \index{vlines!clĂ© de \texttt{\textbackslash SubMatrix}} +\Definition{vlines} contient une liste de numĂ©ros de filets verticaux Ă  tracer dans la sous-matrice (si cette clĂ© est utilisĂ©e sans valeur, tous les filets verticaux sont tracĂ©s) ; -\item \Definition{hlines} est similaire Ă  |vlines| mais pour les filets horizontaux ; -\item \Definition{hvlines}, qui s'utilise sans valeur, trace tous les filets dans la +\item \index{hlines!clĂ© de \texttt{\textbackslash SubMatrix}} +\Definition{hlines} est similaire Ă  |vlines| mais pour les filets horizontaux ; +\item \index{hvlines!clĂ© de \texttt{\textbackslash SubMatrix}} +\Definition{hvlines}, qui s'utilise sans valeur, trace tous les filets dans la sous-matrice ; -\item \Definition{code} permet d'insĂ©rer du code, en particulier du code TikZ, après la +\item \index{code (clĂ© de \texttt{\textbackslash SubMatrix})} +\Definition{code} permet d'insĂ©rer du code, en particulier du code TikZ, après la construction de la matrice. Cette clĂ© est dĂ©crite en dĂ©tail plus loin. \end{itemize} On remarquera que tous les filets sont dessinĂ©s après la construction du tableau @@ -3633,13 +3832,13 @@ Part A & the first part \\ \vspace{1cm} -\colorbox{yellow!50}{\textbf{Nouveau 6.16}}\enskip La clĂ© |code| de la commande -|\SubMatrix| permet d'insĂ©rer du code après la crĂ©ation de la matrice. Elle a -surtout pour vocation d'Ăªtre utilisĂ©e pour insĂ©rer des instructions TikZ, -sachant que, dans les instructions TikZ insĂ©rĂ©es dans cette clĂ©, les nÅ“uds de la -forme |i-j| et \verb+i-|j+ sont interprĂ©tĂ©s avec |i| et |j| Ă©tant des numĂ©ros de -ligne et colonne \emph{relatifs Ă  la sous-matrice}.\footnote{Attention : la - syntaxe \texttt{j\string|-i} n'est autorisĂ©e.} +La clĂ© |code| de la commande |\SubMatrix| permet d'insĂ©rer du code après la +crĂ©ation de la matrice. Elle a surtout pour vocation d'Ăªtre utilisĂ©e pour +insĂ©rer des instructions TikZ, sachant que, dans les instructions TikZ insĂ©rĂ©es +dans cette clĂ©, les nÅ“uds de la forme |i-j| et \verb+i-|j+ sont interprĂ©tĂ©s avec +|i| et |j| Ă©tant des numĂ©ros de ligne et colonne \emph{relatifs Ă  la + sous-matrice}.\footnote{Attention : la syntaxe \texttt{j\string|-i} n'est + \emph{pas} autorisĂ©e.} \medskip \begin{scope} @@ -3683,6 +3882,14 @@ Comme on le voit, le tracĂ© effectuĂ© par la commande |\MyDraw| est \emph{relati \subsection{Les commandes \textbackslash OverBrace et \textbackslash UnderBrace dans le \textbackslash CodeAfter} +\index{UncerBrace@\texttt{\textbackslash UnderBrace} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})} +\index{OverBrace@\texttt{\textbackslash OverBrace} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})} + + Les commandes |\OverBrace| and |\UnderBrace| permettent de placer des accolades horizontales sur une partie du tableau. Ces commandes prennent trois arguments : \begin{itemize} @@ -3716,6 +3923,18 @@ $\begin{pNiceMatrix} \end{pNiceMatrix}$ \bigskip +Attention : Aucun espace vertical n'est rĂ©servĂ© par \pkg{nicematrix} pour ces +accolades.\footnote{Voir Ă  ce sujet: \url{https://tex.stackexchange.com/questions/685755}} + +\bigskip +\index{color!clĂ© de \texttt{\textbackslash OverBrace} et \texttt{\textbackslash + UnderBrace}} +\index{yshift (clĂ© de \texttt{\textbackslash OverBrace} et \texttt{\textbackslash + UnderBrace})} +\index{left-shorten (clĂ© de \texttt{\textbackslash OverBrace} et\newline \texttt{\textbackslash + UnderBrace})} +\index{right-shorten (clĂ© de \texttt{\textbackslash OverBrace} et\newline \texttt{\textbackslash + UnderBrace})} Les commandes |\OverBrace| et |\UnderBrace| acceptent en fait un premier argument optionnel (entre crochets) pour une liste de couples \textsl{clĂ©=valeur}. Les clĂ©s disponibles sont les suivantes : @@ -3751,6 +3970,7 @@ $\begin{pNiceMatrix} \OverBrace[shorten,yshift=3pt]{1-4}{2-6}{B} \end{pNiceMatrix}$ +\index{CodeAfter@\texttt{\textbackslash CodeAfter}|)} \section{Les lĂ©gendes et les notes dans les tableaux} @@ -3758,6 +3978,15 @@ $\begin{pNiceMatrix} \subsection{La lĂ©gendes des tableaux} +\label{s:caption} + +\index{caption (clĂ© de \texttt{\{NiceTabular\}})} +\index{short-caption} +\index{label (clĂ© de \texttt{\{NiceTabular\}})} +\index{caption-above} +\index{Legende@\textbf{LĂ©gende des tableaux}} + + L'environnement |{NiceTabular}| propose des clĂ©s |caption|, |short-caption| et |label| Ă  utiliser lorsque le tableau est insĂ©rĂ© dans un environnment flottant (typiquement un environnement |{table}|). @@ -3766,8 +3995,9 @@ L'environnement |{NiceTabular}| propose des clĂ©s |caption|, |short-caption| et L'intĂ©rĂªt d'utiliser cette clĂ© |caption| plutĂ´t que la commande classique |\caption| est que la lĂ©gende, si elle est longue, est justifiĂ©e Ă  la largeur du tableau (hors Ă©ventuelles colonnes extĂ©rieures spĂ©cifiĂ©es par |first-col| et -|last-col|). Il n'y a pas besoin d'avoir recours Ă  l'extension -\pkg{threeparttable} ou l'extension \pkg{floatrow}. +|last-col| : cf.~\ref{exterior}, p.~\pageref{exterior}). Il n'y a pas besoin +d'avoir recours Ă  l'extension \pkg{threeparttable} ou l'extension +\pkg{floatrow}. \smallskip Par dĂ©faut, la lĂ©gende est placĂ©e au-dessous du tableau. Pour avoir la lĂ©gende @@ -3779,11 +4009,19 @@ La clĂ© |short-caption| correspond Ă  l'argument optionnel de la commande classique |\caption| et la clĂ© |label| correspond bien sĂ»r Ă  la commande |\label|. \smallskip -Voir table \ref{t:tabularnote}, p.~\pageref{t:tabularnote} un exemple +Voir table \ref{t:tabularnote}, p.~\pageref{t:tabularnote}, un exemple d'utilisation des clĂ©s |caption| et |label|. +\smallskip +Ces fonctionnalitĂ©s sont compatibles avec l'extension \pkg{caption}. + \subsection{Les notes de pied de page} +\index{footnote@\pkg{footnote} (extension)} +\index{footnote (clĂ©)} +\index{footnotehyper@\pkg{footnotehyper} (extension)} +\index{footnotehyper (clĂ©)} + \smallskip L'extension \pkg{nicematrix} permet, en utilisant \pkg{footnote} ou bien \pkg{footnotehyper}, d'extraire les notes insĂ©rĂ©es avec |\footnote| dans un @@ -3812,16 +4050,21 @@ l'extension \pkg{xcolor} et elle n'est pas parfaitement compatible avec \subsection{Les notes de tableaux} +\index{nota@\textbf{Notes dans les tableaux}|(} + \label{tabularnote} +\index{tabularnote@\texttt{\textbackslash tabularnote}} L'extension \pkg{nicematrix} propose aussi une commande |\tabularnote| qui permet de spĂ©cifier des notes qui seront composĂ©es Ă  la fin du tableau avec une longueur de ligne Ă©gale Ă  la largeur du tableau (hors Ă©ventuelles colonnes -extĂ©rieures spĂ©cifiĂ©es par |first-col| et |last-col|). Sans surprise, cette -commande n'est disponible que dans |{NiceTabular}|, |{NiceTabular*}| and -|{NiceTabularX}|. +extĂ©rieures spĂ©cifiĂ©es par |first-col| et |last-col|: cf.~\ref{exterior}, +p.~\pageref{exterior}). Sans surprise, cette commande n'est disponible que dans +|{NiceTabular}|, |{NiceTabular*}| et |{NiceTabularX}|. + +\index{enumitem@\pkg{enumitem} (extension requise pour utiliser\newline \texttt{\textbackslash tabularnote})} En fait, cette commande n'est disponible que si l'extension \pkg{enumitem} a Ă©tĂ© chargĂ©e (avant ou après \pkg{nicematrix}). Les notes sont en effet composĂ©es en fin de tableau selon un type de liste dĂ©fini par l'extension \pkg{enumitem}. @@ -3883,9 +4126,13 @@ colonne). \item Si la clĂ© |notes/para| est utilisĂ©e, les notes sont composĂ©es Ă  la fin du tableau en un seul paragraphe. -\item Il existe une clĂ© |tabularnote| qui permet d'insĂ©rer du texte dans la zone +\item \index{tabularnote (clĂ© de \texttt{\{NiceTabular\}})} +Il existe une clĂ© |tabularnote| qui permet d'insĂ©rer du texte dans la zone des notes avant les notes numĂ©rotĂ©es. +\index{tabularnote@\texttt{\{TabularNote\}}} +\index{notes (clĂ© pour paramĂ©trer les notes de\newline tableau)} + Une syntaxe alternative est proposĂ©e : il est possible d'utiliser l'environnement |{TabularNote}| Ă  la fin de l'environnement |{NiceTabular}| (mais \emph{avant} l'Ă©ventuel |\CodeAfter|). @@ -3903,6 +4150,12 @@ sont marquĂ©s). Il est possible de dĂ©sactiver cette fonctionnalitĂ© avec la cl \item Il est possible de rĂ©fĂ©rencer une note de tableau (avec la commande |\label| placĂ©e après le |\tabularnote|). + +\item \colorbox{yellow!50}{\textbf{Nouveau 6.19}} La commande |\tabularnote| +admet un argument optionnel (entre crochets) qui permet de changer le symbole de +l'appel de note. + +\emph{Exemple} : |\tabularnote[$\star$]{Une note...}|. \end{itemize} % Voir sur la table \ref{t:tabularnote}, p.~\pageref{t:tabularnote}, certaines de ces @@ -3917,8 +4170,8 @@ remarques illustrĂ©es. Cette table a Ă©tĂ© composĂ©e avec le code suivant \NiceMatrixOptions{caption-above} \begin{NiceTabular}{@{}llc@{}}% [ - caption = Un tableau dont la lĂ©gende a Ă©tĂ© rentrĂ©e avec la clĂ© \texttt{caption} - ~emphase#\tabularnote{On peut mettre une note dans la lĂ©gende.}! , + caption = Un tableau dont la lĂ©gende a Ă©tĂ© rentrĂ©e avec la clĂ© \texttt{caption}% + ~emphase#\tabularnote[$\star$]{On peut mettre une note dans la lĂ©gende.}! , label = t:tabularnote , tabularnote = Un peu de texte avant les notes. , notes/bottomrule @@ -3944,8 +4197,8 @@ Wallis & John & 87 \\ \NiceMatrixOptions{caption-above} \begin{NiceTabular}{@{}llc@{}}% [ - caption = Un tableau dont la lĂ©gende a Ă©tĂ© rentrĂ©e avec la clĂ© \texttt{caption} - \tabularnote{On peut mettre une note dans la lĂ©gende.} , + caption = Un tableau dont la lĂ©gende a Ă©tĂ© rentrĂ©e avec la clĂ© \texttt{caption}% + \tabularnote[$\star$]{On peut mettre une note dans la lĂ©gende.} , label = t:tabularnote, tabularnote = Un peu de texte avant les notes. , notes/bottomrule @@ -3967,9 +4220,18 @@ Wallis & John & 87 \\ - \subsection{Personnalisation des notes de tableau} +\index{para (sous-clĂ© de «notes»)} +\index{bottomrule (sous-clĂ© de «notes»)} +\index{style (sous-clĂ© de «notes»)} +\index{label-in-tabular (sous-clĂ© de «notes»)} +\index{label-in-list (sous-clĂ© de «notes»)} +\index{enumitem-keys (sous-clĂ© de «notes»)} +\index{enumitem-keys-para (sous-clĂ© de «notes»)} +\index{code-before!sous-clĂ© de «notes»} +\index{detect-duplicates (sous-clĂ© de «notes»)} + Les notes de tableau peuvent Ăªtre personnalisĂ©es grĂ¢ce Ă  un ensemble de clĂ©s disponibles dans |\NiceMatrixOptions|. Ces clĂ©s ont un nom prĂ©fixĂ© par |notes| : @@ -3984,7 +4246,7 @@ disponibles dans |\NiceMatrixOptions|. Ces clĂ©s ont un nom prĂ©fixĂ© par |notes \item |notes/code-before| \item |notes/detect-duplicates| \end{itemize} -Pour la commmoditĂ©, il est aussi possible de fixer ces clĂ©s dans +Pour la commoditĂ©, il est aussi possible de fixer ces clĂ©s dans |\NiceMatrixOptions| via une clĂ© |notes| qui prend en argument une liste de paires \textsl{clĂ©=valeur} oĂ¹ le nom des clĂ©s n'a plus Ă  Ăªtre prĂ©fixĂ© par |notes|: @@ -4121,6 +4383,7 @@ commandes |\tabularnote| avec le mĂªme argument. Valeur initiale : |true| \end{itemize} +\index{nota@\textbf{Notes dans les tableaux}|)} \medskip @@ -4129,6 +4392,7 @@ Pour un exemple de personnalisation des notes de tableau, voir p.~\pageref{ex:no \subsection{Utilisation de \{NiceTabular\} avec threeparttable} +\index{threeparttable@\pkg{threeparttable} (extension)} Si vous souhaitez utiliser les environnements |{NiceTabular}|, |{NiceTabular*}| ou |{NiceTabularX}| dans un environnement |{threeparttable}| de l'extension @@ -4141,8 +4405,9 @@ suivant (avec une version de LaTeX postĂ©rieure Ă  2020/10/01). \makeatother \end{Verbatim} -NĂ©anmoins, les fonctionnalitĂ©s proposĂ©es par \pkg{nicematrix} rendent peu -utile l'utilisation de \pkg{threeparttable} en conjonction avec \pkg{nicematrix}. +NĂ©anmoins, les fonctionnalitĂ©s proposĂ©es par \pkg{nicematrix} rendent peu utile +l'utilisation de \pkg{threeparttable} en conjonction avec \pkg{nicematrix} (voir +la clĂ© |caption| Ă  la partie \ref{s:caption}, p.~\pageref{s:caption}). \section{Autres fonctionnalitĂ©s} @@ -4150,6 +4415,8 @@ utile l'utilisation de \pkg{threeparttable} en conjonction avec \pkg{nicematrix} \subsection{La clĂ© rounded-corners de \{NiceTabular\}} \label{tabular-rounded-corners} +\index{rounded-corners!clĂ© de \texttt{\{NiceTabular\}}} +\index{Coins arrondis!pour un tableau} \colorbox{yellow!50}{\textbf{Nouveau 6.18}}\par\nobreak @@ -4198,6 +4465,9 @@ avec des coins arrondis. \subsection{Commande \textbackslash ShowCellNames} +\index{ShowCellNames@\texttt{\textbackslash ShowCellNames} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})} La commande |\ShowCellNames|, utilisable dans le |\CodeBefore| et le |\CodeAfter| affiche le nom (sous la forme $i$-$j$) de chaque case. Quand elle @@ -4225,6 +4495,10 @@ semi-transparent pour estomper le tableau (attention : certains lecteurs de \subsection{Utilisation du type de colonne S de siunitx} + +\index{S (les colonnes S de \pkg{siunitx})} +\index{siunitx@\pkg{siunitx} (extension)} + Si l'extension \pkg{siunitx} est chargĂ©e (avant ou après \pkg{nicematrix}), il est possible d'utiliser les colonnes de type |S| de \pkg{siunitx} dans les environnements de \pkg{nicematrix}. L'implĂ©mentation n'utilise explicitement aucune macro privĂ©e de \pkg{siunitx}. @@ -4256,6 +4530,7 @@ charge par \pkg{nicematrix}. \subsection{Type de colonne par dĂ©faut dans \{NiceMatrix\}} \label{columns-type} +\index{columns-type (clĂ© de \texttt{\{NiceMatrix\}}, etc.)} Les environnements sans prĂ©ambule (|{NiceMatrix}|, |{pNiceMatrix}|, etc.) ainsi que la commande |\pAutoNiceMatrix| et ses variantes, acceptent la clĂ© @@ -4285,6 +4560,7 @@ de la prĂ©fixer par |matrix|, ce qui fait que son nom devient |matrix/columns-ty \subsection{La commande \textbackslash rotate} \label{rotate} +\index{rotate@\texttt{\textbackslash rotate}} UtilisĂ©e au dĂ©but d'une case, la commande |\rotate| (fournie par \pkg{nicematrix}) compose le contenu après une rotation de 90° dans le sens direct. @@ -4318,6 +4594,12 @@ e_1 & e_2 & e_3 \\ \end{varwidth} \medskip +\index{first-row|textit} +\index{last-row|textit} +\index{code-for-first-row|textit} +\index{code-for-last-row|textit} +\index{last-col|textit} +\index{code-for-last-col|textit} Si la commande |\rotate| est utilisĂ©e dans la «dernière rangĂ©e» (extĂ©rieure Ă  la matrice), les Ă©lĂ©ments qui subissent cette rotation sont alignĂ©s vers le haut. @@ -4349,6 +4631,9 @@ $A = \begin{pNiceMatrix}[last-row,last-col=4] \subsection{L'option small} \label{small} +\index{small (clĂ© pour un environnement)} +\index{smallmatrix@\texttt{\{smallmatrix\}} (envionnement de \pkg{amsmath})} + Avec l'option |small|, les environnements de l'extension \pkg{nicematrix} sont composĂ©s d'une manière proche de ce que propose l'environnement |{smallmatrix}| @@ -4401,6 +4686,8 @@ partie \ref{delimiters-in-preamble}, p.~\pageref{delimiters-in-preamble}). \subsection{Les compteurs iRow et jCol} \label{iRow} +\index{iRow (compteur LaTeX)} +\index{jCol (compteur LaTeX)} Dans les cases du tableau, il est possible d'utiliser les compteurs LaTeX |iRow| et |jCol| qui reprĂ©sentent le numĂ©ro de la rangĂ©e courante et le numĂ©ro de la @@ -4444,6 +4731,12 @@ final), ces compteurs sont masquĂ©s dans les environnements de \pkg{nicematrix}. \medskip +\indexcommand{AutoNiceMatrix} +\indexcommand{pAutoNiceMatrix} +\indexcommand{bAutoNiceMatrix} +\indexcommand{vAutoNiceMatrix} +\indexcommand{VAutoNiceMatrix} +\indexcommand{BAutoNiceMatrix} L'extension \pkg{nicematrix} propose aussi des commandes pour composer automatiquement des matrices Ă  partir d'un motif gĂ©nĂ©ral. Ces commandes sont nommĂ©es |\AutoNiceMatrix|, |\pAutoNiceMatrix|, |\bAutoNiceMatrix|, @@ -4460,16 +4753,12 @@ simplement des tokens qui seront insĂ©rĂ©s dans chaque case de la matrice). $C = ~emphase#\pAutoNiceMatrix@{3-3}{C_{\arabic{iRow},\arabic{jCol}}}$ \end{Verbatim} - - - \[C = \pAutoNiceMatrix{3-3}{C_{\arabic{iRow},\arabic{jCol}}}\] - - \subsection{L'option light-syntax} \label{light-syntax} +\index{light-syntax} L'option |light-syntax| (inspirĂ©e de l'extension \pkg{spalign}) permet d'allĂ©ger la saisie des matrices, ainsi que leur lisibilitĂ© dans le source TeX. Lorsque @@ -4498,6 +4787,7 @@ b \cos a+\cos b { 2 \cos b } \end{bNiceMatrix}$ \medskip +\index{end-of-row (Ă  utiliser avec light-syntax)} On peut changer le caractère utilisĂ© pour indiquer les fins de rangĂ©es avec l'option |end-of-row|. Comme dit prĂ©cĂ©demment, la valeur initiale de ce paramètre est un point-virgule. @@ -4514,6 +4804,10 @@ dans les cases du tableau.\footnote{La raison en est que lorsque l'option |light \subsection{Couleur des dĂ©limiteurs} +\index{delimiters!---/color pour un environnement} +\index{color!pour les dĂ©limiteurs de matrices} +\index{Couleur!des dĂ©limiteurs de matrices} + Pour les environnements avec dĂ©limiteurs (|{pNiceArray}|, |{pNiceMatrix}|, etc.), il est possible de changer la couleur des dĂ©limiteurs avec la clĂ© |delimiters/color|. @@ -4532,13 +4826,16 @@ $\begin{bNiceMatrix}[delimiters/color=red] \medskip Cette couleur s'applique aussi aux dĂ©limiteurs tracĂ©s par |\SubMatrix| -(cf.~p.~\pageref{sub-matrix}). +(cf.~p.~\pageref{sub-matrix}) et aux dĂ©limiteurs spĂ©cifiĂ©s directement dans le +prĂ©ambule des environnements Ă  prĂ©ambule (cf.~p.~\pageref{delimiters-in-preamble}). \subsection{L'environnement \{NiceArrayWithDelims\}} \label{NiceArrayWithDelims} +\index{NiceArrayWithDelims@\texttt{\{NiceArrayWithDelims\}}} + En fait, l'environnement |{pNiceArray}| et ses variantes sont fondĂ©s sur un environnement plus gĂ©nĂ©ral, appelĂ© |{NiceArrayWithDelims}|. Les deux premiers arguments obligatoires de cet environnement sont les dĂ©limiteurs gauche et droit @@ -4566,6 +4863,8 @@ $\begin{NiceArrayWithDelims} \subsection{La commande \textbackslash OnlyMainNiceMatrix} +\indexcommand{OnlyMainNiceMatrix} + La commande |\OnlyMainNiceMatrix| n'exĂ©cute son argument que si on se trouve dans le tableau principal, c'est-Ă -dire que l'on n'est pas dans les rangĂ©es extĂ©rieures. Si elle est utilisĂ©e hors d'un environnement de \pkg{nicematrix}, @@ -4577,7 +4876,8 @@ Pour un exemple d'utilisation, voir \url{tex.stackexchange.com/questions/488566} \section{Utilisation de TikZ avec nicematrix} \label{name}\label{PGF-nodes} - +\index{tikza@TikZ (utilisation avec \pkg{nicematrix})} +\index{noeud@\textbf{NÅ“uds PGF/Tikz}|(} \subsection{Les nÅ“uds correspondant aux contenus des cases} @@ -4609,11 +4909,13 @@ Si l'environnement concernĂ© a le numĂ©ro $n$, alors le nÅ“ud de la rangĂ©e~$i$ de la colonne~$j$ a pour nom |nm-|$n$|-|$i$|-|$j$. \smallskip +\indexcommand{NiceMatrixLastEnv} La commande |\NiceMatrixLastEnv| donne le numĂ©ro du dernier de ces environnements (pour LaTeX, il s'agit d'une commande — complètement dĂ©veloppable — et non d'un compteur). \smallskip +\index{name!clĂ© pour un environnement} Il est nĂ©anmoins recommandĂ© de passer plutĂ´t par la clĂ© |name|. Celle-ci permet de donner un nom Ă  l'environnement. Une fois l'environnement nommĂ©, les nÅ“uds sont accessibles Ă  travers les noms «\textsl{nom}-$i$-$j$» oĂ¹ \textsl{nom} est @@ -4723,6 +5025,8 @@ p.~\pageref{triangular}. \subsubsection{La clĂ© pgf-node-code} +\index{pgf-node-code} + \colorbox{yellow!50}{\textbf{Nouveau 6.17}}\enskip \textbf{Pour les utilisateurs expĂ©rimentĂ©s}, \pkg{nicematrix} fournit la clĂ© |pgf-node-code| qui correspond Ă  du code PGF qui sera exĂ©cutĂ© Ă  la crĂ©ation, par PGF, des nÅ“uds correspondants aux @@ -4734,6 +5038,9 @@ contenir au moins une instruction comme |\pgfusepath|, |\pgfusepathqstroke|, \subsubsection{Les colonnes V de varwidth} \label{node-V} +\index{V (les colonnes V de \pkg{varwidth})} +\index{varwidth@\pkg{varwidth} (extension)} + Quand l'extension \pkg{varwidth} est chargĂ©e, les colonnes de type |V| dĂ©finies par \pkg{varwidth} sont prises en charge par \pkg{nicematrix}. Il peut Ăªtre intĂ©ressant de prĂ©ciser que, pour une case situĂ©e dans une colonne de type @@ -4770,6 +5077,9 @@ peu plus loin, p.~\pageref{nodes-i}. \subsection{Les «nÅ“uds moyens» et les «nÅ“uds larges»} +\index{create-medium-nodes} +\index{create-large-nodes} +\index{create-extra-nodes} En fait, l'extension \pkg{nicematrix} peut crĂ©er deux sĂ©ries de nÅ“uds supplĂ©mentaires (\emph{extra nodes} en anglais) : les «nÅ“uds moyens» @@ -4840,6 +5150,8 @@ a & a & a \medskip +\index{left-margin} +\index{right-margin} Les «nÅ“uds larges» de la première colonne et de la dernière colonne peuvent apparaĂ®tre trop petits pour certains usages. C'est pourquoi il est possible d'utiliser les options |left-margin| et |right-margin| pour ajouter de l'espace @@ -4872,6 +5184,8 @@ a & a & a \end{pNiceMatrix}\] \medskip +\index{extra-left-margin} +\index{extra-right-margin} Il est aussi possible d'ajouter de l'espace sur les cĂ´tĂ©s du tableau avec les options |extra-left-margin| et |extra-right-margin|. Ces marges ne sont pas incorporĂ©es dans les «nÅ“uds larges». Dans l'exemple suivant, nous avons utilisĂ© @@ -4978,6 +5292,8 @@ noix & noisette & brugnon Les nÅ“uds que l'on vient de dĂ©crire ne sont pas accessibles par dĂ©faut dans le |\CodeBefore| (dĂ©crit p.~\pageref{code-before}). \par\nobreak + +\index{create-cell-nodes (clĂ© de \texttt{\textbackslash CodeBefore})} On peut rendre ces nÅ“uds accessibles dans le |\CodeBefore| en utilisant la clĂ© |create-cell-nodes| du mot-clĂ© |\CodeBefore| (dans ce cas-lĂ , les nÅ“uds sont crĂ©Ă©s une première fois avant la construction du tableau en utilisant des @@ -5124,13 +5440,19 @@ $\begin{pNiceArray}{ccc|c} \end{pNiceArray}$ -\subsection{Les nÅ“uds correspondants aux commandes \textbackslash SubMatrix} +\subsection{Les nÅ“uds correspondant aux commandes \textbackslash SubMatrix} \label{node-sub-matrix} La commande |\SubMatrix| disponible dans le |\CodeAfter| a Ă©tĂ© prĂ©sentĂ©e p.~\pageref{sub-matrix}. +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})} +\index{name!clĂ© de \texttt{\textbackslash SubMatrix}} + + \smallskip Si une commande |\SubMatrix| est utilisĂ©e avec la clĂ© |name| sous la forme |name=|\textsl{\ttfamily MonNom}, trois nÅ“uds PGF-TikZ sont crĂ©Ă©s avec les noms @@ -5162,9 +5484,14 @@ a Ă©tĂ© crĂ©Ă©e avec |\SubMatrix\{{2-2}{3-3}\}|). \end{tikzpicture} \end{pNiceMatrix}\] +\index{noeud@\textbf{NÅ“uds PGF/Tikz}|)} + \section{API pour les dĂ©veloppeurs} +\indexcommand{g\_nicematrix\_code\_before\_tl} +\indexcommand{g\_nicematrix\_code\_after\_tl} + L'extension \pkg{nicematrix} fournit deux variables internes mais publiques\footnote{ConformĂ©ment aux conventions de LaTeX3, toute variable dont le nom commence par |\g_nicematrix| ou |\l_nicematrix| est publique alors que toute variable dont le nom dĂ©bute par |\g__nicematrix| ou @@ -5187,9 +5514,6 @@ On remarquera que l'utilisation de |\g_nicematrix_code_before_tl| nĂ©cessite une compilation supplĂ©mentaire (car les instructions sont Ă©crites dans le fichier |aux| pour Ăªtre utilisĂ©es Ă  la compilation suivante). - - - \medskip \emph{Exemple} : On souhaite Ă©crire une commande |\crossbox| qui barre en croix la case courante. Cette commande prendra en argument optionnel une liste de @@ -5201,6 +5525,8 @@ On peut alors programmer cette commande |\crossbox| de la manière suivante, qui utilise explicitement la variable publique |\g_nicematrix_code_before_tl|. +\index{crossbox@\texttt{\textbackslash crossbox} (dĂ©finie dans un exemple)|textit} + \begin{scope} \fvset{commandchars=\§\¤\μ} \begin{Verbatim} @@ -5283,6 +5609,9 @@ l'extension \pkg{underscore}. Si elle est chargĂ©e après, une erreur sera levĂ© \subsection{Lignes diagonales} \label{parallelization} +\index{parallelize-diags} +\index{Ddots@\texttt{\textbackslash Ddots}} +\index{Iddots@\texttt{\textbackslash Iddots}} Par dĂ©faut, toutes les lignes diagonales\footnote{On parle des lignes crĂ©Ă©es par |\Ddots| et non des lignes crĂ©Ă©es par une commande |\line| dans le @@ -5295,8 +5624,6 @@ tableau peut avoir un effet marquĂ© sur le rĂ©sultat final. \medskip Dans les exemples suivants, la première instruction |\Ddots| est marquĂ©e en couleur : - - \medskip \begin{scope} \begin{minipage}{9.5cm} @@ -5355,6 +5682,8 @@ a+b & \Cdots & a+b & 1 \end{scope} \medskip +\index{draw-first (clĂ© de \texttt{\textbackslash Ddots} et + \texttt{\textbackslash Iddots})} On peut choisir l'instruction |\Ddots| qui sera tracĂ©e en premier (et qui servira pour tracer les suivantes quand la parallĂ©lisation est activĂ©e) avec la clĂ© |draw-first| : |\Ddots[draw-first]|\rlap{.} @@ -5407,6 +5736,8 @@ lignes en pointillĂ©s par \pkg{nicematrix}. \subsection{L'option exterior-arraycolsep} +\index{exterior-arraycolsep} + L'environnement |{array}| insère un espace horizontal Ă©gal Ă  |\arraycolsep| avant et après chaque colonne. En particulier, il y a un espace Ă©gal Ă  |\arraycolsep| avant et après le tableau. Cette caractĂ©ristique de @@ -5434,6 +5765,7 @@ environnements de l'extension \pkg{nicematrix} ne sont pas affectĂ©s). \subsection{IncompatibilitĂ©s} +\index{IncompatibilitĂ©s} \medskip L'extension \pkg{nicematrix} n'est pas compatible avec la classe \cls{ieeeaccess} @@ -5483,6 +5815,8 @@ on utiliser la colonne |S| de \pkg{siunitx}). \subsection{Utilisation de la clĂ© «tikz» de la commande \textbackslash Block} +\index{tikzz@tikz!clĂ© de \texttt{\textbackslash Block}|textit} + \label{tikz-key-examples} La clĂ© |tikz| de la commande |\Block| n'est disponible que lorsque TikZ est @@ -5529,10 +5863,17 @@ Pour l'exemple suivant, la bibliothèque \pkg{patterns} de TikZ doit aussi Ăªtre \bigskip + Dans l'exemple suivant, on utilise la clĂ© |tikz| pour hachurer une ligne du tableau. On remarquera que l'on utilise la clĂ© |transparent| de la commande -|\Block| pour que les filets soient tracĂ©s dans le bloc.\footnote{Par dĂ©faut, les filets ne sont pas tracĂ©s dans les blocs crĂ©Ă©s avec la commande -\texttt{\textbackslash Block} : cf.~section~\ref{rules} p.~\pageref{rules}} +|\Block| pour que les filets soient tracĂ©s dans le bloc.\footnote{Par dĂ©faut, + les filets ne sont pas tracĂ©s dans les blocs crĂ©Ă©s avec la commande + \texttt{\textbackslash Block} : cf.~section~\ref{rules} p.~\pageref{rules}} + +\index{transparent (clĂ© de \texttt{\textbackslash Block})|textit} +\index{columncolor@\texttt{\textbackslash columncolor}!commande du + \texttt{\textbackslash CodeBefore}|textit} + \begin{Verbatim} \begin{NiceTabular}{ccc}[hvlines] @@ -5560,6 +5901,7 @@ sept & huit & neuf \subsection{Utilisation avec tcolorbox} \label{tcolorbox} +\index{tcolorbox@\pkg{tcolorbox} (extension)|textit} Voici un exemple d'utilisation de |{NiceTabular}| dans une commande |\tcbox| de \pkg{tcolorbox}. On a utilisĂ© la clĂ© |hvlines-except-borders| pour faire afficher @@ -5602,6 +5944,11 @@ tous les filets sauf ceux sur les bords (qui sont, bien entendu, ajoutĂ©s par } \end{BVerbatim} + +\index{hvlines-except-borders|textit} +\index{rules (clĂ© pour un environnement)|textit} +\index{rowcolor@\texttt{\textbackslash rowcolor}!commande du \texttt{\textbackslash CodeBefore}|textit} + \medskip \begin{center} \tcbset @@ -5643,6 +5990,13 @@ tous les filets sauf ceux sur les bords (qui sont, bien entendu, ajoutĂ©s par \subsection{Notes dans les tableaux} +\index{nota@\textbf{Notes dans les tableaux}|textit} +\index{tabularnote@\texttt{\textbackslash tabularnote}|textit} +\index{notes (clĂ© pour paramĂ©trer les notes de\newline tableau)|textit} +\index{style (sous-clĂ© de «notes»)|textit} +\index{enumitem-keys (sous-clĂ© de «notes»)|textit} +\index{enumitem@\pkg{enumitem} (extension requise pour utiliser\newline \texttt{\textbackslash tabularnote})|textit} + \label{ex:notes} Les outils de \pkg{nicematrix} pour les notes dans les tableaux ont Ă©tĂ© @@ -5744,6 +6098,9 @@ Dupont & Chantal & 15 janvier 1998 \\ \subsection{Lignes en pointillĂ©s} +\index{PointillĂ©s@\textbf{PointillĂ©s (lignes en ---)}|textit} + + Un exemple pour le rĂ©sultant de deux polynĂ´mes : \par\nobreak \medskip @@ -5760,6 +6117,9 @@ a_p & &&a_0 & & &b_1 \\ \end{vNiceArray} \end{BVerbatim} + +\index{Ddots@\texttt{\textbackslash Ddots}|textit} + \medskip \begin{scope} @@ -5778,6 +6138,9 @@ a_p & &&a_0 & & &b_1 \\ \vspace{2cm} Un exemple avec un système linĂ©aire: +\index{last-col|textit} +\index{code-for-last-col|textit} + \begin{Verbatim} $\begin{pNiceArray}{*6c|c}[nullify-dots,last-col,code-for-last-col=\scriptstyle] 1 & 1 & 1 &\Cdots & & 1 & 0 & \\ @@ -5808,8 +6171,7 @@ L'option |line-style| permet de changer le style des lignes tracĂ©es par |\Ldots|, |\Cdots|, etc. On peut de ce fait tracer des lignes qui ne sont plus pointillĂ©es. - - +\index{line-style (clĂ© pour les lignes pointillĂ©es)|textit} \begin{Verbatim}[formatcom=\small\color{gray}] \NiceMatrixOptions{code-for-first-row = \scriptstyle,code-for-first-col = \scriptstyle } @@ -5832,6 +6194,8 @@ pointillĂ©es. \end{pNiceMatrix}\] \end{Verbatim} +\index{code-for-first-row|textit} +\index{code-for-last-col|textit} \begin{scope} \NiceMatrixOptions{code-for-first-row = \scriptstyle,code-for-first-col = \scriptstyle } @@ -5893,6 +6257,8 @@ $\begin{pNiceMatrix}[first-row,first-col] \label{tiretes} +\index{tikzz@tikz!clĂ© de «borders» de \texttt{\textbackslash Block}|textit} + Dans l'exemple suivant, on utilise des commandes |\Block| pour tracer des filets en tiretĂ©s. Cet exemple nĂ©cessite que TikZ soit chargĂ© (par |\usepackage{tikz}|). @@ -5937,6 +6303,8 @@ Pour avoir les colonnes alignĂ©es les unes sous les autres, on peut imposer une largeur commune Ă  toutes les colonnes, ce que l'on fait dans l'exemple suivant avec l'environnement |{NiceMatrixBlock}| et l'option |auto-columns-width|. +\index{NiceMatrixBlock@\texttt{\{NiceMatrixBlock\}}|textit} + \begin{Verbatim}[formatcom=\small\color{gray}] ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@ \NiceMatrixOptions @@ -5978,6 +6346,7 @@ $\begin{pNiceArray}{rrrr|r} \end{Verbatim} \medskip +\index{auto-columns-width!(clĂ© de \texttt{\{NiceMatrixBlock\}})|textit} \begin{NiceMatrixBlock}[auto-columns-width] \NiceMatrixOptions { @@ -6021,6 +6390,8 @@ prĂ©cĂ©dentes. C'est que les parenthèses, en LaTeX, n'ont pas toutes la mĂªme largeur suivant leur taille. \medskip +\index{max-width (sous-clĂ© de «delimiters»)} +\index{delimiters!---/max-width} Pour rĂ©soudre ce problème, on peut demander que les dĂ©limiteurs soient composĂ©s avec leur largeur maximale grĂ¢ce Ă  la clĂ© boolĂ©enne |delimiters/max-width|. @@ -6093,6 +6464,9 @@ et placer les parenthèses avec des commandes |\SubMatrix| dans le |\CodeAfter|. Bien sĂ»r, ce tableau ne pourra pas Ăªtre coupĂ© par un saut de page. \medskip +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})|textit} \begin{Verbatim} \setlength{\extrarowheight}{1mm} \[\begin{NiceMatrix}% @@ -6150,6 +6524,7 @@ composition du tableau et les traits verticaux sont donc tracĂ©s sans espacer le colonnes. \medskip +\index{vlines-in-sub-matrix} En fait, on peut avec la clĂ© |vlines-in-sub-matrix| choisir un spĂ©cificateur dans le prĂ©ambule du tableau pour indiquer des filets verticaux qui seront tracĂ©s dans les |\SubMatrix| uniquement (en espaçant les colonnes). @@ -6224,6 +6599,7 @@ tracĂ©s dans les |\SubMatrix| uniquement (en espaçant les colonnes). \subsection{Comment surligner les cases d'une matrice} \label{highlight} +\index{draw (clĂ© de \texttt{\textbackslash Block})|textit} \medskip Pour mettre en Ă©vidence une case d'une matrice, il est possible de «dessiner» @@ -6263,6 +6639,9 @@ Il est possible de colorier une rangĂ©e avec |\rowcolor| dans le |\CodeBefore| |colortbl-like| − mĂªme si \pkg{colortbl} n'est pas chargĂ©). +\index{colortbl-like|textit} +\index{rowcolor@\texttt{\textbackslash rowcolor}!commande en tableau|textit} + \begin{Verbatim} \begin{pNiceArray}{>{\strut}cccc}[margin, extra-margin=2pt,colortbl-like] ~emphase#\rowcolor{red!15}@A_{11} & A_{12} & A_{13} & A_{14} \\ @@ -6311,6 +6690,7 @@ faut utiliser la clĂ© |create-cell-nodes| du |\CodeBefore| pour demander leur cr fit=#1}} \medskip +\index{highlight (style TikZ dĂ©fini dans\newline un exemple)|textit} \begin{Verbatim} \tikzset{highlight/.style={rectangle, fill=red!15, @@ -6328,6 +6708,9 @@ $\begin{bNiceMatrix} \end{bNiceMatrix}$ \end{Verbatim} +\index{create-cell-nodes (clĂ© de \texttt{\textbackslash CodeBefore})|textit} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}|textit} + \[\begin{bNiceMatrix} \CodeBefore [create-cell-nodes] \tikz \node [highlight = (2-1) (2-3)] {} ; @@ -6376,6 +6759,9 @@ a & a & a & L_3 Le rĂ©sultat peut paraĂ®tre dĂ©cevant. On peut l'amĂ©liorer en utilisant les «nÅ“uds moyens» au lieu des «nÅ“uds normaux». +\index{create-medium-nodes|textit} +\index{create-cell-nodes (clĂ© de \texttt{\textbackslash CodeBefore})|textit} + \begin{Verbatim} \[\begin{pNiceArray}{ccc}[last-col, margin = 2pt, create-medium-nodes] \CodeBefore [create-cell-nodes] @@ -6409,6 +6795,13 @@ a & a & a & L_3 \subsection{Utilisation de \textbackslash SubMatrix dans le \textbackslash CodeBefore} +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (commande du +\texttt{\textbackslash CodeAfter}\newline et du +\texttt{\textbackslash CodeBefore})|textit} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}|textit} +\index{CodeAfter@\texttt{\textbackslash CodeAfter}|textit} +\index{create-cell-nodes (clĂ© de \texttt{\textbackslash CodeBefore})|textit} + \label{submatrix-in-codebefore} @@ -6493,6 +6886,11 @@ de parenthèses ont Ă©tĂ© rajoutĂ©es avec |\SubMatrix| dans le |\CodeBefore|. \subsection{Un tableau triangulaire} \label{triangular} +\index{pgf-node-code|textit} +\index{Coins (les --- vides)|textit} +\index{chessboardcolors@\texttt{\textbackslash chessboardcolors}!(commande + du \texttt{\textbackslash CodeBefore})|textit} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}|textit} Dans l'exemple suivant, on utilise le style PGF/Tikz |nicematrix/cell-node| pour faire tourner le contenu des cases (rotation que l'on compense ensuite en faisant @@ -6549,13 +6947,21 @@ qui doit donc Ăªtre chargĂ©e prĂ©alablement). \end{NiceTabular}} \end{center} +\cleardoublepage +\phantomsection +\addcontentsline{toc}{section}{Index} + +\printindex \section*{Autre documentation} Le document |nicematrix.pdf| (fourni avec l'extension \pkg{nicematrix}) contient -une traduction anglaise de la documentation ici prĂ©sente, ainsi que le code -source commentĂ© et un historique des versions. +une traduction anglaise de la documentation ici prĂ©sente ainsi qu'un historique +des versions. + +Le document |nicematrix-code.pdf| (fourni Ă©galement avec l'extension \pkg{nicematrix} +contient le code LaTeX commentĂ© (Ă  partir du fichier |nicematrix-code.dtx|). \medskip Les versions successives du fichier |nicematrix.sty| fournies par diff --git a/macros/latex/contrib/nicematrix/nicematrix.dtx b/macros/latex/contrib/nicematrix/nicematrix.dtx deleted file mode 100644 index c22ed30da1..0000000000 --- a/macros/latex/contrib/nicematrix/nicematrix.dtx +++ /dev/null @@ -1,23021 +0,0 @@ -% \iffalse meta-comment -% -% This file should be compiled with $xelatex$. -% -% Copyright (C) 2018-2023 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.18} -\def\myfiledate{2023/04/19} -% -% -%<*batchfile> -\begingroup -\input l3docstrip.tex -\keepsilent -\usedir{tex/latex/nicematrix} -\preamble - - -Copyright (C) 2018-2023 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,arrows.meta,decorations.pathmorphing} -\usepackage{nicematrix} -\usepackage{siunitx} -\usepackage{caption} -\usepackage{varwidth} -\usepackage{tcolorbox} -\usepackage{adjustbox} -\usepackage[auto-lang=false]{lipsum} - -\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{footnotehyper} -\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, TeX Live or MacTeX. -% -% \medskip -% \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}} -% -% \medskip -% 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.} -% -% \medskip -% 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}|. -% -% -% \medskip -% 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.} -% -% \medskip -% Most features of \pkg{nicematrix} may be used without explicit use of -% \textsc{pgf} or Tikz (which, in fact, is not loaded by default). -% -% \medskip -% 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 -% The environment |{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 environment |{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} -% \frac{1}{2} & -\frac{1}{2} \\ -% \frac{1}{3} & \frac{1}{4} \\ -% \end{pmatrix}$ -% \end{BVerbatim} -% $\begin{pmatrix} -% \frac{1}{2} & -\frac{1}{2} \\ -% \frac{1}{3} & \frac{1}{4} \\ -% \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]@ -% \dfrac{1}{A} & \dfrac{1}{B} & 0 & 0 \\ -% \dfrac{1}{C} & \dfrac{1}{D} & 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] -% \dfrac{1}{A} & \dfrac{1}{B} & 0 & 0 \\ -% \dfrac{1}{C} & \dfrac{1}{D} & 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}|, -% |{NiceTabular*}| and |{NiceTabularX}|, 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}{cw{c}{1cm}c|c}[margin] -% ~emphase#\Block{3-3}{A}@ & & & 0 \\ -% & & & \Vdots \\ -% & & & 0 \\ -% \hline -% 0 & \Cdots& 0 & 0 -% \end{bNiceArray}$ -% \end{BVerbatim} -% $\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] -% \Block{3-3}{A} & & & 0 \\ -% & & & \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}{cw{c}{1cm}c|c}[margin] -% \Block{3-3}~emphase#<\Large>@{A} & & & 0 \\ -% 0 & & & \Vdots \\ -% & & & 0 \\ -% \hline -% 0 & \Cdots& 0 & 0 -% \end{bNiceArray}$ -% \end{BVerbatim} -% \begin{scope} -% $\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] -% \Block{3-3}<\Large>{A} & & & 0 \\ -% & & & \Vdots \\ -% & & & 0 \\ -% \hline -% 0 & \Cdots& 0 & 0 -% \end{bNiceArray}$ -% \end{scope} -% -% \NewDocumentCommand{\Definition}{m} -% {{\setlength{\fboxsep}{1pt}\colorbox{gray!20}{\ttfamily \vphantom{gl}#1}}} -% -% -% \interitem -% In fact, the command |\Block| accepts as first optional argument (between -% square brackets) a list of couples \textsl{key=value}. The available keys are as -% follows: -% \begin{itemize} -% \item the key \Definition{fill} takes in as value a color and fills the block -% with that color; -% \item the key \Definition{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 \Definition{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 keys \Definition{hlines}, \Definition{vlines} and -% \Definition{hvlines} draw all the corresponding rules in the -% block;\footnote{However, the rules are not drawn in the sub-blocks of the -% block, as always with \pkg{nicematrix}: the rules are not drawn in the blocks -% (cf. section~\ref{rules} p.~\pageref{rules}).} -% \item the key \Definition{line-width} is the width of the rules (is relevant -% only when one of the keys |draw|, |hvlines|, |vlines| and |hlines| is used); -% \item the key \Definition{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 when the key \Definition{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}; -% \item the key \Definition{name} provides a name to the rectangular Tikz node -% corresponding to the block; it's possible to use that name with Tikz in the -% |\CodeAfter| of the environment (cf.~p.~\pageref{code-after}); -% \item the key \Definition{respect-arraystretch} prevents the setting of -% |\arraystretch| to $1$ at the beginning of the block (which is the behaviour -% by default) ; -% \item the key \Definition{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|; it's possible, in -% fact, in the list which is the value of the key |borders|, to add an entry of -% the form |tikz={|\textsl{list}|}| where \textsl{list} is a list of couples -% \textsl{key=value} of Tikz specifying the graphical characteristics of the -% lines that will be drawn (for an example, see p.~\pageref{dashed}). -% \item \colorbox{yellow!50}{\textbf{New 6.15}}\par\nobreak -% By default, the rules are not drawn in the blocks (see the section about the -% rules: section~\ref{rules} p.~\pageref{rules}). However, if the key -% \Definition{transparent} is used, the rules are drawn. For an example, see -% section~\ref{tikz-key-examples} on page~\pageref{tikz-key-examples}. -% \end{itemize} -% -% There is also keys for the horizontal and vertical positions of the content of -% the block: cf.~\ref{horizontal-block} p.~\pageref{horizontal-block}. -% -% \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 |w{c}{...}| of \pkg{array}). -% -% \bigskip -% \begin{BVerbatim} -% \begin{NiceTabular}{cw{c}{2cm}w{c}{3cm}c} -% rose & tulip & daisy & dahlia \\ -% violet -% & ~emphase#\Block[draw=red,fill=[RGB]{204,204,255},rounded-corners]{2-2}@ -% ~emphase#{\LARGE Some beautiful flowers}@ -% & & marigold \\ -% iris & & & lis \\ -% arum & periwinkle & forget-me-not & hyacinth -% \end{NiceTabular} -% \end{BVerbatim} -% -% \medskip -% \begin{center} -% \begin{NiceTabular}{cw{c}{2cm}w{c}{3cm}c} -% rose & tulip & daisy & dahlia \\ -% violet & \Block[draw=red,fill=[RGB]{204,204,255},rounded-corners]{2-2} -% {\LARGE Some beautiful flowers} & & marigold \\ -% iris & & & lis \\ -% arum & periwinkle & forget-me-not & hyacinth -% \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. -% -% In the columns with a fixed width (columns |w{...}{...}|, |W{...}{...}|, -% |p{...}|, |b{...}|, |m{...}|, |V| 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 (but the -% |\Block| may have its own specification of alignment: -% cf.~\ref{horizontal-block} p.~\pageref{horizontal-block}). -% -% \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} -% -% \label{horizontal-block} -% -% The command |\Block| accepts the keys |l|, |c| and |r| for the horizontal -% position of its content. -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] -% $\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] -% \Block~emphase#[r]@{3-3}<\LARGE>{A} & & & 0 \\ -% & & & \Vdots \\ -% & & & 0 \\ -% \hline -% 0 & \Cdots& 0 & 0 -% \end{bNiceArray}$ -% \end{BVerbatim} -% $\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] -% \Block[r]{3-3}<\LARGE>{A} & & & 0 \\ -% & & & \Vdots \\ -% & & & 0 \\ -% \hline -% 0 & \Cdots& 0 & 0 -% \end{bNiceArray}$ -% -% -% \medskip -% 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|. -% -% \medskip -% Here is the same example with the key |C| for the first block. -% -% \medskip -% \begin{center} -% \fvset{commandchars=\~\#\+} -% \begin{BVerbatim} -% \begin{NiceTabular}{@{}c!{\qquad}ccc~emphase#!{\qquad}+ccc@{}} -% \toprule -% Rank & ~emphase#\Block[C]{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[C]{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} -% -% -% \subsection{Vertical position of the content of the block} -% -% -% For the vertical position, the command |\Blocks| accepts the keys -% |v-center|\footnote{That key could not have been named |c| since the key |c| -% is used for the horizontal alignement.}, -% |t|, |b|, |T| and |B|. -% -% \begin{itemize} -% \item With the key |v-center|, the content of the block is vertically -% centered. -% \item With the key |t|, the baseline of the content of the block is aligned -% With the basline of the first row concerned by the block). -% \item with the key |b|, the baseline of the last row of the content of the -% block (we recall that the content of a block may contains several lines -% separated by |\\|) is aligned with the baseline of the last of the rows of the -% array involved in the block. -% \item With the key |T|, the content of the block is set upwards. -% -% \colorbox{yellow!50}{\textbf{Modification 6.18}}\enskip No vertical margin is -% added. However, the contents of the block is (always) composed by -% \pkg{nicematrix} in a |{minipage}|, a |{tabular}| or an |{array}| and, hence, -% there will still remain a margin (in most cases). -% -% \item With the key |B|, the content of the block is set downwards. -% \end{itemize} -% -% When no key is given, the key |v-center| applies (excepted in the mono-row blocks). -% -% -% -% \medskip -% \begin{scope} -% \NiceMatrixOptions{rules/color=[gray]{0.75}, hvlines} -% -% \begin{BVerbatim} -% \NiceMatrixOptions{rules/color=[gray]{0.75}, hvlines} -% \end{BVerbatim} -% -% \bigskip -% -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,~emphase#t@,l]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,t,l]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% -% -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,~emphase#b@,r]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,b,r]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,~emphase#T@,l]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,T,l]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% -% -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,~emphase#B@,r]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc} -% \Block[fill=red!10,B,r]{4-2}{two\\lines} -% & & \Huge Un\\ -% & & deux \\ -% & & trois \\ -% & & \Huge quatre \\ -% text & text \\ -% \end{NiceTabular} -% -% -% \end{scope} -% -% -% -% -% \section{The rules} -% -% \label{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 the package~\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}) nor in the potential exterior rows (created by the -% keys |first-row| and |last-row|: cf.~p.~\pageref{exterior}). -% -% \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} -% -% -% \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}@ -% 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} -% A&B&C&D \\ -% \hline -% \end{NiceTabular} -% \end{scope} -% -% \medskip -% In the environments of \pkg{nicematrix}, an instruction |\cline{|\textsl{\texttt{i}}|}| -% is equivalent to |\cline{|\textsl{\texttt{i}}|-|\textsl{\texttt{i}}|}|. -% -% -% \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} -% -% -% -% \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), nor in the exterior rows and -% columns.} -% \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}). -% \item For the exterior rows and columns, see~p.~\pageref{exterior}. -% \end{itemize} -% -% In particular, this remark explains the difference between the standard -% command |\hline| and the command |\Hline| provided by \pkg{nicematrix}. -% -% The key |\Hline| takes in an optional argument (between square brackets) which -% is a list of \textsl{key=value} pairs. For the description of those keys, see -% |custom-line| on p.~\pageref{custom-line}. -% -% \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.\footnote{It's possible to put in that list some intervals of integers -% with the syntax $i$|-|$j$.} -% -% 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 -% It's worth noting that, when the key |rounded-corners| is used for the -% environment |{NiceTabular}|, the key |hvlines| draws rounded corners for the -% exterior frame of the tabular: cf. part~\ref{tabular-rounded-corners}, -% p.~\pageref{tabular-rounded-corners}. -% -% \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. For an -% example of use of that key, see the part ``Use with tcolorbox'', -% p.~\pageref{tcolorbox}. -% -% \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. The precise definition of a ``non-empty cell'' is given below (cf. -% p.~\pageref{empty-cells}).} -% -% However, it's possible, for a cell without content, to require \pkg{nicematrix} -% 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|\footnote{The key \texttt{corners} that we describe now -% has no direct link with the key \texttt{rounded-corners} described in the part -% \ref{tabular-rounded-corners}, p.~\pageref{tabular-rounded-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). -% -% \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. -% -% \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{Commands for customized rules} -% \label{custom-line} -% -% It's also possible to define commands and letters for customized rules with -% the key |custom-line| available in |\NiceMatrixOptions| and in the options of -% individual environments. That key takes in as argument a list of -% \textsl{key=value} pairs. First, there is three keys to define the tools which -% will be used to use that new type of rule. -% -% \begin{itemize} -% \item the key |command| is the name (without the backslash) of a command that -% will be created by \pkg{nicematrix} and that will be available for the final -% user in order to draw horizontal rules (similarly to |\hline|); -% -% \item the key |ccommand| is the name (without the backslash) of a command -% that will be created by \pkg{nicematrix} and that will be available for the -% final user to order to draw partial horizontal rules (similarly to |\cline|, -% hence the name |ccommand|): the argument of that command is a list of -% intervals of columns specified by the syntax~$i$ or $i$-$j$.\footnote{It's -% recommended to use such commands only once in a row because each use will -% create space between the rows corresponding to the total width of the rule.} -% -% \item the key |letter| takes in as argument a letter\footnote{The following -% letters are forbidden: \verb+lcrpmbVX|()[]!@<>+} that the user will use in -% the preamble of an environment with preamble (such as |{NiceTabular}| in order -% to specify a vertical rule. -% \end{itemize} -% -% \bigskip -% We will now speak of the keys which describe the rule itself. Those keys may -% also be used in the (optional) argument of an individual command |\Hline|. -% -% There is three possibilities. -% -% \begin{itemize} -% \item \emph{First possibility}\par\nobreak -% -% It's possible to specify composite rules, with a color and a color for the -% inter-rule space (as possible with \pkg{colortbl} for instance). -% -% \begin{itemize} -% \item the key |multiplicity| is the number of consecutive rules that will be -% drawn: for instance, a value of $2$ will create double rules such those -% created by |\hline\hline| or \verb+||+ in the preamble of an environment; -% -% \item the key |color| sets the color of the rules ; -% -% \item the key |sep-color| sets the color between two successive rules (should be -% used only in conjonction with |multiplicity|). -% \end{itemize} -% -% \medskip -% That system may be used, in particular, for the definition of commands and -% letters to draw rules with a specific color (and those rules will respect the -% blocks and corners as do all the rules of \pkg{nicematrix}). -% -% \medskip -% \begin{Verbatim} -% \begin{NiceTabular}{lcIcIc}~emphase#[custom-line = {letter=I, color=blue}]@ -% \hline -% & \Block{1-3}{dimensions} \\ -% & L & l & h \\ -% \hline -% Product A & 3 & 1 & 2 \\ -% Product B & 1 & 3 & 4 \\ -% Product C & 5 & 4 & 1 \\ -% \hline -% \end{NiceTabular} -% \end{Verbatim} -% -% -% \bigskip -% \item \emph{Second possibility}\par\nobreak -% -% It's possible to use the key |tikz| (if Tikz is loaded). In that case, the -% rule is drawn directly with Tikz by using as parameters the value of the key -% |tikz| which must be a list of \textsl{key=value} pairs which may be applied -% to a Tikz path. -% -% By default, no space is reserved for the rule that will be drawn with Tikz. It -% is possible to specify a reservation (horizontal for a vertical rule and -% vertical for an horizontal one) with the key |total-width|. That value of that -% key, is, in some ways, the width of the rule that will be drawn -% (\pkg{nicematrix} does not compute that width from the characteristics of the -% rule specified in |tikz|). -% -% -% \begin{center} -% \begin{NiceTabular}{lcIcIc}[custom-line = {letter=I, color=blue}] -% \hline -% & \Block{1-3}{dimensions} \\ -% & L & l & H \\ -% \hline -% Product A & 3 & 1 & 2 \\ -% Product B & 1 & 3 & 4 \\ -% Product C & 5 & 4 & 1 \\ -% \hline -% \end{NiceTabular} -% \end{center} -% -% \bigskip -% Here is an example with the key |dotted| of Tikz. -% -% \begin{BVerbatim}[boxwidth=9cm,baseline=c] -% \NiceMatrixOptions -% { -% custom-line = -% { -% letter = I , -% ~emphase#tikz = dotted@ , -% ~emphase#total-width = \pgflinewidth@ -% } -% } -% -% \begin{NiceTabular}{cIcIc} -% one & two & three \\ -% four & five & six \\ -% seven & eight & nine -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{scope} -% \NiceMatrixOptions -% { -% custom-line = -% { -% letter = I , -% tikz = dotted , -% total-width = \pgflinewidth -% } -% } -% \begin{NiceTabular}{cIcIc} -% one & two & three \\ -% four & five & six \\ -% seven & eight & nine -% \end{NiceTabular} -% \end{scope} -% -% \bigskip -% \item \emph{Third possibility} : the key |dotted| -% \label{dotted} -% -% As one can see, the dots of a dotted line of Tikz have the shape of a square, -% and not a circle. That's why the extension \pkg{nicematrix} provides in the -% key |custom-line| a key |dotted| which will draw rounded dots. The initial -% value of the key |total-width| is, in this case, equal to the diameter of the dots -% (but the user may change the value with the key |total-width| if needed). Those -% dotted rules are also used by \pkg{nicematrix} to draw continuous dotted rules -% between cells of the matrix with |\Cdots|, |\Vdots|, etc. (cf. p.~\pageref{Cdots}). -% -% In fact, \pkg{nicematrix} defines by default the commands |\hdottedline| and -% |\cdottedline |and the letter ``|:|'' for those dotted -% rules.\footnote{However, it's possible to overwrite those definitions with a -% |custom-line| (in order, for example, to switch to dashed lines).} -% -%\smallskip -%\begin{BVerbatim} -% -% \NiceMatrixOptions % ~textsl#present in nicematrix.sty@ -% { -% custom-line = -% { -% letter = : , -% command = hdottedline , -% ccommand = cdottedline , -% ~emphase#dotted@ -% } -% } -% \end{BVerbatim} -% -% Thus, it's possible to use the commands |\hdottedline| and |\cdottedline |to -% draw horizontal dotted rules. -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=9.5cm] -% \begin{pNiceMatrix} -% 1 & 2 & 3 & 4 & 5 \\ -% ~emphase#\hdottedline@ -% 6 & 7 & 8 & 9 & 10 \\ -% ~emphase#\cdottedline{1,4-5}@ -% 11 & 12 & 13 & 14 & 15 -% \end{pNiceMatrix} -% \end{BVerbatim} -% $\begin{pNiceMatrix} -% 1 & 2 & 3 & 4 & 5 \\ -% \hdottedline -% 6 & 7 & 8 & 9 & 10 \\ -% \cdottedline{1,4-5} -% 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)$ -% -% \end{itemize} -% -% -% -%\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#options@]@ -% ~textsl#instructions of the code-before@ -% ~emphase#\Body@ -% ~textsl#contents of the environment@ -% \end{pNiceArray} -% \end{Verbatim} -% -% \smallskip -% The optional argument between square brackets is a list of \textsl{key=value} -% pairs which will be presented progressively in this -% documentation.\footnote{The available keys are |create-cell-nodes|, -% |sub-matrix| (and its subkeys) and \texttt{delimiters-color}.} -% -% \medskip -% 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 -% These commands don't color the cells which are in the ``corners'' if the key -% |corners| is used. That key has been described p.~\pageref{corners}. -% -% \medskip -% These commands respect the rounded corners if the key |rounded-corners| -% (described in the part \ref{tabular-rounded-corners} at the -% page~\pageref{tabular-rounded-corners}) has been used. -% -% \medskip -% All these commands accept an optional argument, between square brackets and -% in first position. That optional argument may contain two elements (separated -% by a comma) -% \begin{itemize} -% \item the colorimetric space (|RGB|, |rgb|, |HTML|, etc) as specified by the -% the extension \pkg{xcolor}; -% \item \colorbox{yellow!50}{\textbf{New 6.18}}\par\nobreak -% a specification of opacity f the form \texttt{opacity = \textsl{value}}. -% \end{itemize} -% -% \bigskip -% -% We describe now in detail those commands. -% -% \medskip -% \begin{itemize} -% \item The command \Definition{\textbackslash 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. In fact, despite its name, this command may -% be used to color a whole row (with the syntax $i$-) or a whole column (with the -% syntax -$j$). -% -% \medskip -% \begin{scope} -% \hfuzz=10cm -% \begin{BVerbatim}[boxwidth=10cm,baseline=c] -% \begin{NiceTabular}{ccc}[hvlines] -% \CodeBefore -% ~emphase#\cellcolor[HTML]{FFFF88}{3-1,2-2,-3}@ -% \Body -% a & b & c \\ -% e & f & g \\ -% h & i & j \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc}[hvlines] -% \CodeBefore -% \cellcolor[HTML]{FFFF88}{3-1,2-2,-3} -% \Body -% a & b & c \\ -% e & f & g \\ -% h & i & j \\ -% \end{NiceTabular} -% \end{scope} -% -% \bigskip -% \item The command \Definition{\textbackslash 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}{ccc}[hvlines] -% \CodeBefore -% ~emphase#\rectanglecolor{blue!15}{2-2}{3-3}@ -% \Body -% a & b & c \\ -% e & f & g \\ -% h & i & j \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc}[hvlines] -% \CodeBefore -% \rectanglecolor{blue!15}{2-2}{3-3} -% \Body -% a & b & c \\ -% e & f & g \\ -% h & i & j \\ -% \end{NiceTabular} -% \end{scope} -% -% \bigskip -% \item The command \Definition{\textbackslash 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 \Definition{\textbackslash 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{columns-width}). -% -% -% \bigskip -% \item The command \Definition{\textbackslash 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 \Definition{\textbackslash columncolor} takes its name from -% the command |\columncolor| of \pkg{colortbl}. Its syntax is similar to the -% syntax of |\rowcolor|. -% -% \bigskip -% \item The command \Definition{\textbackslash rowcolors} (with a \emph{s}) -% takes its name from the command |\rowcolors| of \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 two 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 -% \textsl{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 The extension \pkg{nicematrix} provides also a command -% \Definition{\textbackslash 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. -% -% \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} -% -% \bigskip -% It's also possible to use in the command |\rowlistcolors| a color series -% defined by the command |\definecolorseries| of \pkg{xcolor} (and initialized -% with the command |\resetcolorseries|\footnote{For the initialization, in the -% following example, you have used the counter |iRow| which, when used in the -% |\CodeBefore| (and in the |\CodeAfter|) corresponds to the number of rows of -% the array: cf.~p~\pageref{iRow}. That leads to an adjustement of the gradation -% of the colors to the size of the tabular.}). -% -% \smallskip -% \begin{BVerbatim}[boxwidth=12.5cm,baseline=c] -% \begin{NiceTabular}{c} -% \CodeBefore -% ~emphase#\definecolorseries{BlueWhite}{rgb}{last}{blue}{white}@ -% ~emphase#\resetcolorseries{\value{iRow}}{BlueWhite}@ -% ~emphase#\rowlistcolors{1}{BlueWhite!!+}@ -% \Body -% Peter \\ -% James \\ -% Abigail \\ -% Elisabeth \\ -% Claudius \\ -% Jane \\ -% Alexandra \\ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{c} -% \CodeBefore -% \definecolorseries{BlueWhite}{rgb}{last}{blue}{white} -% \resetcolorseries[\value{iRow}]{BlueWhite} -% \rowlistcolors{1}{BlueWhite!!+} -% \Body -% Peter \\ -% James \\ -% Abigail \\ -% Elisabeth \\ -% Claudius \\ -% Jane \\ -% Alexandra \\ -% \end{NiceTabular} -% \end{itemize} -% -% \vspace{1cm} -% 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 \emph{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;\footnote{However, this command -% |\cellcolor| will delete the following spaces, which does not the command -% |\cellcolor| of \pkg{colortbl}.} -% \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} -% -% \smallskip -% \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} -% -% 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 \textsl{key=value} pairs. -% \begin{itemize} -% \item The key |nb-rows| sets -% the number of rows to which the specifications of the current command will -% apply (with the special value |*|, it will apply to all the following rows). -% \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 The key |rowcolor| sets -% the color of the background and 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|, |X| and |V| (which start in -% vertical mode).} -% \item The key |bold| enforces -% bold characters for the cells of the row, both in math and text mode. -% \end{itemize} -% -% \medskip -% \begin{BVerbatim}[boxwidth=12cm,baseline=c] -% \begin{NiceTabular}{cccc} -% \hline -% ~emphase#\RowStyle[cell-space-limits=3pt]{\rotate}@ -% first & second & third & fourth \\ -% ~emphase#\RowStyle[nb-rows=2,rowcolor=blue!50,color=white]{\sffamily}@ -% 1 & 2 & 3 & 4 \\ -% I & II & III & IV -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{cccc} -% \hline -% \RowStyle[cell-space-limits=3pt]{\rotate} -% first & second & third & fourth \\ -% \RowStyle[nb-rows=2,rowcolor=blue!50,color=white]{\sffamily} -% 1 & 2 & 3 & 4 \\ -% I & II & III & IV \\ -% \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#W{c}{2cm}@cc}[hvlines] -% Paris & New York & Madrid \\ -% Berlin & London & Roma \\ -% Rio & Tokyo & Oslo -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{W{c}{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} -% -% 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| (in -% |{NiceTabular}| or in |\NiceMatrixOptions|). The initial value of this -% parameter is |\linewidth| (and not |\textwidth|). -% -% For sake of similarity with the environment |{tabularx}|, \pkg{nicematrix} -% also provides an environment |{NiceTabularX}| with a syntax similar to the -% syntax of |{tabularx}|, that is to say with a first mandatory argument -% which is the width of the tabular.\footnote{If \pkg{tabularx} is loaded, one -% must use |{NiceTabularX}| (and not |{NiceTabular}|) in order to use the -% columns |X| (this point comes from a conflict in the definitions of the -% specifier |X|).} -% -% As with the packages \pkg{tabu}\footnote{The extension \pkg{tabu} is now -% considered as deprecated.} 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 a positive -% 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$).\footnote{The negative values of the weight, as provided -% by \pkg{tabu} (which is now obsolete), are \emph{not} supported by \pkg{nicematrix}. -% If such a value is used, an error will be raised.} -% \item It's possible to specify an horizontal alignment with one of the -% letters |l|, |c| and |r| (which insert respectively |\raggedright|, -% |\centering| and |\raggedleft| followed by |\arraybackslash|). -% \item It's possible to specify a vertical alignment 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} -% -% -% \subsection{The columns V of varwidth} -% -% \label{varwidth} -% -% Let's recall first the behaviour of the environment |{varwidth}| of the -% eponymous package \pkg{varwidth}. That environment is similar to the classical -% environment |{minipage}| but the width provided in the argument is only the -% \emph{maximal} width of the created box. In the general case, the width of the -% box constructed by an environment |{varwidth}| is the natural width of its -% contents. -% -% \medskip -% That point is illustrated on the following examples. -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=6cm] -% \fbox{% -% \begin{~emphase#varwidth@}{8cm} -% \begin{itemize} -% \item first item -% \item second item -% \end{itemize} -% \end{~emphase#varwidth@}} -% \end{BVerbatim} -% \fbox{\begin{varwidth}{8cm} -% \begin{itemize} -% \item first item -% \item second item -% \end{itemize} -% \end{varwidth}} -% -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=6cm] -% \fbox{% -% \begin{~emphase#minipage@}{8cm} -% \begin{itemize} -% \item first item -% \item second item -% \end{itemize} -% \end{~emphase#minipage@}} -% \end{BVerbatim} -% \fbox{\begin{minipage}{8cm} -% \begin{itemize} -% \item first item -% \item second item -% \end{itemize} -% \end{minipage}} -% -% -% \bigskip -% The package \pkg{varwidth} provides also the column type |V|. A column of type -% |V{|$\langle$\textsl{dim}$\rangle$|}| encapsulates all its cells in a -% |{varwidth}| with the argument $\langle$\textsl{dim}$\rangle$ (and does also some tuning). -% -% \smallskip -% When the package \pkg{varwidth} is loaded, the columns |V| of \pkg{varwidth} -% are supported by \pkg{nicematrix}. -% -% \medskip -% \begin{Verbatim} -% \begin{NiceTabular}[corners=NW,hvlines]{~emphase#V{3cm}V{3cm}V{3cm}@} -% & some text & some very very very long text \\ -% some very very very long text \\ -% some very very very long text -% \end{NiceTabular} -% \end{Verbatim} -% -% \medskip -% \begin{center} -% \begin{NiceTabular}[corners=NW,hvlines]{V{3cm}V{3cm}V{3cm}} -% & some text & some very very very long text \\ -% some very very very long text \\ -% some very very very long text -% \end{NiceTabular} -% \end{center} -% -% \bigskip -% Concerning \pkg{nicematrix}, one of the -% interests of this type of columns is that, for a cell of a column of type~|V|, -% the PGF/Tikz node created by \pkg{nicematrix} for the content of that cell has -% a width adjusted to the content of the cell : cf. p.~\pageref{node-V}. -% -% -% \bigskip -% The columns |V| of \pkg{nicematrix} supports the keys |t|, |p|, |m|, |b|, |l|, -% |c| and |r| also supported by the columns |X|: see their description in the -% section~\ref{X-columns}, p.~\pageref{X-columns}. -% -% \bigskip -% One should remark that the extension \pkg{varwidth} (at least in its version -% 0.92) has some problems: for instance, with LuaLaTeX, it does not work when -% the content begins with |\color|. -% -% \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 exterior 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 and 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. This remark also applies to the -% customized rules created by the key |custom-line| -% (cf.~p.~\pageref{custom-line}). -% -% \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 example, 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|.} -% -% \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|, -% |\Hdotsfor| and |\Vdotsfor| (and by the command |\line| in the |\CodeAfter| -% which is described p.~\pageref{line-in-code-after}) may be customized by the following -% options (specified between square brackets after the command): -% \begin{itemize} -% \item |color|; -% \item |radius|; -% \item |shorten-start|, |shorten-end| and |shorten|; -% \item |inter|; -% \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| (\textsl{xdots} to remind that it works for -% |\Cdots|, |\Ldots|, |\Vdots|, etc.), and, thus have for names: -% \begin{itemize} -% \item |xdots/color|; -% \item |xdots/radius|; -% \item |xdots/shorten-start|, |xdots/shorten-end| and |xdots/shorten|; -% \item |xdots/inter|; -% \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/radius}\par\nobreak -% -% The option |radius| fixes the radius of the dots. The initial value is 0.53~pt. -% -% \bigskip -% \textbf{The option xdots/shorten}\par\nobreak -% -% \smallskip -% The keys |xdots/shorten-start| and |xdots/shorten-end| fix the margin at the -% extremities of the line. The key |xdots/shorten| fixes both parameters. -% The initial value is 0.3~em (it is recommanded to use a unit of length -% dependent of the current font). -% -% \bigskip -% \textbf{The option xdots/inter}\par\nobreak -% -% \smallskip -% The option |xdots/inter| fixes the length between the dots. The initial value -% is 0.45~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. Nevertheless, you can -% have a look at the following page to see how to have dotted rules with rounded -% dots in Tikz:\newline \small -% \url{https://tex.stackexchange.com/questions/52848/tikz-line-with-large-dots}} -% -% \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|, by the keys |hlines|, |vlines|, -% |hvlines| and |hvlines-except-borders| and by the tools created by -% |custom-line| 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{Delimiters in the preamble of the environnment} -% -% \label{delimiters-in-preamble} -% -% \colorbox{yellow!50}{\textbf{New 6.16}\enskip} -% In the environments with preamble (|{NiceArray}|, |{pNiceArray}|, etc.), it's -% possible to put vertical delimiters directly in the preamble of the -% environnment.\footnote{This syntax is inspired by the extension \pkg{blkarray}.} -% -% \smallskip -% The opening delimiters should be prefixed by the keyword |\left| and the -% closing delimiters by the keyword |\right|. It's not mandatory to use -% |\left| and |\right| pair-wise. -% -% \smallskip -% All the vertical extensible delimiters of LaTeX are allowed. -% -% \medskip -% Here is a example which uses the delimiters |\lgroup| and |\rgroup|. -% -% \smallskip -% \begin{BVerbatim} -% $\begin{NiceArray}{~emphase#\left\lgroup@ ccc~emphase#\right\rgroup@ l} -% 1 & 2 & 3 & -% 4 & 1 & 6 & -% 7 & 8 & 9 & \scriptstyle L_3 \gets L_3 + L_1 + L_2 -% \end{NiceArray}$ -% \end{BVerbatim} -% -% \[\begin{NiceArray}{\left\lgroup ccc\right\rgroup l} -% 1 & 2 & 3 & \\ -% 4 & 1 & 6 & \\ -% 7 & 8 & 9 & \scriptstyle L_3 \gets L_3 + L_1 + L_2 -% \end{NiceArray}\] -% -% \medskip -% For this example, it would also have been possible to use the environnment -% |{NiceArrayWithDelims}| (cf. the section \ref{NiceArrayWithDelims}, -% p.~\pageref{NiceArrayWithDelims}) and the key |last-col| (cf. p.~\pageref{exterior}). -% -% \bigskip -% There is a particular case: for the delimiters |(|, |[| and |\{| (and the -% corresponding closing delimiters), the prefixes |\left| et |\right| are -% optional.\footnote{For the delimiters |[| and |]|, the prefixes remain mandatory -% when there is a conflict of notation with the square brackets for the options -% of some descriptors of columns.} -% -% -% -% \bigskip -% 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}\] -% -% -% \bigskip -% For more complex constructions, in particular with delimiters spanning only a -% \emph{subset} of the rows of the array, one should consider the command -% |\SubMatrix| available in the |\CodeAfter|. See the section~\ref{sub-matrix}, -% p.~\pageref{sub-matrix}. -% -% \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).\footnote{Here are the keys accepted in that argument: -% |delimiters/color|, |rules| and its sub-keys and |sub-matrix| (linked to the -% command |\SubMatrix|) and its sub-keys.} -% -% -% \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, several special commands are available in the |\CodeAfter|: |line|, -% |\SubMatrix|, |\OverBrace| and |\UnderBrace|. We will now present these commands. -% -% \subsection{The command \textbackslash line in the \textbackslash CodeAfter} -% -% \label{line-in-code-after} -% The command |\line| draws directly dotted lines between cells or blocks. It takes in two -% arguments for the cells or blocks to link. Both argument may be: -% \begin{itemize} -% \item a specification of cell of the form $i$-$j$ where is the -% number of the row and $j$ is the number of the column; -% \item the name of a block (created by the command |\Block| with the key |name| -% of that command). -% \end{itemize} -% 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 (and the \textbackslash CodeBefore)} -% -% \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 \textsl{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 \emph{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}$ -% -% \medskip -% Eventually, in this example, it would probably have been easier to put the -% delimiters directly in the preamble of |{NiceArray}| (see -% section~\ref{delimiters-in-preamble}, p.~\pageref{delimiters-in-preamble}) -% with the following construction. -% -% \medskip -% \begin{scope} -% \hfuzz=15cm -% \begin{BVerbatim}[boxwidth=11cm,baseline=c] -% $\begin{NiceArray}{~emphase#(ccc)(c)@}[cell-space-limits=2pt] -% 1 & 1 & 1 & x \\ -% \dfrac{1}{4} & \dfrac{1}{2} & \dfrac{1}{4} & y \\ -% 1 & 2 & 3 & z -% \end{NiceArray}$ -% \end{BVerbatim} -% \end{scope} -% $\begin{NiceArray}{(ccc)(c)}[cell-space-limits=2pt] -% 1 & 1 & 1 & x \\ -% \dfrac{1}{4} & \dfrac{1}{2} & \dfrac{1}{4} & y \\ -% 1 & 2 & 3 & z -% \end{NiceArray}$ -% -% \bigskip -% 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 \Definition{left-xshift} and \Definition{right-xshift} shift -% horizontally the delimiters (there exists also the key \Definition{xshift} -% which fixes both parameters); -% \item \Definition{extra-height} adds a quantity to the total height of the -% delimiters (height |\ht| + depth |\dp|); -% \item \Definition{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 \Definition{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 \Definition{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 \Definition{hlines} is similar to |vlines| but for the horizontal rules; -% \item \Definition{hvlines}, which must be used without value, draws all the -% vertical and horizontal rules; -% \item \Definition{code} insert code, especially TikZ code, after the -% construcion of the submatrix. That key is detailed below. -% \end{itemize} -% One should remark that the 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 -% Despite its name, the command |\SubMatrix| may also be used within a -% |{NiceTabular}|. Here is an example (which uses |\bottomrule| and -% |\toprule| of \pkg{booktabs}). -% -% \medskip -% \begin{BVerbatim}[baseline=c] -% \begin{NiceTabular}{~@{}ll~@{}} -% \toprule -% Part A & the first part \\ -% \Block{2-1}{Part B} & a first sub-part \\ -% & a second sub-part \\ -% \bottomrule -% \CodeAfter -% ~emphase#\SubMatrix{\{}{2-2}{3-2}{.}@ -% \end{NiceTabular} -% \end{BVerbatim} -% \hspace{2cm} -% \begin{NiceTabular}{@{}ll@{}} -% \toprule -% Part A & the first part \\ -% \Block{2-1}{Part B} & a first sub-part \\ -% & a second sub-part \\ -% \bottomrule -% \CodeAfter -% \SubMatrix{\{}{2-2}{3-2}{.} -% \end{NiceTabular} -% -% \bigskip -% The command |\SubMatrix| is, in fact, also available in the |\CodeBefore|. By -% using |\SubMatrix| in the |\CodeBefore|, the delimiters drawn by those -% commands |\SubMatrix| are taken into account to limit the continuous dotted -% lines (drawn by |\Cdots|, |\Vdots|, etc.) which have an open extremity. -% -% For an example, see voir \ref{submatrix-in-codebefore} -% p.~\pageref{submatrix-in-codebefore}. -% -% -% -% \vspace{1cm} -% \colorbox{yellow!50}{\textbf{New 6.16}}\enskip The key |code| of the command -% |\SubMatrix| allows the insertion of code after the construction of the -% submatrix. It's meant to be used to insert TikZ instructions because, in the -% TikZ instructions inserted by that code, the nodes of the form |i-j| and -% \verb+i-|j+ are interpreted with |i| and |j| as numbers of row and columns -% \emph{relative to the submatrix}.\footnote{Be careful: the syntax -% \verb+j|-i+ is not allowed.} -% -% \medskip -% \begin{scope} -% \fvset{commandchars=\~\#\!}% -% \begin{Verbatim} -% $\begin{NiceArray}{ccc@{}w{c}{5mm}@{}ccc} -% & & && -1 & 1 & 2 \\ -% & & && 0 & 3 & 4 \\ -% & & && 0 & 0 & 5 \\ -% 1 & 2 & 3 && -1 & 7 & 25 \\ -% 0 & 4 & 5 && 0 & 12 & 41 \\ -% 0 & 0 & 6 && 0 & 0 & 30 -% \CodeAfter -% ~emphase#\NewDocumentCommand{\MyDraw}{}{\tikz \draw [blue] (2-|1) -| (3-|2) -| (4-|3) ;}! -% \SubMatrix({1-5}{3-7})[~emphase#code = \MyDraw!] -% \SubMatrix({4-1}{6-3})[~emphase#code = \MyDraw!] -% \SubMatrix({4-5}{6-7})[~emphase#code = \MyDraw!] -% \end{NiceArray}$ -% \end{Verbatim} -% \end{scope} -% -% -% \[\begin{NiceArray}{ccc@{}w{c}{5mm}@{}ccc} -% & & && -1 & 1 & 2 \\ -% & & && 0 & 3 & 4 \\ -% & & && 0 & 0 & 5 \\ -% 1 & 2 & 3 && -1 & 7 & 25 \\ -% 0 & 4 & 5 && 0 & 12 & 41 \\ -% 0 & 0 & 6 && 0 & 0 & 30 -% \CodeAfter -% \NewDocumentCommand{\MyDraw}{}{\tikz \draw [blue] (2-|1) -| (3-|2) -| (4-|3) ;} -% \SubMatrix({1-5}{3-7})[code = \MyDraw ] -% \SubMatrix({4-1}{6-3})[code = \MyDraw ] -% \SubMatrix({4-5}{6-7})[code = \MyDraw ] -% \end{NiceArray}\] -% -% \medskip -% As we see, the drawing done by our command |\MyDraw| is \emph{relative} to the -% submatrix to which it is applied. -% -% \subsection{The commands \textbackslash OverBrace and \textbackslash -% UnderBrace in the \textbackslash CodeAfter} -% -% The commands |\OverBrace| and |\UnderBrace| provide a way to put -% horizontal braces on a part of the array. These commands take in three -% arguments: -% \begin{itemize} -% \item the first 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 second argument is the lower-right corner with the same syntax; -% \item the third argument is the label of the brace that will be put by -% \pkg{nicematrix} (with \textsc{pgf}) above the brace (for the command -% |\OverBrace|) or under the brace (for |\UnderBrace|). -% \end{itemize} -% -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=9cm] -% \begin{pNiceMatrix} -% 1 & 2 & 3 & 4 & 5 & 6 \\ -% 11 & 12 & 13 & 14 & 15 & 16 \\ -% \CodeAfter -% ~emphase#\OverBrace{1-1}{2-3}{A}@ -% ~emphase#\OverBrace{1-4}{2-6}{B}@ -% \end{pNiceMatrix} -% \end{BVerbatim} -% $\begin{pNiceMatrix} -% 1 & 2 & 3 & 4 & 5 & 6 \\ -% 11 & 12 & 13 & 14 & 15 & 16 \\ -% \CodeAfter -% \OverBrace{1-1}{2-3}{A} -% \OverBrace{1-4}{2-6}{B} -% \end{pNiceMatrix}$ -% -% \bigskip -% In fact, the commands |\OverBrace| and |\UnderBrace| take in an optional -% argument (in first position and between square brackets) for a list of -% \textsl{key=value} pairs. The available keys are: -% \begin{itemize} -% \item |left-shorten| and |right-shorten| which do not take in value; when the -% key |left-shorten| is used, the abscissa of the left extremity of the brace is -% computed with the contents of the cells of the involved sub-array, otherwise, -% the position of the potential vertical rule is used (idem for -% |right-shorten|). -% -% \item |shorten|, which is the conjunction of the keys |left-shorten| and -% |right-shorten|; -% -% \item |yshift|, which shifts vertically the brace (and its label) ; -% -% \item |color|, which sets the color of the brace (and its label). -% \end{itemize} -% -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=9cm] -% \begin{pNiceMatrix} -% 1 & 2 & 3 & 4 & 5 & 6 \\ -% 11 & 12 & 13 & 14 & 15 & 16 \\ -% \CodeAfter -% \OverBrace~emphase#[shorten,yshift=3pt]@{1-1}{2-3}{A} -% \OverBrace~emphase#[shorten,yshift=3pt]@{1-4}{2-6}{B} -% \end{pNiceMatrix} -% \end{BVerbatim} -% $\begin{pNiceMatrix} -% 1 & 2 & 3 & 4 & 5 & 6 \\ -% 11 & 12 & 13 & 14 & 15 & 16 \\ -% \CodeAfter -% \OverBrace[shorten,yshift=3pt]{1-1}{2-3}{A} -% \OverBrace[shorten,yshift=3pt]{1-4}{2-6}{B} -% \end{pNiceMatrix}$ -% -% -% -% \section{Captions and notes in the tabulars} -% -% \label{s:notes} -% -% \subsection{Caption of a tabular} -% -% \smallskip -% The environment |{NiceTabular}| provides the keys |caption|, |short-caption| -% and |label| which may be used when the tabular is inserted in a floating -% environment (typically the environment |{table}|). -% -% \smallskip -% With the key |caption|, the caption, when it is long, is wrapped at the width -% of the tabular (excepted the potential exterior columns specified by -% |first-col| and |last-col|), without the use of the package -% \pkg{threeparttable} or the package \pkg{floatrow}. -% -% \smallskip -% By default, the caption is composed below the tabular. With the key -% |caption-above|, available in |\NiceMatrixOptions|, the caption will be -% composed above de tabular. -% -% \smallskip -% The key |short-caption| corresponds to the optional argument of the clasical -% command |\caption| and the key |label| corresponds, of course, to the command -% |\label|. -% -% \smallskip -% See table \ref{t:tabularnote}, p.~\pageref{t:tabularnote} for an example of -% use the keys |caption| and |label|. -% -% \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 -% 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 specified by |first-col| and |last-col|). With no -% surprise, that command is available only in the environments -% |{NiceTabular}|, |{NiceTabular*}| and |{NiceTabularX}|. -% -% 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. -% -% An alternative syntaxe is available with the environment |{TabularNote}|. That -% environment should be used at the end of the environment |{NiceTabular}| (but -% \emph{before} a potential instruction |\CodeAfter|). -% -% \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 (or in a -% command |\captionof| of the package \pkg{caption}). It's also possible, as -% expected, to use the command |\tabularnote| in the caption provided by the -% \emph{key} |caption| of the environment |{NiceTabaular}|. -% -% If several commands |\tabularnote| are used in a tabular with the same -% argument, only one note is inserted at the end of the tabular (but all the -% labels are composed, of course). It's possible to control that feature with -% the key |notes/detect-duplicates|.\footnote{For technical reasons, the final -% user is not allowed to put several commands |\tabularnote| with exactly the -% same argument in the caption of the tabular.} -% -% \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 (the package \pkg{caption} has been loaded in this document). -% -% \begin{center} -% \fvset{commandchars=\~\#\!} -% \begin{Verbatim}[formatcom=\small\color{gray}] -% \begin{table} -% \centering -% \NiceMatrixOptions{caption-above} -% \begin{NiceTabular}{@{}llc@{} -% [ -% caption = A tabular whose caption has been specified by the key -% \texttt{caption}~emphase#\tabularnote{It's possible to put a tabular note in the caption}! , -% label = t:tabularnote , -% tabularnote = Some text before the notes. , -% notes/bottomrule -% ] -% \toprule -% Last name & First name & Length of life \\ -% \midrule -% Churchill & Wiston & 91\\ -% Nightingale~emphase#\tabularnote{Considered as the first nurse of history}! -% ~emphase#\tabularnote{Nicknamed ``the Lady with the Lamp''.}! -% & Florence~emphase#\tabularnote{This note is shared by two references.}! & 90 \\ -% Schoelcher & Victor & 89~emphase#\tabularnote{The label of the note is overlapping.}!\\ -% Touchet & Marie~emphase#\tabularnote{This note is shared by two references.}! & 89 \\ -% Wallis & John & 87 \\ -% \bottomrule -% \end{NiceTabular} -% \end{table} -% \end{Verbatim} -% \end{center} -% -% -% \begin{table}[hbt] -% \centering -% \NiceMatrixOptions{caption-above} -% \begin{NiceTabular}{@{}llc@{}}[ -% caption = A tabular whose caption has been specified by the key -% \texttt{caption}\tabularnote{It's possible to put a tabular note in the caption} , -% label = t:tabularnote , -% tabularnote = Some text before the notes. , -% notes/bottomrule -% ] -% \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\tabularnote{This note is shared by two references.} & 90 \\ -% Schoelcher & Victor & 89\tabularnote{The label of the note is overlapping.}\\ -% Touchet & Marie\tabularnote{This note is shared by two references.} & 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}. This style of list is defined as follows (with, of -% course, keys of \pkg{enumitem}): -% -% |noitemsep , leftmargin = * , align = left , labelsep = 0pt| -% -% The specification |align = left| in that style 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}). -% -% \medskip -% The key |notes/enumitem-keys| specifies a list of pairs -% \textsl{key=value} (following the specifications of \pkg{enumitem}) to -% customize that style of list (it uses internally the command |\setlist*| of -% \pkg{enumitem}). -% -% -% \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|. -% -% Initially, the style of list is defined by:\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}). -% -% \item The key |notes/detect-duplicates| activates the detection of the commands -% |\tabularnotes| with the same argument. -% -% Initial value : |true| -% \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} -% -% Nevertheless, the use of \pkg{threeparttable} in conjonction with -% \pkg{nicematrix} seems rather point-less because of the functionalities -% provided by \pkg{nicematrix}. -% -% -% \section{Other features} -% -% \subsection{The key rounded-corners of \{NiceTabular\}} -% -% \label{tabular-rounded-corners} -% \colorbox{yellow!50}{\textbf{New 6.18}}\par\nobreak -% -% \smallskip -% The key |rounded-corners| that we will descrite now has no direct link with -% the key |corners| (which is used to specify ``empty corners'') described in -% the part~\ref{corners}, p.~\pageref{corners}. -% -% \smallskip -% The environment |{NiceTabular}| provides also a key |rounded-corners| which -% specify that the tabular should have rounded corners 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.}). More precisely, that -% key has two effects that we describe now. -% \begin{itemize} -% \item All the commands for coloring the cells, columns and rows (in the -% |\CodeBefore| but also directly in the array if the key |colortbl-like| is -% used) will respect those rounded corners. -% -% \item When the key |hvlines| is used, the exterior rules will be drawn with -% rounded corners. -% \end{itemize} - -% \bigskip -% \begin{BVerbatim}[baseline=c,boxwidth=9cm] -% \begin{NiceTabular} -% [hvlines,~emphase#rounded-corners@] -% {ccc} -% \CodeBefore -% \rowcolor{red!15}{1} -% \Body -% Last name & First name & Profession \\ -% Arvy & Jacques & Physicist \\ -% Jalon & Amandine & Physicist -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc}[hvlines,rounded-corners] -% \CodeBefore -% \rowcolor{red!15}{1} -% \Body -% Last name & First name & Profession \\ -% Arvy & Jacques & Physicist \\ -% Jalon & Amandine & Physicist -% \end{NiceTabular} -% -% -% \subsection{Command \textbackslash ShowCellNames} -% -% The command |\ShowCellNames|, which may be used in the |\CodeBefore| and in -% the |\CodeAfter| displays the name (with the form $i$-$j$) of each cell. When -% used in the |\CodeAfter|, that command applies a semi-transparent white -% rectangle to fade the array (caution: some \textsc{pdf} readers don't support -% transparency). -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=10.6cm] -% \begin{NiceTabular}{ccc}[hvlines,cell-space-limits=3pt] -% \Block{2-2}{} & & test \\ -% & & blabla \\ -% & some text & nothing -% ~emphase#\CodeAfter \ShowCellNames@ -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc}[hvlines,cell-space-limits=3pt] -% \Block{2-2}{} & & test \\ -% & & blabla \\ -% & some text & nothing -% \CodeAfter \ShowCellNames -% \end{NiceTabular} -% -% -% \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 = 11cm] -% $\begin{pNiceArray}{~emphase#S@cW{c}{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}{ScW{c}{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{Default column type in \{NiceMatrix\}} -% -% \label{columns-width} -% -% The environments without preamble (|{NiceMatrix}|, |{pNiceMatrix}|, -% |{bNiceMatrix}|, etc.) and the commande |\pAutoNiceMatrix| (and its variants) -% provide an option |columns-type| to specify the type of column which will be -% used (the initial value is, of course, |c|). -% -% The keys |l| and |r| are shortcuts for |columns-type=l| and |columns-type=r|. -% -% -% \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}$ -% -% \medskip -% The key |columns-type| is available in |\NiceMatrixOptions| but with the -% prefix |matrix|, which means that its name is, within |\NiceMatrixOptions| : -% |matrix/columns-type|. -% -% \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} -% -% \medskip -% When the key |small| is in force, some functionalities of \pkg{nicematrix} are -% no longer available: for example, it's no longer possible to put vertical -% delimiters directly in the preamble of an environment with preamble (cf. -% section \ref{delimiters-in-preamble}, p.~\pageref{delimiters-in-preamble}). -% -% -% \subsection{The counters iRow and jCol} -% -% \label{iRow} -% -% 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 key 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 environments 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 also applies to the delimiters drawn by the command |\SubMatrix| -% (cf.~p.~\pageref{sub-matrix}). -% -% \subsection{The environment \{NiceArrayWithDelims\}} -% -% \label{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}$ -% -% \subsection{The command \textbackslash OnlyMainNiceMatrix} -% -% The command |\OnlyMainNiceMatrix| executes its argument only when it is in the -% main part of the array, that is to say it is not in one of the exterior rows. -% If it is used outside an environment of \pkg{nicematrix}, that command is no-op. -% -% For an example of utilisation, see \url{tex.stackexchange.com/questions/488566} -% -% \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\footnote{We recall that Tikz -% is a layer over PGF. The extension \pkg{nicematrix} loads PGF but does not -% load Tikz. We speak of PGF/Tikz nodes to emphase the fact that the PGF nodes -% created by \pkg{nicematrix} may be used with PGF but also with Tikz. The final -% user will probably prefer to use Tikz rather than PGF.} 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}$ -% -% \medskip -% The nodes of the last column (excepted the potential «last column» specified -% by |last-col|\footnote{For the exterior columns, cf. part~\ref{exterior}, -% p.~\pageref{exterior}.}) may also be indicated by $i$-|last|. Similarly, the -% nodes of the last row may be indicated by |last|-$j$. -% -% \bigskip -% In the following example, we have underlined all the nodes of the matrix. -% -% \[ -% \NiceMatrixOptions -% { -% pgf-node-code = -% { -% \pgfsetfillcolor{red!15}% -% \pgfusepathqfill -% } -% } -% \begin{pNiceMatrix} -% a & a + b & a + b + c \\ -% a & a & a + b \\ -% a & a & a -% \end{pNiceMatrix}\] -% -% -% \bigskip -% \colorbox{yellow!50}{\textbf{New 6.17}}\enskip Since those nodes are PGF -% nodes, one won't be surprised to learn that they are drawn by using a specific -% PGF style. That style is called |nicematrix/cell-node| and its definition in -% the source file |nicematrix.sty| is as follows: -% -% \begin{Verbatim} -% \pgfset -% { -% ~emphase#nicematrix / cell-node@ /.style = -% { -% inner sep = 0 pt , -% minimum width = 0 pt -% } -% } -% \end{Verbatim} -% -% The final user may modify that style by changing the values of the keys |text/rotate|, -% |inner xsep|, |inner ysep|, |inner sep|, |outer xsep|, |outer ysep|, |outer sep|, -% |minimum width|, |minimum height| and |minimum size|. -% -% \medskip -% For an example of utilisation, see part~\ref{triangular}, p.~\pageref{triangular}. -% -% -% \subsubsection{The key pgf-node-code} -% -% \colorbox{yellow!50}{\textbf{New 6.17}}\enskip \textbf{For the experienced -% users}, \pkg{nicematrix} provides the key |pgf-node-code| which corresponds to -% some PGF node that will be executed at the creation, by PGF, of the nodes -% corresponding to the cells of the array. More pricisely, the value given to -% the key |pgf-node-code| will be passed in the fifth argument of the command -% |\pgfnode|. That value should contain at least an instruction such as -% |\pgfusepath|, |\pgfusepathqstroke|, |\pgfusepathqfill|, etc. -% -% \subsubsection{The columns V of varwidth} -% -% \label{node-V} -% When the extension \pkg{varwidth} is loaded, the columns of the type |V| -% defined by \pkg{varwidth} are supported by \pkg{nicematrix}. It may be -% interessant to notice that, for a cell of a column of type |V|, the PGF/Tikz -% node created by \pkg{nicematrix} for the content of that cell has a width -% adjusted to the content of the cell. This is in contrast to the case of the -% columns of type |p|, |m| or |b| for which the nodes have always a width equal -% to the width of the column. In the following example, the command |\lipsum| is -% provided by the eponymous package. -% -% \begin{Verbatim} -% \begin{NiceTabular}{V{10cm}} -% \bfseries \large -% Titre \\ -% \lipsum[1][1-4] -% \CodeAfter -% \tikz \draw [rounded corners] (1-1) -| (last-|2) -- (last-|1) |- (1-1) ; -% \end{NiceTabular} -% \end{Verbatim} -% -% -% \begin{center} -% \begin{NiceTabular}{V{10cm}} -% \bfseries \large -% Titre \\ -% \lipsum[1][1-4] -% \CodeAfter -% \tikz \draw [rounded corners] (1-1) -| (last-|2) -- (last-|1) |- (1-1) ; -% \end{NiceTabular} -% \end{center} -% -% We have used the nodes corresponding to the position of the potential rules, -% which are described below (cf. p.~\pageref{nodes-i}). -% -% -% \subsection[The medium nodes and the large nodes]{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). -% -% \bigskip -% Here is an example which uses these nodes in the |\CodeAfter|. -% -% \begin{center} -% \fvset{commandchars=\~\#\+} -% \begin{Verbatim} -% \begin{NiceArray}{c@{\;}c@{\;}c@{\;}c@{\;}c}[create-medium-nodes] -% u_1 &-& u_0 &=& r \\ -% u_2 &-& u_1 &=& r \\ -% u_3 &-& u_2 &=& r \\ -% u_4 &-& u_3 &=& r \\ -% \phantom{u_5} & & \phantom{u_4} &\smash{\vdots} & \\ -% u_n &-& u_{n-1} &=& r \\[3pt] -% \hline -% u_n &-& u_0 &=& nr \\ -% \CodeAfter -% \tikz[very thick, red, opacity=0.4, name suffix = -medium] -% \draw (1-1.north west) -- (2-3.south east) -% (2-1.north west) -- (3-3.south east) -% (3-1.north west) -- (4-3.south east) -% (4-1.north west) -- (5-3.south east) -% (5-1.north west) -- (6-3.south east) ; -% \end{NiceArray} -% \end{Verbatim} -% \end{center} -% -% \[\begin{NiceArray}{c@{\;}c@{\;}c@{\;}c@{\;}c}[create-medium-nodes] -% u_1 &-& u_0 &=& r \\ -% u_2 &-& u_1 &=& r \\ -% u_3 &-& u_2 &=& r \\ -% u_4 &-& u_3 &=& r \\ -% \phantom{u_5} & & \phantom{u_4} &\smash{\vdots} & \\ -% u_n &-& u_{n-1} &=& r \\[3pt] -% \hline -% u_n &-& u_0 &=& nr \\ -% \CodeAfter -% \tikz[very thick, red, opacity=0.4, name suffix = -medium] -% \draw (1-1.north west) -- (2-3.south east) -% (2-1.north west) --(3-3.south east) -% (3-1.north west) -- (4-3.south east) -% (4-1.north west) -- (5-3.south east) -% (5-1.north west) -- (6-3.south east) ; -% \end{NiceArray}\] -% -% -% -% \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_before_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_before_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_before_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] -% \CodeBefore -% \arraycolor{gray!10} -% \Body -% merlan & requin & cabillaud \\ -% baleine & ~emphase#\crossbox[red]@ & morue \\ -% mante & raie & poule -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{ccc}[hvlines] -% \CodeBefore -% \arraycolor{gray!10} -% \Body -% merlan & requin & cabillaud \\ -% baleine & \crossbox[red] & morue \\ -% mante & raie & poule -% \end{NiceTabular} -% -% -% -% \section{Technical remarks} -% -% First remark: the package \pkg{underscore} must be loaded before -% \pkg{nicematrix}. If it is loaded after, an error will be raised. -% -% \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]{The ``empty'' cells} -% -% \label{empty-cells} -% An instruction like |\Ldots|, |\Cdots|, etc. tries to determine the first -% non-empty cell on both sides. When the key |corners| is used -% (cf.~p.~\pageref{corners}), \pkg{nicematrix} computes corners consisting of -% empty cells. 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 For the columns of type |p|, |m|, |b|, |V|\footnote{The columns of type -% |V| are provided by \pkg{varwidth}: cf.~p.~\pageref{varwidth}.} and -% |X|\footnote{See p.~\pageref{X-columns}}, the cell is empty if (and only if) -% its content in the TeX code is empty (there is only spaces between the -% ampersands |&|). -% -% \medskip -% \item For the columns of type |c|, |l|, |r| and |w{...}{...}|, the cell is -% empty if (and only if) its TeX output has a width equal to zero. -% -% \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 only 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}. -% \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 -% \pkg{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 compatible with the class \cls{ieeeaccess} -% (because that class is not compatible with PGF/Tikz).\footnote{See -% \url{https://tex.stackexchange.com/questions/528975/error-loading-tikz-in-ieeeaccess-class}} -% -% \bigskip -% In order to use \pkg{nicematrix} with the class \cls{aastex631} -% (of the \emph{American Astronomical Society}), you have to -% add the following lines in the preamble of your document : -% -% \begin{Verbatim} -% \BeforeBegin{NiceTabular}{\let\begin\BeginEnvironment\let\end\EndEnvironment} -% \BeforeBegin{NiceArray}{\let\begin\BeginEnvironment} -% \BeforeBegin{NiceMatrix}{\let\begin\BeginEnvironment} -% \end{Verbatim} -% -% \bigskip -% In order to use \pkg{nicematrix} with the class \cls{sn-jnl} (of -% \emph{Springer Nature}), \pkg{pgf} must -% be loaded before the |\documentclass| with |\RequirePackage|: -% -% \begin{Verbatim} -% \RequirePackage{pgf} -% \documentclass{sn-jnl} -% \end{Verbatim} -% -% \bigskip -% The package \pkg{nicematrix} is not fully compatible with the packages and classes -% of \LuaTeX-ja: the detection of the empty corners (cf. % p.~\pageref{corners}) -% may be wrong in some circonstances. -% -% \bigskip -% The package \pkg{nicematrix} is not fully compatible with the package -% \pkg{arydshln} (because this package redefines many internals of \pkg{array}). -% By any means, in the context of \pkg{nicematrix}, it's recommended to draw -% dashed rules with the tools provided by \pkg{nicematrix}, by creating a -% customized line style with |custom-line|: cf.~p.~\pageref{custom-line}. -% -% \bigskip -% The columns |d| of \pkg{dcolumn} are not supported (but it's possible to use -% the colums |S| of \pkg{siunitx}). -% -% \section{Examples} -% -% \subsection[{Utilisation of the key 'tikz' of the command \textbackslash -% Block}]{Utilisation of the key ``tikz'' of the command \textbackslash Block} -% \label{tikz-key-examples} -% -% -% The key |tikz| of the command |\Block| is available only when Tikz is -% loaded.\footnote{By default, \pkg{nicematrix} only loads \textsc{pgf}, which is -% a sub-layer of Tikz.} -% -% For the following example, we also need the Tikz library |patterns|. -% -% \begin{Verbatim} -% \usetikzlibrary{patterns} -% \end{Verbatim} -% -% -% \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} -% -% \bigskip -% In the following example, we use the key |tikz| to hatch a row of the tabular. -% Remark that you use the key |transparent| of the command |\Block| in order to -% have the rules drawn in the block.\footnote{By default, the rules are not -% drawn in the blocks created by the command |\Block|: cf.~section~\ref{rules} -% p.~\pageref{rules}} -% -% \begin{Verbatim} -% \begin{NiceTabular}{ccc}[hvlines] -% \CodeBefore -% \columncolor[RGB]{169,208,142}{2} -% \Body -% one & two & three \\ -% \Block[~emphase#transparent, tikz={pattern = north west lines, pattern color = gray}@]{1-*}{} -% four & five & six \\ -% seven & eight & nine -% \end{Verbatim} -% -% \begin{center} -% \begin{NiceTabular}{ccc}[hvlines] -% \CodeBefore -% \columncolor[RGB]{169,208,142}{2} -% \Body -% one & two & three \\ -% \Block[transparent, tikz={pattern = north west lines, pattern color = gray}]{1-*}{} -% four & five & six \\ -% seven & eight & nine -% \end{NiceTabular} -% \end{center} -% -% \subsection{Use with tcolorbox} -% -% \label{tcolorbox} -% -% Here is an example of use of |{NiceTabular}| within a command |\tcbox| of -% \pkg{tcolorbox}. We have used the key |hvlines-except-borders| in order all -% the rules excepted on the borders (which are, of course, added by \pkg{tcolorbox}) -% -% \medskip -% \begin{BVerbatim} -% \tcbset -% { -% colframe = blue!50!black , -% colback = white , -% colupper = red!50!black , -% fonttitle = \bfseries , -% nobeforeafter , -% center title -% } -% -% \tcbox -% [ -% left = 0mm , -% right = 0mm , -% top = 0mm , -% bottom = 0mm , -% boxsep = 0mm , -% toptitle = 0.5mm , -% bottomtitle = 0.5mm , -% title = My table -% ] -% { -% \renewcommand{\arraystretch}{1.2}% <-- the % is mandatory here -% \begin{NiceTabular}{rcl}[~emphase#hvlines-except-borders@,rules/color=blue!50!black] -% \CodeBefore -% \rowcolor{red!15}{1} -% \Body -% One & Two & Three \\ -% Men & Mice & Lions \\ -% Upper & Middle & Lower -% \end{NiceTabular} -% } -% \end{BVerbatim} -% -% \medskip -% \begin{center} -% \tcbset -% { -% colframe = blue!50!black , -% colback = white , -% colupper = red!50!black , -% fonttitle = \bfseries , -% nobeforeafter , -% center title -% } -% -% \tcbox -% [ -% left = 0mm , -% right = 0mm , -% top = 0mm , -% bottom = 0mm , -% boxsep = 0mm , -% toptitle = 0.5mm , -% bottomtitle = 0.5mm , -% title = My table -% ] -% { -% \renewcommand{\arraystretch}{1.2}\begin{NiceTabular}{rcl}[hvlines-except-borders,rules/color=blue!50!black] -% \CodeBefore -% \rowcolor{red!15}{1} -% \Body -% One & Two & Three \\ -% Men & Mice & Lions \\ -% Upper & Middle & Lower -% \end{NiceTabular} -% } -% \end{center} -% -% -% -% \vspace{1cm} -% That example shows the use of \pkg{nicematrix} in conjunction with -% \pkg{tcolorbox}. If one wishes a tabular with an exterior frame with rounded -% corners, it's not necessary to use \pkg{tcolorbox}: it's possible to use the -% command |\Block| with the key |rounded-corners|. -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=10.5cm] -% \begin{NiceTabular}{rcl}[hvlines-except-borders] -% \Block[draw,transparent,~emphase#rounded-corners@]{*-*}{} -% One & Two & Three \\ -% Men & Mice & Lions \\ -% Upper & Middle & Lower -% \end{NiceTabular} -% \end{BVerbatim} -% \begin{NiceTabular}{rcl}[hvlines-except-borders] -% \Block[draw,transparent,rounded-corners]{*-*}{} -% One & Two & Three \\ -% Men & Mice & Lions \\ -% Upper & Middle & Lower -% \end{NiceTabular} -% -% \medskip -% We have used the key |transparent| to have the rules specified by -% |hvlines-except-borders| drawn in the blocks (by default, the rules are not -% drawn in the blocks). -% -% \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.\footnote{In this document, the Tikz library \pkg{arrows.meta} -% has been loaded, which impacts the shape of the arrow tips.} -% -% \begin{Verbatim} -% \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{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{Dashed rules} -% \label{dashed} -% -% In the following example, we use the command |\Block| to draw dashed rules. -% For that example, Tikz should be loaded (by |\usepackage{tikz}|). -% -% -% \begin{Verbatim} -% \begin{pNiceMatrix} -% ~emphase#\Block[borders={bottom,right,tikz=dashed}]{2-2}{}@ -% 1 & 2 & 0 & 0 & 0 & 0 \\ -% 4 & 5 & 0 & 0 & 0 & 0 \\ -% 0 & 0 & ~emphase#\Block[borders={bottom,top,right,left,tikz=dashed}]{2-2}{}@ -% 7 & 1 & 0 & 0 \\ -% 0 & 0 & -1 & 2 & 0 & 0 \\ -% 0 & 0 & 0 & 0 & ~emphase#\Block[borders={left,top,tikz=dashed}]{2-2}{}@ -% 3 & 4 \\ -% 0 & 0 & 0 & 0 & 1 & 4 -% \end{pNiceMatrix} -% \end{Verbatim} -% -% -% \[\begin{pNiceMatrix} -% \Block[borders={bottom,right,tikz=dashed}]{2-2}{} -% 1 & 2 & 0 & 0 & 0 & 0 \\ -% 4 & 5 & 0 & 0 & 0 & 0 \\ -% 0 & 0 & \Block[borders={bottom,top,right,left,tikz=dashed}]{2-2}{} -% 7 & 1 & 0 & 0 \\ -% 0 & 0 & -1 & 2 & 0 & 0 \\ -% 0 & 0 & 0 & 0 & \Block[borders={left,top,tikz=dashed}]{2-2}{} -% 3 & 4 \\ -% 0 & 0 & 0 & 0 & 1 & 4 -% \end{pNiceMatrix}\] -% -% -% \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} -% -% \bigskip -% In this tabular, the instructions |\SubMatrix| are executed after the -% composition of the tabular and, thus, the vertical rules are drawn without -% adding space between the columns. -% -% -%\bigskip -% In fact, it's possible, with the key |vlines-in-sub-matrix|, to choice a -% letter in the preamble of the array to specify vertical rules which will be -% drawn in the |\SubMatrix| only (by adding space between the columns). -% -% \medskip -% \begin{Verbatim} -% \setlength{\extrarowheight}{1mm} -% \[\begin{NiceArray} -% [ -% ~emphase#vlines-in-sub-matrix=I@, -% last-col, -% code-for-last-col = \scriptstyle \color{blue} -% ] -% {rrrrIr} -% 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 -% \SubMatrix({1-1}{4-5}) -% \SubMatrix({5-1}{8-5}) -% \SubMatrix({9-1}{11-5}) -% \SubMatrix({12-1}{13-5}) -% \end{NiceArray}\] -% \end{Verbatim} -% -% -% \medskip -% \begin{scope} -% \setlength{\extrarowheight}{1mm} -% \[\begin{NiceArray} -% [ -% vlines-in-sub-matrix=I, -% last-col, -% code-for-last-col = \scriptstyle \color{blue} -% ] -% {rrrrIr} -% 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 -% \SubMatrix({1-1}{4-5}) -% \SubMatrix({5-1}{8-5}) -% \SubMatrix({9-1}{11-5}) -% \SubMatrix({12-1}{13-5}) -% \end{NiceArray}\] -% \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. -% -% \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, margin = 2pt] -% \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, margin = 2pt] -% \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, margin = 2pt, 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, margin = 2pt, 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} -% -% \label{submatrix-in-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-last}) -% \SubMatrix({7-2}{last-6}) -% \SubMatrix({7-7}{last-last}) -% \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-last}) -% \SubMatrix({7-2}{last-6}) -% \SubMatrix({7-7}{last-last}) -% \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} -% -% -% -% \subsection{A triangular tabular} -% -% \label{triangular} -% -% In the following example, we use the style PGF/TikZ |nicematrix/cell-node| -% to rotate the contents of the cells (and, then, we compensate that rotation by -% a rotation of the whole tabular with the command |\adjustbox| of the eponymous -% package, which must be loaded previously). -% -% -% \medskip -% \begin{Verbatim} -% \pgfset -% { -% ~emphase#nicematrix/cell-node@/.append style = -% { text/rotate = 45, minimum size = 6 mm } -% } -% -% \setlength{\tabcolsep}{0pt} -% -% ~emphase#\adjustbox@{rotate = -45, set depth = 6mm + 1.414 \arrayrulewidth} -% {\begin{NiceTabular} [ hvlines, corners=SE, baseline = line-9 ] { cccccccc } -% \CodeBefore -% \chessboardcolors{red!15}{blue!15} -% \Body -% 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ -% 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ -% 1 & 3 & 6 & 10 & 15 & 21 \\ -% 1 & 4 & 10 & 20 & 35 \\ -% 1 & 5 & 15 & 35 \\ -% 1 & 6 & 21 \\ -% 1 & 7 \\ -% 1 -% \end{NiceTabular}} -% \end{Verbatim} -% -% -% \begin{center} -% \pgfset -% { -% nicematrix/cell-node/.append style = -% { text/rotate = 45, minimum size = 6 mm } -% }% -% \setlength{\tabcolsep}{0pt}% -% \adjustbox{rotate = -45, set depth = 6mm + 1.414 \arrayrulewidth} -% {\begin{NiceTabular} [ hvlines, corners=SE, baseline = line-9 ] { cccccccc } -% \CodeBefore -% \chessboardcolors{red!15}{blue!15} -% \Body -% 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ -% 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ -% 1 & 3 & 6 & 10 & 15 & 21 \\ -% 1 & 4 & 10 & 20 & 35 \\ -% 1 & 5 & 15 & 35 \\ -% 1 & 6 & 21 \\ -% 1 & 7 \\ -% 1 -% \end{NiceTabular}} -% \end{center} -% -% -% -% \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. -% \begin{macrocode} -\RequirePackage { array } -\RequirePackage { amsmath } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_error:n { \msg_error:nn { nicematrix } } -\cs_new_protected:Npn \@@_warning:n { \msg_warning:nn { nicematrix } } -\cs_new_protected:Npn \@@_error:nn { \msg_error:nnn { nicematrix } } -\cs_generate_variant:Nn \@@_error:nn { n x } -\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 } } -% \end{macrocode} -% -% With Overleaf, a document is compiled in non-stop mode. When there is an -% error, there is no way to the user to use the key H in order to have more -% information. That's why we decide to put that piece of information (for the -% messages with such information) in the main part of the message when the key -% |messages-for-Overleaf| is used (at load-time). -% \begin{macrocode} -\cs_new_protected:Npn \@@_msg_new:nnn #1 #2 #3 - { - \bool_if:NTF \c_@@_messages_for_Overleaf_bool - { \msg_new:nnn { nicematrix } { #1 } { #2 \\ #3 } } - { \msg_new:nnnn { nicematrix } { #1 } { #2 } { #3 } } - } -% \end{macrocode} -% -% \bigskip -% We also create a command which will genereate usually an error but only a -% warning on Overleaf. The argument is given by currification. -% \begin{macrocode} -\cs_new_protected:Npn \@@_error_or_warning:n - { \bool_if:NTF \c_@@_messages_for_Overleaf_bool \@@_warning:n \@@_error:n } -% \end{macrocode} -% -% We try to detect whether the compilation is done on Overleaf. We use -% |\c_sys_jobname_str| because, with Overleaf, the value of |\c_sys_jobname_str| -% is always ``|output|''. -% \begin{macrocode} -\bool_set:Nn \c_@@_messages_for_Overleaf_bool - { - \str_if_eq_p:Vn \c_sys_jobname_str { _region_ } % for Emacs - || \str_if_eq_p:Vn \c_sys_jobname_str { output } % for Overleaf - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_msg_redirect_name:nn - { \msg_redirect_name:nnn { nicematrix } } -\cs_new_protected:Npn \@@_gredirect_none:n #1 - { - \group_begin: - \globaldefs = 1 - \@@_msg_redirect_name:nn { #1 } { none } - \group_end: - } -\cs_new_protected:Npn \@@_err_gredirect_none:n #1 - { - \@@_error:n { #1 } - \@@_gredirect_none:n { #1 } - } -\cs_new_protected:Npn \@@_warning_gredirect_none:n #1 - { - \@@_warning:n { #1 } - \@@_gredirect_none:n { #1 } - } -% \end{macrocode} -% -% \bigskip -% \subsection*{Security test} -% -% Within the package \pkg{nicematrix}, we will have to test whether a cell of a -% |{NiceTabular}| is empty. For the cells of the columns of type |p|, |b|, |m|, -% |X| and |V|, we will test whether the cell is syntactically empty (that is to -% say that there is only spaces between the ampersands |&|). That test will be -% done with the command |\@@_test_if_empty:| by testing if the two first tokens -% in the cells are (during the TeX process) are |\ignorespaces| and |\unskip|. -% -% However, if, one day, there is a changement in the implementation of -% \pkg{array}, maybe that this test will be broken (and \pkg{nicematrix} also). -% -% That's why, by security, we will take a test in a small |{tabular}| composed -% in the box |\l_tmpa_box| used as sandbox. -% -% \begin{macrocode} -\@@_msg_new:nn { Internal~error } - { - Potential~problem~when~using~nicematrix.\\ - The~package~nicematrix~have~detected~a~modification~of~the~ - standard~environment~{array}~(of~the~package~array).~Maybe~you~will~encounter~ - some~slight~problems~when~using~nicematrix.~If~you~don't~want~to~see~ - this~message~again,~load~nicematrix~with:~\token_to_str:N - \usepackage[no-test-for-array]{nicematrix}. - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\@@_msg_new:nn { mdwtab~loaded } - { - The~packages~'mdwtab'~and~'nicematrix'~are~incompatible.~ - This~error~is~fatal. - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_security_test:n #1 - { - \peek_meaning:NTF \ignorespaces - { \@@_security_test_i:w } - { \@@_error:n { Internal~error } } - #1 - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_security_test_i:w \ignorespaces #1 - { - \peek_meaning:NF \unskip { \@@_error:n { Internal~error } } - #1 - } -% \end{macrocode} -% -% \bigskip -% Here, the box |\l_tmpa_box| will be used as sandbox to take our security test. -% This code has benne modified in version 6.18 (see question 682891 on TeX -% StackExchange). -% \begin{macrocode} -\hook_gput_code:nnn { begindocument / after } { . } - { - \@ifpackageloaded { mdwtab } - { \@@_fatal:n { mdwtab~loaded } } - { - \bool_if:NF \c_@@_no_test_for_array_bool - { - \group_begin: - \hbox_set:Nn \l_tmpa_box - { - \begin { tabular } { c > { \@@_security_test:n } c c } - text & & text - \end { tabular } - } - \group_end: - } - } - } -% \end{macrocode} -% -% \bigskip -% \subsection*{Technical definitions} -% -% \begin{macrocode} -\tl_new:N \l_@@_argspec_tl -% \end{macrocode} -% -% \begin{macrocode} -\cs_generate_variant:Nn \seq_set_split:Nnn { N V n } -\cs_generate_variant:Nn \keys_define:nn { n x } -\cs_generate_variant:Nn \str_lowercase:n { V } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \@ifpackageloaded { varwidth } - { \bool_const:Nn \c_@@_varwidth_loaded_bool { \c_true_bool } } - { \bool_const:Nn \c_@@_varwidth_loaded_bool { \c_false_bool } } - \@ifpackageloaded { booktabs } - { \bool_const:Nn \c_@@_booktabs_loaded_bool { \c_true_bool } } - { \bool_const:Nn \c_@@_booktabs_loaded_bool { \c_false_bool } } - \@ifpackageloaded { enumitem } - { \bool_const:Nn \c_@@_enumitem_loaded_bool { \c_true_bool } } - { \bool_const:Nn \c_@@_enumitem_loaded_bool { \c_false_bool } } - \@ifpackageloaded { tabularx } - { \bool_const:Nn \c_@@_tabularx_loaded_bool { \c_true_bool } } - { \bool_const:Nn \c_@@_tabularx_loaded_bool { \c_false_bool } } - \@ifpackageloaded { floatrow } - { \bool_const:Nn \c_@@_floatrow_loaded_bool { \c_true_bool } } - { \bool_const:Nn \c_@@_floatrow_loaded_bool { \c_false_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. The tokens -% |\exp_not:N| are mandatory. -% \begin{macrocode} - \bool_const:Nn \c_@@_tikz_loaded_bool \c_true_bool - \tl_const:Nn \c_@@_pgfortikzpicture_tl { \exp_not:N \tikzpicture } - \tl_const:Nn \c_@@_endpgfortikzpicture_tl { \exp_not:N \endtikzpicture } - } - { - \bool_const:Nn \c_@@_tikz_loaded_bool \c_false_bool - \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 March 2023, the current -% version \cls{revtex4-2} is 4.2e (compatible with \pkg{booktabs}). -% -% \begin{macrocode} -\@ifclassloaded { revtex4-1 } - { \bool_const:Nn \c_@@_revtex_bool \c_true_bool } - { - \@ifclassloaded { revtex4-2 } - { \bool_const:Nn \c_@@_revtex_bool \c_true_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_const:Nn \c_@@_revtex_bool \c_true_bool } - { \bool_const:Nn \c_@@_revtex_bool \c_false_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} -\hook_gput_code:nnn { begindocument } { . } - { - \@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 \l_@@_colortbl_loaded_bool -\hook_gput_code:nnn { begindocument } { . } - { - \@ifpackageloaded { colortbl } - { \bool_set_true:N \l_@@_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 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 { \int_eval:n { #1 - 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} or the form -% \textsl{i}. -% \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 - { - \tl_if_empty:nTF { #3 } - { \@@_cline_iii:w #1|#2-#2 \q_stop } - { \@@_cline_ii:w #1|#2-#3 \q_stop } - } -\cs_set:Npn \@@_cline_ii:w #1|#2-#3-\q_stop - { \@@_cline_iii:w #1|#2-#3 \q_stop } -\cs_set:Npn \@@_cline_iii: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 { \int_eval:n { #3 + 1 } } } - { \everycr { } \cr } - } -\cs_generate_variant:Nn \@@_cline_i:nn { e n } -% \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@:n #1 - { - \tl_if_blank:nF { #1 } - { - \tl_if_head_eq_meaning:nNTF { #1 } [ - { \cs_set:Npn \CT@arc@ { \color #1 } } - { \cs_set:Npn \CT@arc@ { \color { #1 } } } - } - } -\cs_generate_variant:Nn \@@_set_CT@arc@:n { V } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_set_CT@drsc@:n #1 - { - \tl_if_head_eq_meaning:nNTF { #1 } [ - { \cs_set:Npn \CT@drsc@ { \color #1 } } - { \cs_set:Npn \CT@drsc@ { \color { #1 } } } - } -\cs_generate_variant:Nn \@@_set_CT@drsc@:n { V } -% \end{macrocode} -% -% \bigskip -% The following command must \emph{not} be protected since it will be used to -% write instructions in the (internal) |\CodeBefore|. -% \begin{macrocode} -\cs_new:Npn \@@_exp_color_arg:Nn #1 #2 - { - \tl_if_head_eq_meaning:nNTF { #2 } [ - { #1 #2 } - { #1 { #2 } } - } -\cs_generate_variant:Nn \@@_exp_color_arg:Nn { N V } -% \end{macrocode} -% -% The following command must be protected because of its use of the command |\color|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_color:n #1 - { - \tl_if_blank:nF { #1 } - { \@@_exp_color_arg:Nn \color { #1 } } - } -\cs_generate_variant:Nn \@@_color:n { V } -% \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 \l_@@_siunitx_loaded_bool -\hook_gput_code:nnn { begindocument } { . } - { - \@ifpackageloaded { siunitx } - { \bool_set_true:N \l_@@_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} -\hook_gput_code:nnn { begindocument } { . } - { - \bool_if:nTF { ! \l_@@_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 the L3 programming layer). -% \begin{macrocode} - \tl_if_empty:nTF { ##1 } - { - \@temptokena \exp_after:wN - { \tex_the:D \@temptokena \@@_S: } - } - { - \@temptokena \exp_after:wN - { \tex_the:D \@temptokena \@@_S: [ ##1 ] } - } - \NC@find - } - } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_rescan_for_spanish:N #1 - { - \tl_set_rescan:Nno - #1 - { - \char_set_catcode_other:N > - \char_set_catcode_other:N < - } - #1 - } -% \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 -% If, in a tabular, there is a tabular note in a caption that must be composed -% \emph{above} the tabular, we will store in |\l_@@_note_in_caption_int| the -% number of notes in that caption. It will be stored in the |aux| file. -% \begin{macrocode} -\int_new:N \l_@@_note_in_caption_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 parameter will be used by |\@@_create_row_node:| to avoid to -% create the same row-node twice (at the end of the array). -% \begin{macrocode} -\int_new:N \g_@@_last_row_node_int -% \end{macrocode} -% -% \bigskip -% The following counter corresponds to the key |nb-rows| of the command -% |\RowStyle|. -% \begin{macrocode} -\int_new:N \l_@@_key_nb_rows_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 example, 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 for the mono-row blocks. -% \begin{macrocode} -\dim_new:N \g_@@_blocks_ht_dim -\dim_new:N \g_@@_blocks_dp_dim -% \end{macrocode} -% -% \bigskip -% The following dimension will be used by the command |\Block| for the blocks -% with a key of vertical position equal to |T| or |B|. -% \begin{macrocode} -\dim_new:N \l_@@_block_ysep_dim -% \end{macrocode} -% -% \bigskip -% The following dimension correspond to the key |width| (which may be fixed in -% |\NiceMatrixOptions| but also in an environment |{NiceTabular}|). -% \begin{macrocode} -\dim_new:N \l_@@_width_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 -% The following key corresponds to the key |notes/detect_duplicates|. -% \begin{macrocode} -\bool_new:N \l_@@_notes_detect_duplicates_bool -\bool_set_true:N \l_@@_notes_detect_duplicates_bool -% \end{macrocode} -% -% \bigskip -% If the user uses |{NiceArray}| or |{NiceTabular}| the flag -% |\g_@@_NiceArray_bool| will be raised. -% \begin{macrocode} -\bool_new:N \g_@@_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}|, |{NiceTabular*}| or |{NiceTabularX}|, 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 -% The following dimension will be used for the total width of composite rules -% (\emph{total} means that the spaces on both sides are included). -% \begin{macrocode} -\dim_new:N \l_@@_rule_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} -% -% \begin{macrocode} -\bool_new:N \g_@@_caption_finished_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 -% The following parameter corresponds to the key |columns-type| of the -% environments |{NiceMatrix}|, |{pNiceMatrix}|, etc. and also the key -% |matrix / columns-type| of |\NiceMatrixOptions|. However, it does \emph{not} -% contain the value provided by the final user. Indeed, a transformation is done -% in order to have a preamble (for the package \pkg{array}) which is -% nicematrix-aware. That transformation is done with the command -% |\@@_set_preamble:Nn|. -% \begin{macrocode} -\tl_new:N \l_@@_columns_type_tl -\hook_gput_code:nnn { begindocument } { . } - { \@@_set_preamble:Nn \l_@@_columns_type_tl { c } } -% \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_new:N \g_@@_com_or_env_str -\tl_gset: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|). -% That parameter is \emph{public}. -% \begin{macrocode} -\tl_new:N \g_nicematrix_code_after_tl -\bool_new:N \l_@@_in_code_after_bool -% \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 -% For the key |pgf-node-code|. That code will be used when the nodes of the -% cells (that is to say the nodes of the form |i-j|) will be created. -% \begin{macrocode} -\tl_new:N \l_@@_pgf_node_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_@@_pre_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_@@_pre_code_after_tl -% \end{macrocode} -% -% \bigskip -% The value of the key |code-before| will be added to the left of -% |\g_@@_pre_code_before_tl|. Idem for the code between |\CodeBefore| and -% |\Body|. -% \begin{macrocode} -\tl_new:N \g_nicematrix_code_before_tl -\tl_new:N \g_@@_pre_code_before_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 sequence will contain the names (without backslash) of the -% commands created by |custom-line| by the key |command| or |ccommand| (commands -% used by the final user in order to draw horizontal rules). -% \begin{macrocode} -\seq_new:N \l_@@_custom_line_commands_seq -% \end{macrocode} -% -% \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 an 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 the 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. -% \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 boolean will be used to deal with the commands |\tabularnote| in -% the caption (command |\caption| or key |caption|). -% \begin{macrocode} -\bool_new:N \g_@@_second_composition_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 five components: -% |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}{|% -% \textsl{name}|}|. 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 five components: -% |{|\textsl{imin}|}{|\textsl{jmin}|}{|\textsl{imax}|}{|\textsl{jmax}|}{|% -% \textsl{name}|}|. -% \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|, 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| is used in an environment -% |{NiceTabular}| (not in a command |\NiceMatrixOptions|). 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 |\CodeBefore| (and not in the |\CodeAfter|). It will contain the position of -% all the sub-matrices specified in the |\CodeBefore|. Each sub-matrix is -% represented by an ``object'' of the form |{|$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 dimension corresponds to the key |rounded-corners| available in -% an individual environment |{NiceTabular}|. When that key is used, a clipping -% is applied in the |\CodeBefore| of the environment in order to have rounded -% corners for the potential colored panels. -% \begin{macrocode} -\dim_new:N \l_@@_tab_rounded_corners_dim -% \end{macrocode} -% -% \medskip -% The following token list correspond to the key |color| of the command |\Block| -% and also the key |color| of the command |\RowStyle|. -% \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} -\str_new:N \l_@@_vpos_of_block_str -\str_set:Nn \l_@@_vpos_of_block_str { 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 keys |vlines| and |hlines| of the -% command |\Block| (the key |hvlines| is the conjunction of both). -% \begin{macrocode} -\bool_new:N \l_@@_vlines_block_bool -\bool_new:N \l_@@_hlines_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} -% -% \medskip -% The following key is set when the keys |hvlines| and |hvlines-except-borders| -% are used. It's used only to change slightly the clipping path set by the key -% |rounded-corners| (for a |{tabular}|). -% \begin{macrocode} -\bool_new:N \l_@@_hvlines_bool -% \end{macrocode} -% -% -% -% \bigskip -% The following flag will be used by (for instance) |\@@_vline_ii:|. -% When |\l_@@_dotted_bool| is |true|, a dotted line (with our system) will be drawn. -% \begin{macrocode} -\bool_new:N \l_@@_dotted_bool -% \end{macrocode} -% -% \bigskip -% The following flag will be set to true during the composition of a caption -% specified (by the key |caption|). -% \begin{macrocode} -\bool_new:N \l_@@_in_caption_bool -% \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 -% \textbf{Some utilities} -% -% \medskip -% \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} -% -% -% The following takes as argument the name of a |clist| and which should be a -% list of intervals of integers. It \emph{expands} that list, that is to say, -% it replaces (by a sort of |mapcan| or |flat_map|) the interval by the explicit -% list of the integers. -% \begin{macrocode} -\cs_new_protected:Npn \@@_expand_clist:N #1 - { - \clist_if_in:NnF #1 { all } - { - \clist_clear:N \l_tmpa_clist - \clist_map_inline:Nn #1 - { - \tl_if_in:nnTF { ##1 } { - } - { \@@_cut_on_hyphen:w ##1 \q_stop } - { - \tl_set:Nn \l_tmpa_tl { ##1 } - \tl_set:Nn \l_tmpb_tl { ##1 } - } - \int_step_inline:nnn { \l_tmpa_tl } { \l_tmpb_tl } - { \clist_put_right:Nn \l_tmpa_clist { ####1 } } - } - \tl_set_eq:NN #1 \l_tmpa_clist - } - } -% \end{macrocode} -% -% \bigskip -% \subsection*{The command \textbackslash tabularnote} -% -% \bigskip -% Of course, it's possible to use |\tabularnote| in the main tabular. But there -% is also the possibility to use that command in the caption of the tabular. And -% the caption may be specified by two means: -% -% \begin{itemize} -% \item The caption may of course be provided by the command |\caption| in a -% floating environment. Of course, a command |\tabularnote| in that |\caption| -% makes sens only if the |\caption| is \emph{before} the |{tabular}|. -% \item It's also possible to use |\tabularnote| in the value of the key -% |caption| of the |{NiceTabular}| when the key |caption-above| is in force. -% However, in that case, one must remind that the caption is composed -% \emph{after} the composition of the box which contains the main tabular -% (that's mandatory since that caption must be wrapped with a line width equal -% to the width ot the tabular). However, we want the labels of the successive -% tabular notes in the logical order. That's why: -% \begin{itemize} -% \item The number of tabular notes present in the caption will be written on -% the |aux| file and available in |\l_@@_note_in_caption_int|. -% \item During the composition of the main tabular, the tabular notes will be -% numbered from |\l_@@_note_in_caption_int|+1 and the notes will be stored in -% |\g_@@_notes_seq|. -% \item During the composition of the caption (value of |\l_@@_caption_tl|), the -% tabular notes will be numbered from $1$ to |\l_@@_note_in_caption_int| and the -% notes themselves will be stored in |\g_@@_notes_in_caption_seq|. -% \item After the composition of the main tabular and after the composition of -% the caption, the sequences |\g_@@_notes_in_caption_seq| and |\g_@@_notes_seq| -% will be merged (in that order) and the notes will be composed. -% \end{itemize} -% \end{itemize} -% -% -% \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} -% -% \begin{macrocode} -\seq_new:N \g_@@_notes_seq -\seq_new:N \g_@@_notes_in_caption_seq -% \end{macrocode} -% -% \bigskip -% 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 \g_@@_tabularnote_tl -% \end{macrocode} -% -% \bigskip -% We prepare the tools for the formatting of the references of the footnotes (in -% the tabular itself). There may have several references of footnote at the same -% point and we have to take into account that point. -% \begin{macrocode} -\seq_new:N \l_@@_notes_labels_seq -\newcounter{nicematrix_draft} -\cs_new_protected:Npn \@@_notes_format:n #1 - { - \setcounter { nicematrix_draft } { #1 } - \@@_notes_style:n { nicematrix_draft } - } -% \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 tabular 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} -\hook_gput_code:nnn { begindocument } { . } - { - \bool_if:nTF { ! \c_@@_enumitem_loaded_bool } - { - \NewDocumentCommand \tabularnote { m } - { - \@@_error_or_warning:n { enumitem~not~loaded } - \@@_gredirect_none: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} -% -% \bigskip -% One must remind that we have allowed a |\tabular| in the caption and -% that caption may also be found in the list of tables (|\listoftables|). We -% want the command |\tabularnote| be no-op during the composition of that list. -% That's why we program |\tabularnote| to be no-op excepted in a floating -% environment or in an environment of \pkg{nicematrix}. -% \begin{macrocode} - \NewDocumentCommand \tabularnote { m } - { - \bool_if:nT { \cs_if_exist_p:N \@captype || \l_@@_in_env_bool } - { - \bool_if:nTF { ! \l_@@_NiceTabular_bool && \l_@@_in_env_bool } - { \@@_error:n { tabularnote~forbidden } } - { - \bool_if:NTF \l_@@_in_caption_bool - { \@@_tabularnote_ii:n { #1 } } - { \@@_tabularnote_i:n { #1 } } - } - } - } -% \end{macrocode} -% -% \bigskip -% For the version in normal conditions, that is to say not in the key |caption|. -% \begin{macrocode} - \cs_new_protected:Npn \@@_tabularnote_i:n #1 - { -% \end{macrocode} -% You have to see whether the argument of |\tabularnote| has yet been used as -% argument of another |\tabularnote| in the same tabular. In that case, there -% will be only one note (for both commands |\tabularnote|) at the end of the -% tabular. We search the argument of our command |\tabularnote| in the -% |\g_@@_notes_seq|. The position in the sequence will be stored in -% |\l_tmpa_int| (0 if the text is not in the sequence yet). -% \begin{macrocode} - \int_zero:N \l_tmpa_int - \bool_if:NT \l_@@_notes_detect_duplicates_bool - { - \seq_map_indexed_inline:Nn \g_@@_notes_seq - { - \tl_if_eq:nnT { #1 } { ##2 } - { \int_set:Nn \l_tmpa_int { ##1 } \seq_map_break: } - } - \int_compare:nNnF \l_tmpa_int = 0 - { \int_add:Nn \l_tmpa_int \l_@@_note_in_caption_int } - } - \int_compare:nNnTF \l_tmpa_int = 0 - { - \int_gincr:N \c@tabularnote - \seq_put_right:Nx \l_@@_notes_labels_seq - { \@@_notes_format:n { \int_use:c { c @ tabularnote } } } - \seq_gput_right:Nn \g_@@_notes_seq { #1 } - } - { - \seq_put_right:Nx \l_@@_notes_labels_seq - { \@@_notes_format:n { \int_use:N \l_tmpa_int } } - } - \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 an 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 -% put the labels in a |\textsuperscript|. -% \begin{macrocode} - \@@_notes_label_in_tabular:n - { - \seq_use:Nnnn - \l_@@_notes_labels_seq { , } { , } { , } - } - } -% \end{macrocode} -% We want the (last) tabular note referenceable (with the standard command |\label|). -% \begin{macrocode} - \int_gsub:Nn \c@tabularnote { 1 } - \int_set_eq:NN \l_tmpa_int \c@tabularnote - \refstepcounter { tabularnote } - \int_compare:nNnT \l_tmpa_int = \c@tabularnote - { \int_gincr:N \c@tabularnote } - \seq_clear:N \l_@@_notes_labels_seq - \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} -% -% \bigskip -% Now the version when the command is used in the key |caption|. The main -% difficulty is that the argument of the command |\caption| is composed several -% times. In order to know the number of commands |\tabularnote| in the caption, -% we will consider that there should not be the same tabular note twice in the -% caption (in the main tabular, it's possible). Once we have found a tabular -% note which has yet been encoutered, we consider that you are in a new -% composition of the argument of |\caption|. At that time, we store in -% |\g_@@_nb_of_notes_int| the number of notes in the |\caption|. -% \begin{macrocode} - \cs_new_protected:Npn \@@_tabularnote_ii:n #1 - { - \int_gincr:N \c@tabularnote - \bool_if:NTF \g_@@_caption_finished_bool - { - \int_compare:nNnTF - \c@tabularnote > { \tl_count:N \g_@@_notes_in_caption_seq } - { \int_gset:Nn \c@tabularnote { 1 } } - \seq_if_in:NnF \g_@@_notes_in_caption_seq { #1 } - { \@@_fatal:n { Identical~notes~in~caption } } - } - { - \seq_if_in:NnTF \g_@@_notes_in_caption_seq { #1 } - { - \bool_gset_true:N \g_@@_caption_finished_bool - \int_gset:Nn \c@tabularnote { 1 } - } - { \seq_gput_right:Nn \g_@@_notes_in_caption_seq { #1 } } - } - \seq_put_right:Nx \l_@@_notes_labels_seq - { \@@_notes_format:n { \int_use:N \c@tabularnote } } - \peek_meaning:NF \tabularnote - { - \hbox_set:Nn \l_tmpa_box - { - \@@_notes_label_in_tabular:n - { - \seq_use:Nnnn - \l_@@_notes_labels_seq { , } { , } { , } - } - } - \seq_clear:N \l_@@_notes_labels_seq - \hbox_overlap_right:n { \box_use:N \l_tmpa_box } - \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:nnnnn|: -% 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} -% -% The following parameter corresponds to the keys |caption|, |short-caption| and -% |label| of the environment |{NiceTabular}|. -% \begin{macrocode} -\tl_new:N \l_@@_caption_tl -\tl_new:N \l_@@_short_caption_tl -\tl_new:N \l_@@_label_tl -% \end{macrocode} -% -% \bigskip -% The following parameter corresponds to the key |caption-above| of -% |\NiceMatrixOptions|. When this paremeter is |true|, the captions of the -% environments |{NiceTabular}|, specified with the key |caption| are put above -% the tabular (and below elsewhere). -% \begin{macrocode} -\bool_new:N \l_@@_caption_above_bool -% \end{macrocode} -% -% \bigskip -% 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 -% |\arrayrulewidth|. 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_@@_xdots_inter_dim -\hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_xdots_inter_dim { 0.45 em } } -% \end{macrocode} -% We use a hook only by 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_start_dim -\dim_new:N \l_@@_xdots_shorten_end_dim -\hook_gput_code:nnn { begindocument } { . } - { - \dim_set:Nn \l_@@_xdots_shorten_start_dim { 0.3 em } - \dim_set:Nn \l_@@_xdots_shorten_end_dim { 0.3 em } - } -% \end{macrocode} -% We use a hook only by 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_@@_xdots_radius_dim -\hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_xdots_radius_dim { 0.53 pt } } -% \end{macrocode} -% We use a hook only by security in case \cls{revtex4-1} is used (even though 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 -\hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_notes_above_space_dim { 1 mm } } -% \end{macrocode} -% We use a hook only by security in case \cls{revtex4-1} is used (even though 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} -% -% \medskip -% The following flag corresponds to the key |respect-arraystretch| (that key has -% an effect on the blocks). -% \begin{macrocode} -\bool_new:N \l_@@_respect_arraystretch_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 .code:n = - \hook_gput_code:nnn { begindocument } { . } - { - \dim_set:Nn \l_@@_xdots_shorten_start_dim { #1 } - \dim_set:Nn \l_@@_xdots_shorten_end_dim { #1 } - } , - shorten-start .code:n = - \hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_xdots_shorten_start_dim { #1 } } , - shorten-end .code:n = - \hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_xdots_shorten_end_dim { #1 } } , -% \end{macrocode} -% We use a hook only by security in case \cls{revtex4-1} -% is used (even though it is obsolete). Idem for the following keys. -% \begin{macrocode} - shorten .value_required:n = true , - shorten-start .value_required:n = true , - shorten-end .value_required:n = true , - radius .code:n = - \hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_xdots_radius_dim { #1 } } , - radius .value_required:n = true , - inter .code:n = - \hook_gput_code:nnn { begindocument } { . } - { \dim_set:Nn \l_@@_xdots_inter_dim { #1 } } , - radius .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 , - unknown .code:n = \@@_error:n { Unknown~key~for~rules } - } -% \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 } - { - custom-line .code:n = \@@_custom_line:n { #1 } , - 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 = - { - \bool_set_true:N \l_@@_hvlines_bool - \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_@@_hvlines_bool - \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 , - respect-arraystretch .bool_set:N = \l_@@_respect_arraystretch_bool , - respect-arraystretch .default:n = true , - pgf-node-code .tl_set:N = \l_@@_pgf_node_code_tl , - pgf-node-code .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 } - { - corners .clist_set:N = \l_@@_corners_clist , - corners .default:n = { NW , SW , NE , SE } , - code-before .code:n = - { - \tl_if_empty:nF { #1 } - { - \tl_gput_left:Nn \g_@@_pre_code_before_tl { #1 } - \bool_set_true:N \l_@@_code_before_bool - } - } , - code-before .value_required:n = true , -% \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 = - { - \hook_gput_code:nnn { begindocument } { . } - { - \bool_if:NT \c_@@_enumitem_loaded_bool - { \setlist* [ tabularnotes ] { #1 } } - } - } , - enumitem-keys .value_required:n = true , - enumitem-keys-para .code:n = - { - \hook_gput_code:nnn { begindocument } { . } - { - \bool_if:NT \c_@@_enumitem_loaded_bool - { \setlist* [ tabularnotes* ] { #1 } } - } - } , - enumitem-keys-para .value_required:n = true , - detect-duplicates .bool_set:N = \l_@@_notes_detect_duplicates_bool , - detect-duplicates .default: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 / sub-matrix .inherit:n = NiceMatrix / sub-matrix , - SubMatrix / rules .inherit:n = NiceMatrix / rules , - CodeAfter / xdots .inherit:n = NiceMatrix / xdots , - CodeBefore / sub-matrix .inherit:n = NiceMatrix / sub-matrix , - NiceMatrix .inherit:n = - { - NiceMatrix / Global , - NiceMatrix / Env , - } , - NiceMatrix / xdots .inherit:n = NiceMatrix / xdots , - NiceMatrix / rules .inherit:n = NiceMatrix / rules , - NiceTabular .inherit:n = - { - NiceMatrix / Global , - NiceMatrix / Env - } , - NiceTabular / xdots .inherit:n = NiceMatrix / xdots , - NiceTabular / rules .inherit:n = NiceMatrix / rules , - NiceTabular / notes .inherit:n = NiceMatrix / notes , - NiceArray .inherit:n = - { - NiceMatrix / Global , - NiceMatrix / Env , - } , - NiceArray / xdots .inherit:n = NiceMatrix / xdots , - NiceArray / rules .inherit:n = NiceMatrix / rules , - pNiceArray .inherit:n = - { - NiceMatrix / Global , - NiceMatrix / Env , - } , - pNiceArray / xdots .inherit:n = NiceMatrix / xdots , - pNiceArray / rules .inherit:n = NiceMatrix / rules , - } -% \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 } - { - delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , - delimiters / color .value_required:n = true , - delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , - delimiters / max-width .default:n = true , - delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , - delimiters .value_required:n = true , - width .code:n = \dim_set:Nn \l_@@_width_dim { #1 } , - width .value_required:n = true , - 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} -% -% \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} (these 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 , - 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 , - matrix / columns-type .code:n = - \@@_set_preamble:Nn \l_@@_columns_type_tl { #1 }, - matrix / columns-type .value_required:n = true , - caption-above .bool_set:N = \l_@@_caption_above_bool , - caption-above .default:n = true , - unknown .code:n = \@@_error:n { Unknown~key~for~NiceMatrixOptions } - } -% \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|''. -% That set of keys will be used by |{NiceMatrix}|, |{pNiceMatrix}|, -% |{bNiceMatrix}|, etc. -% -% \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 } } , - columns-type .code:n = \@@_set_preamble:Nn \l_@@_columns_type_tl { #1 } , - columns-type .value_required:n = true , - l .meta:n = { columns-type = l } , - r .meta:n = { columns-type = r } , - delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , - delimiters / color .value_required:n = true , - delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , - delimiters / max-width .default:n = true , - delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , - delimiters .value_required:n = true , - 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 , - 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 , - delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , - delimiters / color .value_required:n = true , - delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , - delimiters / max-width .default:n = true , - delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , - delimiters .value_required:n = true , - 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. -% If there is no column of type |X|, an error will be raised. -% \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 , - rounded-corners .dim_set:N = \l_@@_tab_rounded_corners_dim , - rounded-corners .default:n = 4 pt , - notes .code:n = \keys_set:nn { NiceMatrix / notes } { #1 } , - tabularnote .tl_gset:N = \g_@@_tabularnote_tl , - tabularnote .value_required:n = true , - caption .tl_set:N = \l_@@_caption_tl , - caption .value_required:n = true , - short-caption .tl_set:N = \l_@@_short_caption_tl , - short-caption .value_required:n = true , - label .tl_set:N = \l_@@_label_tl , - label .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} -% |\g_@@_cell_after_hook_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. -% \begin{macrocode} - \tl_gclear:N \g_@@_cell_after_hook_tl -% \end{macrocode} -% At the beginning of the cell, we link |\CodeAfter| to a command which do -% begin with |\\| (whereas the standard version of |\CodeAfter| does -% not). -% \begin{macrocode} - \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: -% \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|. 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} -% -% \begin{macrocode} - \g_@@_row_style_tl -% \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} - \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: - { - \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: - \@@_cell_end_i: - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_cell_end_i: - { -% \end{macrocode} -% The token list |\g_@@_cell_after_hook_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_@@_cell_after_hook_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 for the columns of type |p|, |m|, |b|, |V| (of \pkg{varwidth}) or |X|, -% we test whether the cell is syntactically empty with |\@@_test_if_empty:| and -% |\@@_test_if_empty_for_S:| -% \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|, |\llap|, |\clap| -% 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} -% -% \bigskip -% The following variant of |\@@_cell_end:| is only for the columns of type -% |w{s}{...}| or |W{s}{...}| (which use the horizontal alignement key |s| of -% |\makebox|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_cell_end_for_w_s: - { - \@@_math_toggle_token: - \hbox_set_end: - \bool_if:NF \g_@@_rotate_bool - { - \hbox_set:Nn \l_@@_cell_box - { - \makebox [ \l_@@_col_width_dim ] [ s ] - { \hbox_unpack_drop:N \l_@@_cell_box } - } - } - \@@_cell_end_i: - } -% \end{macrocode} -% -% -% \bigskip -% The following command creates the \textsc{pgf} name of the node with, of -% course, |\l_@@_cell_box| as the content. -% \begin{macrocode} -\pgfset - { - nicematrix / cell-node /.style = - { - inner~sep = \c_zero_dim , - minimum~width = \c_zero_dim - } - } -\cs_new_protected:Npn \@@_node_for_cell: - { - \pgfpicture - \pgfsetbaseline \c_zero_dim - \pgfrememberpicturepositiononpagetrue - \pgfset { nicematrix / cell-node } - \pgfnode - { rectangle } - { base } - { -% \end{macrocode} -% The following instruction |\set@color| has been added on 2022/10/06. It's -% necessary only with XeLaTeX and not with the other engines (we don't know why). -% \begin{macrocode} - \set@color - \box_use_drop:N \l_@@_cell_box - } - { \@@_env: - \int_use:N \c@iRow - \int_use:N \c@jCol } - { \l_@@_pgf_node_code_tl } - \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} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_array:n - { - \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 ] - } -\cs_generate_variant:Nn \@@_array:n { V } -% \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: - { - \int_compare:nNnT \c@iRow > \g_@@_last_row_node_int - { - \int_gset_eq:NN \g_@@_last_row_node_int \c@iRow - \@@_create_row_node_i: - } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_create_row_node_i: - { -% \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 - \int_eval:n { \c@iRow + 1 } } - \skip_vertical:N -0.5\arrayrulewidth - } - } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgfcoordinate { \@@_env: - row - \int_eval:n { \c@iRow + 1 } } - { \pgfpoint \c_zero_dim { - 0.5 \arrayrulewidth } } - \str_if_empty:NF \l_@@_name_str - { - \pgfnodealias - { \l_@@_name_str - row - \int_eval:n { \c@iRow + 1 } } - { \@@_env: - row - \int_eval:n { \c@iRow + 1 } } - } - \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 now the rules of the key |hlines| (or |hvlines|) but we reserve the -% vertical space for theses rules (the rules will be drawn by \textsc{pgf}). -% \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 - { \int_eval:n { \c@iRow + 1 } } - } - { -% \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} -% -% \begin{macrocode} - \@@_expand_clist:N \l_@@_hlines_clist - \@@_expand_clist:N \l_@@_vlines_clist -% \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_i: } - \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 \l_@@_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 others) 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 \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 \@@_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 - \seq_map_inline:Nn \l_@@_custom_line_commands_seq - { \cs_set_eq:cc { ##1 } { nicematrix - ##1 } } - \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. -% \begin{macrocode} - \cs_set_eq:NN \multicolumn \@@_multicolumn:nnn - \hook_gput_code:nnn { env / tabular / begin } { . } - { \cs_set_eq:NN \multicolumn \@@_old_multicolumn } -% \end{macrocode} -% If there is one or several commands |\tabularnote| in the caption specified -% by the key |caption| and if that caption has to be composed above the tabular, -% we have now that information because it has been written in the |aux| file at -% a previous run. We use that information to start couting the tabular notes in -% the main array at the right value (that remember that the caption will be -% composed \emph{after} the array!). -% \begin{macrocode} - \tl_if_exist:NT \l_@@_note_in_caption_tl - { - \tl_if_empty:NF \l_@@_note_in_caption_tl - { - \int_set_eq:NN \l_@@_note_in_caption_int - { \l_@@_note_in_caption_tl } - \int_gset:Nn \c@tabularnote { \l_@@_note_in_caption_tl } - } - } -% \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:N \g_nicematrix_code_before_tl - \tl_gclear:N \g_@@_pre_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 \g_@@_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 \g_@@_size_seq 6 } } - } -% \end{macrocode} -% -% \bigskip -% If there is an 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_@@_cols_vlism_seq - \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} -% -% \bigskip -% The command |\create_row_node:| will create a row-node (and not a row of -% nodes!). However, at the end of the array we construct a ``false row'' (for -% the col-nodes) and it interfers with the construction of the last row-node -% of the array. We don't want to create such row-node twice (to avaid warnings -% or, maybe, errors). That's why the command |\@@_create_row_node:| will use the -% following counter to avoid such construction. -% \begin{macrocode} - \int_gset:Nn \g_@@_last_row_node_int { -2 } -% \end{macrocode} -% The value $-2$ is important. -% -% -% \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} -% -% -% \medskip -% We compute the width of both delimiters. We remind 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 \g_@@_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 |\@@_CodeBefore_Body:w| will be used when the keyword -% |\CodeBefore| is present at the beginning of the environment. -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_CodeBefore_Body:w #1 \Body - { - \tl_gput_left:Nn \g_@@_pre_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 -% \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 \g_@@_size_seq 2 } - \int_set:Nn \c@jCol { \seq_item:Nn \g_@@_size_seq 5 } - \int_set_eq:NN \g_@@_row_total_int { \seq_item:Nn \g_@@_size_seq 3 } - \int_set_eq:NN \g_@@_col_total_int { \seq_item:Nn \g_@@_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} -% -% \medskip -% Now, the recreation of the nodes of the blocks \emph{which have a name}. -% \begin{macrocode} - \@@_create_blocks_nodes: -% \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 - \cs_set_eq:NN \ShowCellNames \@@_ShowCellNames - } -% \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 |\CodeBefore| in math mode in order to nullify the spaces put -% by the user between instructions in the |\CodeBefore|. -% \begin{macrocode} - \bool_if:NT \l_@@_NiceTabular_bool \c_math_toggle_token -% \end{macrocode} -% -% \bigskip -% The following code is a security for the case the user has used \pkg{babel} -% with the option \pkg{spanish}: in that case, the characters |<| (de code -% \textsc{ascci} 60) and |>| are activated and Tikz is not able to solve the -% problem (even with the Tikz library \pkg{babel}). -% \begin{macrocode} - \int_compare:nNnT { \char_value_catcode:n { 60 } } = { 13 } - { - \@@_rescan_for_spanish:N \g_@@_pre_code_before_tl - \@@_rescan_for_spanish:N \l_@@_code_before_tl - } -% \end{macrocode} -% -% Here is the |\CodeBefore|. The construction is a bit complicated because -% |\g_@@_pre_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 |\g_@@_pre_code_before_tl| (when it is asked for the creation -% of cell nodes in the |\CodeBefore|). That's why we use a |\q_stop|: it -% will be used to discard the rest of |\g_@@_pre_code_before_tl|. -% \begin{macrocode} - \exp_last_unbraced:NV \@@_CodeBefore_keys: - \g_@@_pre_code_before_tl -% \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: - \l_@@_code_before_tl - \q_stop - \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~CodeBefore } - } -% \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: } - } - } - } - \int_step_inline:nn \c@iRow - { - \pgfnodealias - { \@@_env: - ##1 - last } - { \@@_env: - ##1 - \int_use:N \c@jCol } - } - \int_step_inline:nn \c@jCol - { - \pgfnodealias - { \@@_env: - last - ##1 } - { \@@_env: - \int_use:N \c@iRow - ##1 } - } - \@@_create_extra_nodes: - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_create_blocks_nodes: - { - \pgfpicture - \pgf@relevantforpicturesizefalse - \pgfrememberpicturepositiononpagetrue - \seq_map_inline:Nn \g_@@_pos_of_blocks_seq - { \@@_create_one_block_node:nnnnn ##1 } - \endpgfpicture - } -% \end{macrocode} -% -% The following command is called |\@@_create_one_block_node:nnnnn| but, in -% fact, it creates a node only if the last argument (|#5|) which is the name of -% the block, is not empty.\footnote{Moreover, there is also in the list -% |\g_@@_pos_of_blocks_seq| the positions of the dotted lines (created by -% |\Cdots|, etc.) and, for these entries, there is, of course, no name (the -% fifth component is empty).} -% \begin{macrocode} -\cs_new_protected:Npn \@@_create_one_block_node:nnnnn #1 #2 #3 #4 #5 - { - \tl_if_empty:nF { #5 } - { - \@@_qpoint:n { col - #2 } - \dim_set_eq:NN \l_tmpa_dim \pgf@x - \@@_qpoint:n { #1 } - \dim_set_eq:NN \l_tmpb_dim \pgf@y - \@@_qpoint:n { col - \int_eval:n { #4 + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x - \@@_qpoint:n { \int_eval:n { #3 + 1 } } - \dim_set_eq:NN \l_@@_tmpd_dim \pgf@y - \@@_pgf_rect_node:nnnnn - { \@@_env: - #5 } - { \dim_use:N \l_tmpa_dim } - { \dim_use:N \l_tmpb_dim } - { \dim_use:N \l_@@_tmpc_dim } - { \dim_use:N \l_@@_tmpd_dim } - } - } -% \end{macrocode} -% -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_for_revtex: - { - \cs_set_eq:NN \@addamp \@addamp@LaTeX - \cs_set_eq:NN \insert@column \insert@column@array - \cs_set_eq:NN \@classx \@classx@array - \cs_set_eq:NN \@xarraycr \@xarraycr@array - \cs_set_eq:NN \@arraycr \@arraycr@array - \cs_set_eq:NN \@xargarraycr \@xargarraycr@array - \cs_set_eq:NN \array \array@array - \cs_set_eq:NN \@array \@array@array - \cs_set_eq:NN \@tabular \@tabular@array - \cs_set_eq:NN \@mkpream \@mkpream@array - \cs_set_eq:NN \endarray \endarray@array - \cs_set:Npn \@tabarray { \@ifnextchar [ { \@array } { \@array [ c ] } } - \cs_set:Npn \endtabular { \endarray $\egroup} % $ - } -% \end{macrocode} -% -% -% \bigskip -% \subsection*{The environment \{NiceArrayWithDelims\}} -% -% \begin{macrocode} -\NewDocumentEnvironment { NiceArrayWithDelims } - { m m O { } m ! O { } t \CodeBefore } - { - \bool_if:NT \c_@@_revtex_bool \@@_patch_for_revtex: -% \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 } } - \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 - } - \tl_if_empty:NF \g_@@_pre_code_before_tl - { \bool_set_true:N \l_@@_code_before_bool } -% \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 \g_@@_NiceArray_bool - { \keys_set:nn { NiceMatrix / NiceArray } } - { \keys_set:nn { NiceMatrix / pNiceArray } } - { #3 , #5 } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \@@_set_CT@arc@:V \l_@@_rules_color_tl -% \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 |\@@_CodeBefore_Body:w|. After that job, the command |\@@_CodeBefore_Body:w| -% will go on with |\@@_pre_array:|. -% \begin{macrocode} - \IfBooleanTF { #6 } \@@_CodeBefore_Body:w \@@_pre_array: - } -% \end{macrocode} -% -% Now, the second part of the environment |{NiceArrayWithDelims}|. -% \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_or_warning: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 -% actual 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 |\g_@@_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 \g_@@_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 - \@@_color:V \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 - \arrayrulewidth } - \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 + \arrayrulewidth } - } -% \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} - \@@_color:V \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 - { \@@_warning_gredirect_none:n { columns~not~used } } - } - \@@_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 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} -% -% \bigskip -% The transformation of the preamble is an operation in several -% steps.\footnote{Be careful: the transformation of the preamble may also have -% by-side effects, for example, the boolean |\g_@@_NiceArray_bool| will be set -% to |false| if we detect in the preamble a delimiter at the beginning or at the -% end.} -% -% \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 \@@_transform_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 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 to use 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} -% -% \bigskip -% If the package \pkg{varwidth} has defined the column type |V|, we protect from -% expansion by redefining it to |\@@_V:| (which will be catched by our system). -% \begin{macrocode} - \cs_if_exist:NT \NC@find@V { \@@_newcolumntype V { \@@_V: } } -% \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} -% -% \bigskip -% The following sequence will store the arguments of the successive |>| in the -% preamble. -% \begin{macrocode} - \tl_gclear_new:N \g_@@_pre_cell_tl -% \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_gset_false:N \g_@@_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 - { - \g_@@_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 - { - \g_@@_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*}| (we control that with the value of -% |\l_@@_tabular_width_dim|). -% \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 -% The command |\@@_patch_preamble:n| is the main function for the transformation -% of the preamble. It is recursive. -% \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_xiv:n } - ! { \@@_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 } - \@@_V: { \@@_patch_preamble_v:n } - V { \@@_patch_preamble_v:n } - \@@_w: { \@@_patch_preamble_vi:nnnn { } #1 } - \@@_W: { \@@_patch_preamble_vi:nnnn { \@@_special_W: } #1 } - \@@_S: { \@@_patch_preamble_vii:n } - ( { \@@_patch_preamble_viii:nn #1 } - [ { \@@_patch_preamble_viii:nn #1 } - \{ { \@@_patch_preamble_viii:nn #1 } - \left { \@@_patch_preamble_viii:nn } - ) { \@@_patch_preamble_ix:nn #1 } - ] { \@@_patch_preamble_ix:nn #1 } - \} { \@@_patch_preamble_ix:nn #1 } - \right { \@@_patch_preamble_ix:nn } - X { \@@_patch_preamble_x:n } -% \end{macrocode} -% When \pkg{tabularx} is loaded, a local redefinition of the specifier |X| is -% done to replace |X| by |\@@_X|. Thus, our column type |X| will be used in the -% |{NiceTabularX}|. -% \begin{macrocode} - \@@_X { \@@_patch_preamble_x:n } - \q_stop { } - } - { - \str_if_eq:nVTF { #1 } \l_@@_letter_vlism_tl - { - \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 - } -% \end{macrocode} -% Now the case of a letter set by the final user for a customized rule. Such -% customized rule is defined by using the key |custom-line| in -% |\NiceMatrixOptions|. That key takes in as value a list of \textsl{key=value} -% pairs. Among the keys avalaible in that list, there is the key |letter|. All -% the letters defined by this way by the final user for such customized rules -% are added in the set of keys |{NiceMatrix/ColumnTypes}|. That set of keys is -% used to store the characteristics of those types of rules for convenience: the -% keys of that set of keys won't never be used as keys by the final user (he -% will use, instead, letters in the preamble of its array). -% \begin{macrocode} - { - \keys_if_exist:nnTF { NiceMatrix / ColumnTypes } { #1 } - { - \keys_set:nn { NiceMatrix / ColumnTypes } { #1 } - \@@_patch_preamble:n - } - { - \tl_if_eq:nnT { #1 } { S } - { \@@_fatal:n { unknown~column~type~S } } - { \@@_fatal:nn { unknown~column~type } { #1 } } - } - } - } - } -% \end{macrocode} -% -% -% \bigskip -% Now, we will list all the auxiliary functions for the different types of -% entries in the preamble of the array. -% -% \medskip -% For |c|, |l| and |r| -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_i:n #1 - { - \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \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_xi: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 | } - { - \dim_set:Nn \l_tmpa_dim - { - \arrayrulewidth * \l_tmpa_int - + \doublerulesep * ( \l_tmpa_int - 1) - } - \tl_gput_right:Nx \g_@@_preamble_tl - { -% \end{macrocode} -% Here, the command |\dim_eval:n| is mandatory. -% \begin{macrocode} - \exp_not:N ! { \skip_horizontal:n { \dim_eval:n { \l_tmpa_dim } } } - } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { - \@@_vline:n - { - position = \int_eval:n { \c@jCol + 1 } , - multiplicity = \int_use:N \l_tmpa_int , - total-width = \dim_use:N \l_tmpa_dim % added 2022-08-06 - } -% \end{macrocode} -% We don't have provided value for |start| nor for |end|, which means that the -% rule will cover (potentially) all the rows of the array. -% -% \begin{macrocode} - } - \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} -\cs_new_protected:Npn \@@_patch_preamble_xiv:n #1 - { - \tl_gput_right:Nn \g_@@_pre_cell_tl { > { #1 } } - \@@_patch_preamble:n - } -% \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|, |b|, |V| and |X|) have an -% optional argument between square brackets for a list of -% \emph{key}-\emph{value} pairs. Here are the corresponding keys. -% \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 , - R .code:n = - \IfPackageLoadedTF { ragged2e } - { \str_set:Nn \l_@@_hpos_col_str { R } } - { - \@@_error_or_warning:n { ragged2e~not~loaded } - \str_set:Nn \l_@@_hpos_col_str { r } - } , - R .value_forbidden:n = true , - L .code:n = - \IfPackageLoadedTF { ragged2e } - { \str_set:Nn \l_@@_hpos_col_str { L } } - { - \@@_error_or_warning:n { ragged2e~not~loaded } - \str_set:Nn \l_@@_hpos_col_str { l } - } , - L .value_forbidden:n = true , - C .code:n = - \IfPackageLoadedTF { ragged2e } - { \str_set:Nn \l_@@_hpos_col_str { C } } - { - \@@_error_or_warning:n { ragged2e~not~loaded } - \str_set:Nn \l_@@_hpos_col_str { c } - } , - C .value_forbidden:n = true , - S .code:n = \str_set:Nn \l_@@_hpos_col_str { si } , - S .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|, |r|, |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 } - \tl_set:Nn \l_tmpa_tl { #1 } - \tl_replace_all:Nnn \l_tmpa_tl { \@@_S: } { S } - \@@_keys_p_column:V \l_tmpa_tl - \@@_patch_preamble_iv_iv:nn { #2 } { minipage } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_keys_p_column:n #1 - { \keys_set_known:nnN { WithArrows / p-column } { #1 } \l_tmpa_tl } -\cs_generate_variant:Nn \@@_keys_p_column:n { V } -% \end{macrocode} -% -% \medskip -% The first argument is the width of the column. The second is the type of -% environment: |minipage| or |varwidth|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_iv_iv:nn #1 #2 - { - \use:x - { - \@@_patch_preamble_iv_v:nnnnnnnn - { \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 - { \str_lowercase:V \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 } - 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: } - { #2 } - { - \str_case:VnF \l_@@_hpos_col_str - { - { j } { c } - { si } { c } - } -% \end{macrocode} -% We use |\str_lowercase:n| to convert |R| to |r|, etc. -% \begin{macrocode} - { \str_lowercase:V \l_@@_hpos_col_str } - } - } -% \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_xi:n - } -% \end{macrocode} -% -% \medskip -% |#1| is the optional argument of |{minipage}| (or |{varwidth}|): |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}| (or |{varwidth}|), 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). It's also possible -% to put in that |#3| some code to fix the value of |\l_@@_hpos_cell_str| which -% will be available in each cell of the column. -% -% |#4| is an extra-code which contains |\@@_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| (or |r| or |l|: see |#8|). -% -% |#6| is a code put just after the |c| (or |r| or |l|: see |#8|). -% -% |#7| is the type of environment: |minipage| or |varwidth|. -% -% |#8| is the letter |c| or |r| or |l| which is the basic specificier of column -% which is used \emph{in fine}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_iv_v:nnnnnnnn #1 #2 #3 #4 #5 #6 #7 #8 - { - \str_if_eq:VnTF \l_@@_hpos_col_str { si } - { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_test_if_empty_for_S: } } } - { \tl_gput_right:Nn \g_@@_preamble_tl { > { \@@_test_if_empty: } } } - \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \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 { #7 } [ #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|, |\RaggedRight|, etc.). -% \begin{macrocode} - #3 -% \end{macrocode} -% The following code is to allow something like |\centering| in |\RowStyle|. -% \begin{macrocode} - \g_@@_row_style_tl - \arraybackslash - #5 - } - #8 - < { - #6 -% \end{macrocode} -% The following line has been taken from |array.sty|. -% \begin{macrocode} - \@finalstrut \@arstrutbox - % \bool_if:NT \g_@@_rotate_bool { \raggedright \hsize = 3 cm } - \end { #7 } -% \end{macrocode} -% If the letter in the preamble is |m|, |#4| will be equal to -% |\@@_center_cell_box:| (see just below). -% \begin{macrocode} - #4 - \@@_cell_end: - } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_if_empty: \ignorespaces #1 - { - \peek_meaning:NT \unskip - { - \tl_gput_right:Nn \g_@@_cell_after_hook_tl - { - \box_set_wd:Nn \l_@@_cell_box \c_zero_dim -% \end{macrocode} -% We put the following code in order to have a column with the correct width -% even when all the cells of the column are empty. -% \begin{macrocode} - \skip_horizontal:N \l_@@_col_width_dim - } - } - #1 - } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_if_empty_for_S: #1 - { - \peek_meaning:NT \__siunitx_table_skip:n - { - \tl_gput_right:Nn \g_@@_cell_after_hook_tl - { \box_set_wd:Nn \l_@@_cell_box \c_zero_dim } - } - #1 - } -% \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_@@_cell_after_hook_tl|, we require a -% post-action of the box |\l_@@_cell_box|. -% \begin{macrocode} - \tl_gput_right:Nn \g_@@_cell_after_hook_tl - { - \int_compare:nNnT - { \box_ht:N \l_@@_cell_box } - > -% \end{macrocode} -% Previously, we had |\@arstrutbox| and not |\strutbox| in the following line -% but the code in \pkg{array} has changed in v 2.5g and we follow the change -% (see \emph{array: Correctly identify single-line m-cells} in LaTeX~News~36). -% \begin{macrocode} - { \box_ht:N \strutbox } - { - \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 |V| (similar to the |V| of \pkg{varwidth}). -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_v:n #1 - { - \str_if_eq:nnTF { #1 } { [ } - { \@@_patch_preamble_v_i:w [ } - { \@@_patch_preamble_v_i:w [ ] { #1 } } - } -\cs_new_protected:Npn \@@_patch_preamble_v_i:w [ #1 ] - { \@@_patch_preamble_v_ii:nn { #1 } } -\cs_new_protected:Npn \@@_patch_preamble_v_ii:nn #1 #2 - { - \str_set:Nn \l_@@_vpos_col_str { p } - \str_set:Nn \l_@@_hpos_col_str { j } - \tl_set:Nn \l_tmpa_tl { #1 } - \tl_replace_all:Nnn \l_tmpa_tl { \@@_S: } { S } - \@@_keys_p_column:V \l_tmpa_tl - \bool_if:NTF \c_@@_varwidth_loaded_bool - { \@@_patch_preamble_iv_iv:nn { #2 } { varwidth } } - { - \@@_error_or_warning:n { varwidth~not~loaded } - \@@_patch_preamble_iv_iv:nn { #2 } { minipage } - } - } -% \end{macrocode} -% -% \medskip -% For |w| and |W| -% -% |#1| is a special argument: empty for |w| and equal to |\@@_special_W:| for |W|; -% -% |#2| is the type of column (|w| or |W|); -% -% |#3| is the type of horizontal alignment (|c|, |l|, |r| or |s|); -% -% |#4| is the width of the column. -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_vi:nnnn #1 #2 #3 #4 - { - \str_if_eq:nnTF { #3 } { s } - { \@@_patch_preamble_vi_i:nnnn { #1 } { #4 } } - { \@@_patch_preamble_vi_ii:nnnn { #1 } { #2 } { #3 } { #4 } } - } -% \end{macrocode} -% -% \bigskip -% First, the case of an horizontal alignment equal to |s| (for \emph{stretch}). -% -% |#1| is a special argument: empty for |w| and equal to |\@@_special_W:| for -% |W|; -% -% |#2| is the width of the column. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_vi_i:nnnn #1 #2 - { - \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_preamble_tl - { - > { - \dim_set:Nn \l_@@_col_width_dim { #2 } - \@@_cell_begin:w - \str_set:Nn \l_@@_hpos_cell_str { c } - } - c - < { - \@@_cell_end_for_w_s: - #1 - \@@_adjust_size_box: - \box_use_drop:N \l_@@_cell_box - } - } - \int_gincr:N \c@jCol - \@@_patch_preamble_xi:n - } -% \end{macrocode} -% -% \bigskip -% Then, the most important version, for the horizontal alignments types of |c|, -% |l| and |r| (and not |s|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_vi_ii:nnnn #1 #2 #3 #4 - { - \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \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: - \hbox_set_end: - % The following line is probably pointless - % \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: - #1 - \@@_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_xi:n - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_special_W: - { - \dim_compare:nNnT { \box_wd:N \l_@@_cell_box } > \l_@@_col_width_dim - { \@@_warning:n { W~warning } } - } -% \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_vii:n #1 - { - \str_if_eq:nnTF { #1 } { [ } - { \@@_patch_preamble_vii_i:w [ } - { \@@_patch_preamble_vii_i:w [ ] { #1 } } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_vii_i:w [ #1 ] - { \@@_patch_preamble_vii_ii:n { #1 } } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_vii_ii:n #1 - { -% \end{macrocode} -% We test whether the version of \pkg{nicematrix} is at least 3.0. We will -% change the programmation of the test further with something like |\@ifpackagelater|. -% -% \begin{macrocode} - \cs_if_exist:NTF \siunitx_cell_begin:w - { - \tl_gput_right:NV \g_@@_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \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_xi:n - } - { \@@_fatal:n { Version~of~siunitx~too~old } } - } -% \end{macrocode} -% -% -% \medskip -% For |(|, |[| and |\{|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_viii: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_viii_i:nn { #1 } { #2 } - } - } - { \@@_patch_preamble_viii_i:nn { #1 } { #2 } } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_viii_i:nn #1 #2 - { - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { \@@_delimiter:nnn #1 { \int_eval:n { \c@jCol + 1 } } \c_true_bool } - \tl_if_in:nnTF { ( [ \{ ) ] \} \left \right } { #2 } - { - \@@_error:nn { delimiter~after~opening } { #2 } - \@@_patch_preamble:n - } - { \@@_patch_preamble:n #2 } - } -% \end{macrocode} -% -% \bigskip -% For the closing delimiters. 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_ix:nn #1 #2 - { - \bool_if:NT \l_@@_small_bool { \@@_fatal:n { Delimiter~with~small } } - \tl_if_in:nnTF { ) ] \} } { #2 } - { \@@_patch_preamble_ix_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_@@_pre_code_after_tl - { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } - \@@_patch_preamble:n #2 - } - } - { - \tl_if_in:nnT { ( [ \{ \left } { #2 } - { \tl_gput_right:Nn \g_@@_preamble_tl { ! { \enskip } } } - \tl_gput_right:Nx \g_@@_pre_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_ix_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_@@_pre_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_@@_pre_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_@@_pre_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_x:n #1 - { - \str_if_eq:nnTF { #1 } { [ } - { \@@_patch_preamble_x_i:w [ } - { \@@_patch_preamble_x_i:w [ ] #1 } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_x_i:w [ #1 ] - { \@@_patch_preamble_x_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_x_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} (now obsolete) or \pkg{tabularray}. -% \begin{macrocode} - \int_zero_new:N \l_@@_weight_int - \int_set:Nn \l_@@_weight_int { 1 } - \tl_set:Nn \l_tmpa_tl { #1 } - \tl_replace_all:Nnn \l_tmpa_tl { \@@_S: } { S } - \@@_keys_p_column:V \l_tmpa_tl - \keys_set:nV { WithArrows / X-column } \l_tmpa_tl - \int_compare:nNnT \l_@@_weight_int < 0 - { - \@@_error_or_warning:n { negative~weight } - \int_set:Nn \l_@@_weight_int { - \l_@@_weight_int } - } - \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 - { - \exp_args:Nnx - \@@_patch_preamble_iv_iv:nn - { \l_@@_weight_int \l_@@_X_columns_dim } - { minipage } - } - { - \tl_gput_right:Nn \g_@@_preamble_tl - { - > { - \@@_cell_begin:w - \bool_set_true:N \l_@@_X_column_bool -% \end{macrocode} -% You encounter a problem on 2023-03-04: for an environment with |X| columns, -% during the first compilations (which are not the definitive one), sometimes, -% some cells are declared empty even if they should not. That's a problem -% because user's instructions may use these nodes. That's why we have added the -% following |\NotEmpty|. -% \begin{macrocode} - \NotEmpty -% \end{macrocode} -% The following code will nullify the box of the cell. -% \begin{macrocode} - \tl_gput_right:Nn \g_@@_cell_after_hook_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_xi: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. In fact, we have -% also to test whether there is, after the |<{...}|, a |@{...}|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_xi:n #1 - { - \str_if_eq:nnTF { #1 } { < } - \@@_patch_preamble_xiii:n - { - \str_if_eq:nnTF { #1 } { @ } - \@@_patch_preamble_xv: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 { \int_eval:n { \c@jCol + 1 } } - { - \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_xiii:n #1 - { - \tl_gput_right:Nn \g_@@_preamble_tl { < { #1 } } - \@@_patch_preamble_xi:n - } -% \end{macrocode} -% -% We have to catch a |@{...}| after a specifier of column because, if we have to -% draw a vertical rule, we have to add in that |@{...}| a |\hskip| corresponding -% to the width of the vertical rule. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_preamble_xv:n #1 - { - \tl_if_eq:NnTF \l_@@_vlines_clist { all } - { - \tl_gput_right:Nn \g_@@_preamble_tl - { @ { #1 \skip_horizontal:N \arrayrulewidth } } - } - { - \exp_args:NNx - \clist_if_in:NnTF \l_@@_vlines_clist { \int_eval:n { \c@jCol + 1 } } - { - \tl_gput_right:Nn \g_@@_preamble_tl - { @ { #1 \skip_horizontal:N \arrayrulewidth } } - } - { \tl_gput_right:Nn \g_@@_preamble_tl { @ { #1 } } } - } - \@@_patch_preamble:n - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_set_preamble:Nn #1 #2 - { - \group_begin: - \@@_newcolumntype w [ 2 ] { \@@_w: { ##1 } { ##2 } } - \@@_newcolumntype W [ 2 ] { \@@_W: { ##1 } { ##2 } } - \@temptokena { #2 } - \@tempswatrue - \@whilesw \if@tempswa \fi { \@tempswafalse \the \NC@list } - \tl_gclear:N \g_@@_preamble_tl - \exp_after:wN \@@_patch_m_preamble:n \the \@temptokena \q_stop - \group_end: - \tl_set_eq:NN #1 \g_@@_preamble_tl - } -% \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} -% -% \begin{macrocode} - \@@_newcolumntype w [ 2 ] { \@@_w: { ##1 } { ##2 } } - \@@_newcolumntype W [ 2 ] { \@@_W: { ##1 } { ##2 } } -% \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 - \int_eval:n { \c@jCol + 1 } } - \seq_gput_left:Nn \g_@@_multicolumn_sizes_seq { #1 } - \seq_gput_right:Nx \g_@@_pos_of_blocks_seq - { - { - \int_compare:nNnTF \c@jCol = 0 - { \int_eval:n { \c@iRow + 1 } } - { \int_use:N \c@iRow } - } - { \int_eval:n { \c@jCol + 1 } } - { - \int_compare:nNnTF \c@jCol = 0 - { \int_eval:n { \c@iRow + 1 } } - { \int_use:N \c@iRow } - } - { \int_eval:n { \c@jCol + #1 } } - { } % for the name of the block - } - } -% \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 { \@@_special_W: } #1 } - \q_stop { } - } - { - \tl_if_eq:nnT { #1 } { S } - { \@@_fatal:n { unknown~column~type~S } } - { \@@_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 - { - > { - \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: - \hbox_set_end: - \bool_if:NT \g_@@_rotate_bool \@@_rotate_cell_box: - #1 - \@@_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} -% -% -% After a specifier of column, we have to test whether there is one or several -% |<{..}|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_patch_m_preamble_x:n #1 - { - \str_if_eq:nnTF { #1 } { < } - \@@_patch_m_preamble_ix:n - { \@@_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 - \int_eval:n { \c@iRow + 1 } } - \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 \g_@@_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 } - \bool_if:NT \l_@@_caption_above_bool - { - \tl_if_empty:NF \l_@@_caption_tl - { -% \end{macrocode} -% \begin{macrocode} - \bool_set_false:N \g_@@_caption_finished_bool - \int_gzero:N \c@tabularnote - \@@_insert_caption: -% \end{macrocode} -% If there is one or several commands |\tabularnote| in the caption, we will -% write in the |aux| file the number of such tabular notes. -% \begin{macrocode} - \int_gset:Nn \c@tabularnote - { \seq_count:N \g_@@_notes_in_caption_seq } - \int_compare:nNnF \c@tabularnote = 0 - { - \tl_gput_right:Nx \g_@@_aux_tl - { - \tl_set:Nn \exp_not:N \l_@@_note_in_caption_tl - { \int_eval:n { \c@tabularnote } } - } - } - } - } -% \end{macrocode} -% The |\hbox| avoids that the |pgfpicture| inside |\@@_draw_blocks| adds a extra -% vertical space before the notes. -% \begin{macrocode} - \hbox - { - \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: - } -% \end{macrocode} -% We don't do the following test with |\c@tabularnote| because the value of that -% counter is not reliable when the command |\ttabbox| of \pkg{floatrow} is used -% (because |\ttabbox| de-activate |\stepcounter| because if compiles several -% twice its tabular). -% \begin{macrocode} - \bool_lazy_any:nT - { - { ! \seq_if_empty_p:N \g_@@_notes_seq } - { ! \seq_if_empty_p:N \g_@@_notes_in_caption_seq } - { ! \tl_if_empty_p:V \g_@@_tabularnote_tl } - } - \@@_insert_tabularnotes: - \cs_set_eq:NN \tabularnote \@@_tabularnote_error:n - \bool_if:NF \l_@@_caption_above_bool \@@_insert_caption: - \end { minipage } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_insert_caption: - { - \tl_if_empty:NF \l_@@_caption_tl - { - \cs_if_exist:NTF \@captype - { \@@_insert_caption_i: } - { \@@_error:n { caption~outside~float } } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_insert_caption_i: - { - \group_begin: -% \end{macrocode} -% The flag |\l_@@_in_caption_bool| affects only the behaviour of the command -% |\tabularnote| when used in the caption. -% \begin{macrocode} - \bool_set_true:N \l_@@_in_caption_bool -% \end{macrocode} -% The package \pkg{floatrow} does a redefinition of |\@makecaption| which will -% extract the caption from the tabular. However, the old version of -% |\@makecaption| has been stored by \pkg{floatrow} in |\FR@makecaption|. That's -% why we restore the old version. -% \begin{macrocode} - \bool_if:NT \c_@@_floatrow_loaded_bool - { \cs_set_eq:NN \@makecaption \FR@makecaption } - \tl_if_empty:NTF \l_@@_short_caption_tl - { \caption { \l_@@_caption_tl } } - { \caption [ \l_@@_short_caption_tl ] { \l_@@_caption_tl } } - \tl_if_empty:NF \l_@@_label_tl { \label { \l_@@_label_tl } } - \group_end: - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_tabularnote_error:n #1 - { - \@@_error_or_warning:n { tabularnote~below~the~tabular } - \@@_gredirect_none:n { tabularnote~below~the~tabular } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_insert_tabularnotes: - { - \seq_gconcat:NNN \g_@@_notes_seq \g_@@_notes_in_caption_seq \g_@@_notes_seq - \int_set:Nn \c@tabularnote { \seq_count:N \g_@@_notes_seq } - \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 \g_@@_tabularnote_tl - { - \g_@@_tabularnote_tl \par - \tl_gclear:N \g_@@_tabularnote_tl - } -% \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_@@_notes_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_@@_notes_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_or_warning:n { bottomrule~without~booktabs } } - } - \l_@@_notes_code_after_tl - \seq_gclear:N \g_@@_notes_seq - \seq_gclear:N \g_@@_notes_in_caption_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 - { \box_ht_plus_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 - { \box_ht_plus_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_remove_spaces:n - { - \peek_meaning:NTF \end - \@@_analyze_end:Nn - { - \@@_transform_preamble: -% \end{macrocode} -% Here is the call to |\array| (we have a dedicated macro |\@@_array:n| because -% of compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}). -% \begin{macrocode} - \@@_array:V \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|). -% % \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:w #1 \CodeAfter \q_stop -% \end{macrocode} -% The command |\array| is hidden somewhere in |\@@_light_syntax_i:w|. -% \begin{macrocode} - } -% \end{macrocode} -% Now, the second part of the environment. We must leave these lines in the -% second part (and not put them in the first part even though we caught the -% whole body of the environment with an argument of type |b|) in order to have -% the columns |S| of \pkg{siunitx} working fine. -% \begin{macrocode} - { - \@@_create_col_nodes: - \endarray - } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_light_syntax_i:w #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_clear_new:N \l_@@_rows_seq -% \end{macrocode} -% We rescan the character of end of line in order to have the correct catcode. -% \begin{macrocode} - \tl_set_rescan:Nno \l_@@_end_of_row_tl { } \l_@@_end_of_row_tl - \seq_set_split:NVn \l_@@_rows_seq \l_@@_end_of_row_tl { #1 } -% \end{macrocode} -% We delete the last row if it is empty. -% \begin{macrocode} - \seq_pop_right:NN \l_@@_rows_seq \l_tmpa_tl - \tl_if_empty:NF \l_tmpa_tl - { \seq_put_right:NV \l_@@_rows_seq \l_tmpa_tl } -% \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 compute 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 \l_@@_rows_seq } } -% \end{macrocode} -% -% -% \bigskip -% The new value of the body (that is to say after replacement of the separators -% of rows and columns by |\\| and |&|) of the environment will be stored in -% |\l_@@_new_body_tl| (that part of the implementation has been changed in the -% version 6.11 of \pkg{nicematrix} in order to allow the use of commands such as -% |\hline| or |\hdottedline| with the key |light-syntax|). -% \begin{macrocode} - \tl_clear_new:N \l_@@_new_body_tl - \int_zero_new:N \l_@@_nb_cols_int -% \end{macrocode} -% First, we treat the first row. -% \begin{macrocode} - \seq_pop_left:NN \l_@@_rows_seq \l_tmpa_tl - \@@_line_with_light_syntax:V \l_tmpa_tl -% \end{macrocode} -% Now, the other rows (with the same treatment, excepted that we have to insert -% |\\| between the rows). -% \begin{macrocode} - \seq_map_inline:Nn \l_@@_rows_seq - { - \tl_put_right:Nn \l_@@_new_body_tl { \\ } - \@@_line_with_light_syntax:n { ##1 } - } -% \end{macrocode} -% -% \begin{macrocode} - \int_compare:nNnT \l_@@_last_col_int = { -1 } - { - \int_set:Nn \l_@@_last_col_int - { \l_@@_nb_cols_int - 1 + \l_@@_first_col_int } - } -% \end{macrocode} -% -% Now, we can construct the preamble: if the user has used the key |last-col|, -% we have the correct number of columns even though the user has used |last-col| -% without value. -% \begin{macrocode} - \@@_transform_preamble: -% \end{macrocode} -% -% The call to |\array| is in the following command (we have a dedicated macro -% |\@@_array:n| because of compatibility with the classes \cls{revtex4-1} and -% \cls{revtex4-2}). -% \begin{macrocode} - \@@_array:V \g_@@_preamble_tl \l_@@_new_body_tl - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_line_with_light_syntax:n #1 - { - \seq_clear_new:N \l_@@_cells_seq - \seq_set_split:Nnn \l_@@_cells_seq { ~ } { #1 } - \int_set:Nn \l_@@_nb_cols_int - { - \int_max:nn - \l_@@_nb_cols_int - { \seq_count:N \l_@@_cells_seq } - } - \seq_pop_left:NN \l_@@_cells_seq \l_tmpa_tl - \tl_put_right:NV \l_@@_new_body_tl \l_tmpa_tl - \seq_map_inline:Nn \l_@@_cells_seq - { \tl_put_right:Nn \l_@@_new_body_tl { & ##1 } } - } -\cs_generate_variant:Nn \@@_line_with_light_syntax:n { V } -% \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). When this command is used, |#1| is, in fact, always |\end|. -% \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 - \int_eval:n { \g_tmpa_int + 1 } } - \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 - \int_eval:n { \g_tmpa_int + 1 } } - { \pgfpoint { - 0.5 \arrayrulewidth } \c_zero_dim } - \str_if_empty:NF \l_@@_name_str - { - \pgfnodealias - { \l_@@_name_str - col - \int_eval:n { \g_tmpa_int + 1 } } - { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } - } - \endpgfpicture - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - & - \omit -% \end{macrocode} -% The two following lines have been added on 2021-12-15 to solve a bug -% mentionned by Joao Luis Soares by mail. -% \begin{macrocode} - \int_compare:nNnT \g_@@_col_total_int = 1 - { \skip_gset:Nn \g_tmpa_skip { 0 pt~plus 1 fill } } - \skip_horizontal:N \g_tmpa_skip - \int_gincr:N \g_tmpa_int - \bool_lazy_all:nT - { - \g_@@_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 \g_@@_NiceArray_bool - { \skip_horizontal:N -\arraycolsep } - \pgfsys@markposition - { \@@_env: - col - \int_eval:n { - \g_tmpa_int + 1 } } - \skip_horizontal:N 0.5\arrayrulewidth - \bool_lazy_and:nnT \l_@@_Matrix_bool \g_@@_NiceArray_bool - { \skip_horizontal:N \arraycolsep } - } - } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgfcoordinate { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } - { - \bool_lazy_and:nnTF \l_@@_Matrix_bool \g_@@_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 - \int_eval:n { \g_tmpa_int + 1 } } - { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } - } - \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 - \int_eval:n { \g_@@_col_total_int + 1 } } - } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgfcoordinate - { \@@_env: - col - \int_eval:n { \g_@@_col_total_int + 1 } } - \pgfpointorigin - \str_if_empty:NF \l_@@_name_str - { - \pgfnodealias - { - \l_@@_name_str - col - - \int_eval:n { \g_@@_col_total_int + 1 } - } - { \@@_env: - col - \int_eval:n { \g_@@_col_total_int + 1 } } - } - \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 -% begins with |\\| (whereas the standard version of |\CodeAfter| begins does -% not). -% \begin{macrocode} - \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: - \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 -% begins with |\\| (whereas the standard version of |\CodeAfter| begins does -% not). -% \begin{macrocode} - \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: -% \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 |\g_@@_NiceArray_bool|. -% In |{NiceArrayWithDelims}|, some special code will be executed if this flag is -% raised. -% \begin{macrocode} -\NewDocumentEnvironment { NiceArray } { } - { - \bool_gset_true:N \g_@@_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 -% |\g_@@_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 } { } - { - \bool_gset_false:N \g_@@_NiceArray_bool - \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_case:nnF \l_@@_last_col_int - { - { -2 } { \c@MaxMatrixCols } - { -1 } { \int_eval:n { \c@MaxMatrixCols + 1 } } -% \end{macrocode} -% The value $0$ can't occur here since we are in a matrix (which is an -% environment without preamble). -% \begin{macrocode} - } - { \int_eval:n { \l_@@_last_col_int - 1 } } - } - { #2 } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_generate_variant:Nn \@@_begin_of_NiceMatrix:nn { n V } -% \end{macrocode} -% -% \begin{macrocode} -\clist_map_inline:nn { p , b , B , v , V } - { - \NewDocumentEnvironment { #1 NiceMatrix } { ! O { } } - { - \bool_gset_false:N \g_@@_NiceArray_bool - \str_gset:Nn \g_@@_name_env_str { #1 NiceMatrix } - \keys_set:nn { NiceMatrix / NiceMatrix } { ##1 } - \@@_begin_of_NiceMatrix:nV { #1 } \l_@@_columns_type_tl - } - { \use:c { end #1 NiceArray } } - } -% \end{macrocode} -% -% \bigskip -% We define also an environment |{NiceMatrix}| -% \begin{macrocode} -\NewDocumentEnvironment { NiceMatrix } { ! O { } } - { - \bool_gset_false:N \g_@@_NiceArray_bool - \str_gset:Nn \g_@@_name_env_str { NiceMatrix } - \keys_set:nn { NiceMatrix / NiceMatrix } { #1 } - \@@_begin_of_NiceMatrix:nV { } \l_@@_columns_type_tl - } - { \endNiceArray } -% \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} -% If the dimension |\l_@@_width_dim| is equal to $0$~pt, that means that it has -% not be set by a previous use of |\NiceMatrixOptions|. -% \begin{macrocode} - \dim_compare:nNnT \l_@@_width_dim = \c_zero_dim - { \dim_set_eq:NN \l_@@_width_dim \linewidth } - \str_gset:Nn \g_@@_name_env_str { NiceTabular } - \keys_set:nn { NiceMatrix / NiceTabular } { #1 , #3 } - \int_compare:nNnT \l_@@_tab_rounded_corners_dim > \c_zero_dim - { - \bool_if:NT \l_@@_hvlines_bool - { - \bool_set_true:N \l_@@_except_borders_bool - % we should try to be more efficient in the number of lines of code here - \tl_if_empty:NTF \l_@@_rules_color_tl - { - \tl_gput_right:Nn \g_@@_pre_code_after_tl - { - \@@_stroke_block:nnn - { rounded-corners = \dim_use:N \l_@@_tab_rounded_corners_dim } - { 1-1 } - { \int_use:N \c@iRow - \int_use:N \c@jCol } - } - } - { - \tl_gput_right:Nn \g_@@_pre_code_after_tl - { - \@@_stroke_block:nnn - { - rounded-corners = \dim_use:N \l_@@_tab_rounded_corners_dim , - draw = \l_@@_rules_color_tl - } - { 1-1 } - { \int_use:N \c@iRow - \int_use:N \c@jCol } - } - } - } - } - \tl_if_empty:NF \l_@@_short_caption_tl - { - \tl_if_empty:NT \l_@@_caption_tl - { - \@@_error_or_warning:n { short-caption~without~caption } - \tl_set_eq:NN \l_@@_caption_tl \l_@@_short_caption_tl - } - } - \tl_if_empty:NF \l_@@_label_tl - { - \tl_if_empty:NT \l_@@_caption_tl - { \@@_error_or_warning:n { label~without~caption } } - } - \NewDocumentEnvironment { TabularNote } { b } - { - \bool_if:NTF \l_@@_in_code_after_bool - { \@@_error_or_warning:n { TabularNote~in~CodeAfter } } - { - \tl_if_empty:NF \g_@@_tabularnote_tl - { \tl_gput_right:Nn \g_@@_tabularnote_tl { \par } } - \tl_gput_right:Nn \g_@@_tabularnote_tl { ##1 } - } - } - { } - \bool_set_true:N \l_@@_NiceTabular_bool - \NiceArray { #2 } - } - { \endNiceArray } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_set_protected:Npn \@@_newcolumntype #1 - { - \cs_if_free:cT { NC @ find @ #1 } - { \NC@list \expandafter { \the \NC@list \NC@do #1 } } - \cs_set:cpn {NC @ find @ #1 } ##1 #1 { \NC@ { ##1 } } - \peek_meaning:NTF [ - { \newcol@ #1 } - { \newcol@ #1 [ 0 ] } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\NewDocumentEnvironment { NiceTabularX } { m O { } m ! O { } } - { -% \end{macrocode} -% The following code prevents the expansion of the `X` columns with the -% definition of that columns in \pkg{tabularx} (this would result in an error in -% |{NiceTabularX}|). -% \begin{macrocode} - \bool_if:NT \c_@@_tabularx_loaded_bool { \newcolumntype { X } { \@@_X } } - \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 \g_@@_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 -% used to recreate the blocks with a name in the |\CodeBefore| and also 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} -% -% \medskip -% We create the aliases using |last| for the nodes of the cells in the last row -% and the last column. -% \begin{macrocode} - \pgfpicture - \int_step_inline:nn \c@iRow - { - \pgfnodealias - { \@@_env: - ##1 - last } - { \@@_env: - ##1 - \int_use:N \c@jCol } - } - \int_step_inline:nn \c@jCol - { - \pgfnodealias - { \@@_env: - last - ##1 } - { \@@_env: - \int_use:N \c@iRow - ##1 } - } - \str_if_empty:NF \l_@@_name_str - { - \int_step_inline:nn \c@iRow - { - \pgfnodealias - { \l_@@_name_str - ##1 - last } - { \@@_env: - ##1 - \int_use:N \c@jCol } - } - \int_step_inline:nn \c@jCol - { - \pgfnodealias - { \l_@@_name_str - last - ##1 } - { \@@_env: - \int_use:N \c@iRow - ##1 } - } - } - \endpgfpicture -% \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_@@_xdots_radius_dim| and -% |\l_@@_xdots_inter_dim| (used to draw the dotted lines created by -% |\hdottedline| and |\vdottedline| 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_@@_xdots_radius_dim { 0.7 \l_@@_xdots_radius_dim } - \dim_set:Nn \l_@@_xdots_inter_dim { 0.55 \l_@@_xdots_inter_dim } -% \end{macrocode} -% The dimensions |\l_@@_xdots_shorten_start_dim| and -% |\l_@@_xdots_shorten_start_dim| correspond to the options -% |xdots/shorten-start| and |xdots/shorten-end| available to the user. -% \begin{macrocode} - \dim_set:Nn \l_@@_xdots_shorten_start_dim - { 0.6 \l_@@_xdots_shorten_start_dim } - \dim_set:Nn \l_@@_xdots_shorten_end_dim - { 0.6 \l_@@_xdots_shorten_end_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} -% -% \begin{macrocode} - \tl_if_empty:NF \l_@@_hlines_clist \@@_draw_hlines: - \tl_if_empty:NF \l_@@_vlines_clist \@@_draw_vlines: -% \end{macrocode} -% -% \bigskip -% Now, the pre-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 \ialign \@@_old_ialign: - \cs_set_eq:NN \SubMatrix \@@_SubMatrix - \cs_set_eq:NN \UnderBrace \@@_UnderBrace - \cs_set_eq:NN \OverBrace \@@_OverBrace - \cs_set_eq:NN \ShowCellNames \@@_ShowCellNames - \cs_set_eq:NN \line \@@_line - \g_@@_pre_code_after_tl - \tl_gclear:N \g_@@_pre_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 -% The following code is a security for the case the user has used \pkg{babel} -% with the option \pkg{spanish}: in that case, the characters |>| and |<| are -% activated and Tikz is not able to solve the problem (even with the Tikz -% library \pkg{babel}). -% \begin{macrocode} - \int_compare:nNnT { \char_value_catcode:n { 60 } } = { 13 } - { \@@_rescan_for_spanish:N \g_nicematrix_code_after_tl } -% \end{macrocode} -% \medskip -% 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} - \bool_set_true:N \l_@@_in_code_after_bool - \exp_last_unbraced:NV \@@_CodeAfter_keys: \g_nicematrix_code_after_tl - \scan_stop: - \tl_gclear:N \g_nicematrix_code_after_tl - \group_end: -% \end{macrocode} -% -% -% \medskip -% |\g_@@_pre_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_@@_pre_code_before_tl - { - \tl_gput_right:Nx \g_@@_aux_tl - { - \tl_gset:Nn \exp_not:N \g_@@_pre_code_before_tl - { \exp_not:V \g_@@_pre_code_before_tl } - } - \tl_gclear:N \g_@@_pre_code_before_tl - } - \tl_if_empty:NF \g_nicematrix_code_before_tl - { - \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 } - } - \tl_gclear:N \g_nicematrix_code_before_tl - } -% \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:nnnnn ##1 } - } -% \end{macrocode} -% -% The following command must \emph{not} be protected. -% \begin{macrocode} -\cs_new:Npn \@@_adjust_pos_of_blocks_seq_i:nnnnn #1 #2 #3 #4 #5 - { - { #1 } - { #2 } - { - \int_compare:nNnTF { #3 } > { 99 } - { \int_use:N \c@iRow } - { #3 } - } - { - \int_compare:nNnTF { #4 } > { 99 } - { \int_use:N \c@jCol } - { #4 } - } - { #5 } - } -% \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} -\hook_gput_code:nnn { begindocument } { . } - { - \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 -% 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 } -% \end{macrocode} -% Be careful: with |\Iddots|, |\l_@@_final_j_int| is inferior to -% |\l_@@_initial_j_int|. That's why we use |\int_min:nn| and |\int_max:nn|. -% \begin{macrocode} - { \int_min:nn \l_@@_initial_j_int \l_@@_final_j_int } - { \int_use:N \l_@@_final_i_int } - { \int_max:nn \l_@@_initial_j_int \l_@@_final_j_int } - { } % for the name of the block - } - } -% \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 we are analyzing. -% \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 - \int_eval:n { \l_@@_final_j_int + 1 } } - \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_@@_xdots_radius_dim - \dim_add:Nn \l_@@_y_final_dim \l_@@_xdots_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 - \int_eval:n { \l_@@_initial_i_int + 1 } } - \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 - { - \fp_to_dim:n - { - \pgf@y - + ( \box_ht:N \strutbox + \extrarowheight ) * \arraystretch - } - } % modified 6.13c - \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 - { \fp_to_dim:n { \pgf@y - ( \box_dp:N \strutbox ) * \arraystretch } } - % modified 6.13c - \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 - \int_eval:n { \l_@@_initial_j_int + 1 } } - \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: - \@@_open_x_initial_dim: - } - { \@@_set_initial_coords_from_anchor:n { south~east } } - \bool_if:NTF \l_@@_final_open_bool - { - \@@_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 - \bool_lazy_or:nnTF - { \tl_if_eq_p:NN \l_@@_xdots_line_style_tl \c_@@_standard_tl } - \l_@@_dotted_bool - \@@_draw_standard_dotted_line: - \@@_draw_unstandard_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_unstandard_dotted_line: - { - \begin { scope } - \@@_draw_unstandard_dotted_line:o - { \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_unstandard_dotted_line:n| is, in fact, the list of options. -% \begin{macrocode} -\cs_new_protected:Npn \@@_draw_unstandard_dotted_line:n #1 - { - \@@_draw_unstandard_dotted_line:nVV - { #1 } - \l_@@_xdots_up_tl - \l_@@_xdots_down_tl - } -\cs_generate_variant:Nn \@@_draw_unstandard_dotted_line:n { o } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_draw_unstandard_dotted_line:nnn #1 #2 #3 - { - \draw - [ - #1 , - shorten~> = \l_@@_xdots_shorten_end_dim , - shorten~< = \l_@@_xdots_shorten_start_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_unstandard_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_@@_xdots_inter_dim } - } - { - \int_set:Nn \l_tmpa_int - { - \dim_ratio:nn - { \l_@@_l_dim - \l_@@_xdots_shorten_start_dim } - \l_@@_xdots_inter_dim - } - } - } - { - \bool_if:NTF \l_@@_final_open_bool - { - \int_set:Nn \l_tmpa_int - { - \dim_ratio:nn - { \l_@@_l_dim - \l_@@_xdots_shorten_end_dim } - \l_@@_xdots_inter_dim - } - } - { - \int_set:Nn \l_tmpa_int - { - \dim_ratio:nn - { - \l_@@_l_dim - - \l_@@_xdots_shorten_start_dim - \l_@@_xdots_shorten_end_dim - } - \l_@@_xdots_inter_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_@@_xdots_inter_dim \l_@@_l_dim - } - \dim_set:Nn \l_tmpb_dim - { - ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) * - \dim_ratio:nn \l_@@_xdots_inter_dim \l_@@_l_dim - } -% \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_@@_xdots_inter_dim * \l_tmpa_int - + \l_@@_xdots_shorten_start_dim - \l_@@_xdots_shorten_end_dim - } - { 2 \l_@@_l_dim } - } - \dim_gadd:Nn \l_@@_y_initial_dim - { - ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) * - \dim_ratio:nn - { - \l_@@_l_dim - \l_@@_xdots_inter_dim * \l_tmpa_int - + \l_@@_xdots_shorten_start_dim - \l_@@_xdots_shorten_end_dim - } - { 2 \l_@@_l_dim } - } - \pgf@relevantforpicturesizefalse - \int_step_inline:nnn 0 \l_tmpa_int - { - \pgfpathcircle - { \pgfpoint \l_@@_x_initial_dim \l_@@_y_initial_dim } - { \l_@@_xdots_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 |\hook_gput_code:nnn { begindocument } { . }| -% and the \emph{arg spec} will be rescanned. -% -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \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 |\AddToHook|. -% -% -% \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} -\hook_gput_code:nnn { begindocument } { . } - { - \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} -% -% \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} -\hook_gput_code:nnn { begindocument } { . } - { - \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 |\AddToHook|. -% -% \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 the following behaviour: -% \begin{itemize} -% \item If the argument is of the format $i$-$j$, our command applies -% the command |\int_eval:n| to $i$ and~$j$ ; -% \item If not (that is to say, when it's a name of a |\Block|), the argument is -% left unchanged. -% \end{itemize} -% 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 - { - \tl_if_empty:nTF { #2 } - { #1 } - { \@@_double_int_eval_i:n #1-#2 \q_stop } - } -\cs_new:Npn \@@_double_int_eval_i: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} -\hook_gput_code:nnn { begindocument } { . } - { - \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} -\hook_gput_code:nnn { begindocument } { . } - { - \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*{The command \textbackslash RowStyle} -% -% \medskip -% \begin{macrocode} -\keys_define:nn { NiceMatrix / RowStyle } - { - cell-space-top-limit .dim_set:N = \l_tmpa_dim , - cell-space-top-limit .initial:n = \c_zero_dim , - cell-space-top-limit .value_required:n = true , - cell-space-bottom-limit .dim_set:N = \l_tmpb_dim , - cell-space-bottom-limit .initial:n = \c_zero_dim , - cell-space-bottom-limit .value_required:n = true , - cell-space-limits .meta:n = - { - cell-space-top-limit = #1 , - cell-space-bottom-limit = #1 , - } , - color .tl_set:N = \l_@@_color_tl , - color .value_required:n = true , - bold .bool_set:N = \l_tmpa_bool , - bold .default:n = true , - bold .initial:n = false , - nb-rows .code:n = - \str_if_eq:nnTF { #1 } { * } - { \int_set:Nn \l_@@_key_nb_rows_int { 500 } } - { \int_set:Nn \l_@@_key_nb_rows_int { #1 } } , - nb-rows .value_required:n = true , - rowcolor .tl_set:N = \l_tmpa_tl , - rowcolor .value_required:n = true , - rowcolor .initial:n = , - unknown .code:n = \@@_error:n { Unknown~key~for~RowStyle } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\NewDocumentCommand \@@_RowStyle:n { O { } m } - { - \group_begin: - \tl_clear:N \l_tmpa_tl % value of \rowcolor - \tl_clear:N \l_@@_color_tl - \int_set:Nn \l_@@_key_nb_rows_int 1 - \keys_set:nn { NiceMatrix / RowStyle } { #1 } -% \end{macrocode} -% If the key |rowcolor| has been used. -% \begin{macrocode} - \tl_if_empty:NF \l_tmpa_tl - { -% \end{macrocode} -% First, the end of the current row (we remind that |\RowStyle| applies to the -% \emph{end} of the current row). -% \begin{macrocode} - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { -% \end{macrocode} -% The command |\@@_exp_color_arg:NV| is \emph{fully expandable}. -% \begin{macrocode} - \@@_exp_color_arg:NV \@@_rectanglecolor \l_tmpa_tl - { \int_use:N \c@iRow - \int_use:N \c@jCol } - { \int_use:N \c@iRow - * } - } -% \end{macrocode} -% Then, the other rows (if there is several rows). -% \begin{macrocode} - \int_compare:nNnT \l_@@_key_nb_rows_int > 1 - { - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { - \@@_exp_color_arg:NV \@@_rowcolor \l_tmpa_tl - { - \int_eval:n { \c@iRow + 1 } - - \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int - 1 } - } - } - } - } - \tl_gput_right:Nn \g_@@_row_style_tl { \ifnum \c@iRow < } - \tl_gput_right:Nx \g_@@_row_style_tl - { \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int } } - \tl_gput_right:Nn \g_@@_row_style_tl { #2 } -% \end{macrocode} -% |\l_tmpa_dim| is the value of the key |cell-space-top-limit| of |\RowStyle|. -% \begin{macrocode} - \dim_compare:nNnT \l_tmpa_dim > \c_zero_dim - { - \tl_gput_right:Nx \g_@@_row_style_tl - { - \tl_gput_right:Nn \exp_not:N \g_@@_cell_after_hook_tl - { - \dim_set:Nn \l_@@_cell_space_top_limit_dim - { \dim_use:N \l_tmpa_dim } - } - } - } -% \end{macrocode} -% |\l_tmpb_dim| is the value of the key |cell-space-bottom-limit| of |\RowStyle|. -% \begin{macrocode} - \dim_compare:nNnT \l_tmpb_dim > \c_zero_dim - { - \tl_gput_right:Nx \g_@@_row_style_tl - { - \tl_gput_right:Nn \exp_not:N \g_@@_cell_after_hook_tl - { - \dim_set:Nn \l_@@_cell_space_bottom_limit_dim - { \dim_use:N \l_tmpb_dim } - } - } - } -% \end{macrocode} -% |\l_@@_color_tl| is the value of the key |color| of |\RowStyle|. -% \begin{macrocode} - \tl_if_empty:NF \l_@@_color_tl - { - \tl_gput_right:Nx \g_@@_row_style_tl - { - \mode_leave_vertical: - \@@_color:n { \l_@@_color_tl } - } - } -% \end{macrocode} -% |\l_tmpa_bool| is the value of the key |bold|. -% \begin{macrocode} - \bool_if:NT \l_tmpa_bool - { - \tl_gput_right:Nn \g_@@_row_style_tl - { - \if_mode_math: - \c_math_toggle_token - \bfseries \boldmath - \c_math_toggle_token - \else: - \bfseries \boldmath - \fi: - } - } - \tl_gput_right:Nn \g_@@_row_style_tl { \fi } - \group_end: - \g_@@_row_style_tl - \ignorespaces - } -% \end{macrocode} -% -% \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 -% \end{macrocode} -% We don't take into account the colors like |myserie!!+| because those colors -% are special color from a |\definecolorseries| of \pkg{xcolor}. -% \begin{macrocode} - \str_if_in:nnF { #1 } { !! } - { - \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 -% \end{macrocode} -% If the final user has used the key |rounded-corners| for the environment -% |{NiceTabular}|, we will clip to a rectangle with rounded corners before -% filling the rectangles. -% \begin{macrocode} - \dim_compare:nNnT \l_@@_tab_rounded_corners_dim > \c_zero_dim - { - \pgfsetcornersarced - { - \pgfpoint - { \l_@@_tab_rounded_corners_dim } - { \l_@@_tab_rounded_corners_dim } - } -% \end{macrococde} -% Because we want \pkg{nicematrix} compatible with arrays constructed by -% \pkg{array}, the nodes for the rows and columns (that is to say the nodes -% |row-|\textsl{i} and |col-|\textsl{j}) have not always the expected position, -% that is to say, there is sometimes a slight shifting of something such as -% |\arrayrulewidth|. Now, for the clipping, we have to change slightly the -% position of that clipping whether a rounded rectangle around the array is -% required. That's the point which is tested in the following line. -% \begin{macrocode} - \bool_if:NTF \l_@@_hvlines_bool - { - \pgfpathrectanglecorners - { - \pgfpointadd - { \@@_qpoint:n { row-1 } } - { \pgfpoint { 0.5 \arrayrulewidth } { \c_zero_dim } } - } - { - \pgfpointadd - { - \@@_qpoint:n - { \int_eval:n { \int_max:nn \c@iRow \c@jCol + 1 } } - } - { \pgfpoint \c_zero_dim { 0.5 \arrayrulewidth } } - } - } - { - \pgfpathrectanglecorners - { \@@_qpoint:n { row-1 } } - { - \pgfpointadd - { - \@@_qpoint:n - { \int_eval:n { \int_max:nn \c@iRow \c@jCol + 1 } } - } - { \pgfpoint \c_zero_dim \arrayrulewidth } - } - } - \pgfusepath { clip } - } - \seq_map_indexed_inline:Nn \g_@@_colors_seq - { - \begin { pgfscope } - \@@_color_opacity ##2 - \use:c { g_@@_color _ ##1 _tl } - \tl_gclear:c { g_@@_color _ ##1 _tl } - \pgfusepath { fill } - \end { pgfscope } - } - \endpgfpicture - } -% \end{macrocode} -% -% \bigskip -% The following command will extract the potential key |opacity| in its optional -% argument (between square brackets) and (of course) then apply the command |\color|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_color_opacity - { - \peek_meaning:NTF [ - { \@@_color_opacity:w } - { \@@_color_opacity:w [ ] } - } -% \end{macrocode} -% -% \bigskip -% The command |\@@_color_opacity:w| takes in as argument only the optional -% argument. One may consider that the second argument (the actual definition of -% the color) is provided by currification. -% \begin{macrocode} -\cs_new_protected:Npn \@@_color_opacity:w [ #1 ] - { - \tl_clear:N \l_tmpa_tl - \keys_set_known:nnN { nicematrix / color-opacity } { #1 } \l_tmpb_tl -% \end{macrocode} -% |\l_tmpa_tl| (if not empty) is now the opacity and |\l_tmpb_tl| (if not empty) is now the colorimetric space. -% \begin{macrocode} - \tl_if_empty:NF \l_tmpa_tl { \exp_args:NV \pgfsetfillopacity \l_tmpa_tl } - \tl_if_empty:NTF \l_tmpb_tl - { \@declaredcolor } - { \use:x { \exp_not:N \@undeclaredcolor [ \l_tmpb_tl ] } } - } -% \end{macrocode} -% -% \bigskip -% The following set of keys is used by the command |\@@_color_opacity:wn|. -% \begin{macrocode} -\keys_define:nn { nicematrix / color-opacity } - { - opacity .tl_set:N = \l_tmpa_tl , - opacity .value_required:n = true - } -% \end{macrocode} -% -% \bigskip -% \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 -% The command |\@@_arraycolor| (linked to |\arraycolor| at the beginning of -% the |\CodeBefore|) will color the whole tabular (excepted the potential -% exterior rows and columns) and the cells in the ``corners''. -% \begin{macrocode} -\NewDocumentCommand \@@_arraycolor { O { } m } - { - \@@_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 \textsl{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:nnnnn ##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:nnnnn ####1 } - \seq_map_inline:Nn \l_tmpb_seq { \@@_rowcolors_i:nnnnn ####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:nnnnn #1 #2 #3 #4 #5 - { - \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:nnnnn p - { - \bool_lazy_or:nnTF - { \int_compare_p:nNn { #4 } = \c_zero_int } - { \int_compare_p:nNn { #2 } = { \int_eval:n { \c@jCol + 1 } } } - \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:nnnnn 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 - \int_eval:n { \l_tmpb_tl + 1 } } - \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 - \int_eval:n { \l_tmpb_tl + 1 } } - \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 } - { - \tl_gput_right:Nx \g_@@_pre_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 } - } - \ignorespaces - } -% \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 } - { - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { - \@@_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 } } - } - \ignorespaces - } -% \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_@@_pre_code_before_tl - { - \exp_not:N \columncolor [ #1 ] - { \exp_not:n { #2 } } { \int_use:N \c@jCol } - } - } - } -% \end{macrocode} -% -% -% -% \bigskip -% \subsection*{The vertical and horizontal rules} -% -% -% \bigskip -% \subsubsection*{OnlyMainNiceMatrix} -% -% 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 -% \subsubsection*{General system for drawing rules} -% -% When a command, environment or ``subsystem'' of \pkg{nicematrix} wants to draw -% a rule, it will write in the internal |\CodeAfter| a command |\@@_vline:n| or -% |\@@_hline:n|. Both commands take in as argument a list of \textsl{key=value} -% pairs. That list will first be analyzed with the following set of keys. -% However, unknown keys will be analyzed further with another set of keys. -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / Rules } - { - position .int_set:N = \l_@@_position_int , - position .value_required:n = true , - start .int_set:N = \l_@@_start_int , - start .initial:n = 1 , - end .code:n = - \bool_lazy_or:nnTF - { \tl_if_empty_p:n { #1 } } - { \str_if_eq_p:nn { #1 } { last } } - { \int_set_eq:NN \l_@@_end_int \c@jCol } - { \int_set:Nn \l_@@_end_int { #1 } } - } -% \end{macrocode} -% -% \bigskip -% It's possible that the rule won't be drawn continuously from |start| ot |end| -% because of the blocks (created with the command |\Block|), the virtual blocks -% (created by |\Cdots|, etc.), etc. That's why an analyse is done and the rule -% is cut in small rules which will actually be drawn. The small continuous rules -% will be drawn by |\@@_vline_ii:| and |\@@_hline_ii:|. Those commands use the -% following set of keys. -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / RulesBis } - { - multiplicity .int_set:N = \l_@@_multiplicity_int , - multiplicity .initial:n = 1 , - dotted .bool_set:N = \l_@@_dotted_bool , - dotted .initial:n = false , - dotted .default:n = true , - color .code:n = \@@_set_CT@arc@:n { #1 } , - color .value_required:n = true , - sep-color .code:n = \@@_set_CT@drsc@:n { #1 } , - sep-color .value_required:n = true , -% \end{macrocode} -% If the user uses the key |tikz|, the rule (or more precisely: the different -% sub-rules since a rule may be broken by blocks or others) will be drawn with -% Tikz. -% \begin{macrocode} - tikz .tl_set:N = \l_@@_tikz_rule_tl , - tikz .value_required:n = true , - tikz .initial:n = , - total-width .dim_set:N = \l_@@_rule_width_dim , - total-width .value_required:n = true , - width .meta:n = { total-width = #1 } , - unknown .code:n = \@@_error:n { Unknow~key~for~RulesBis } - } -% \end{macrocode} -% -% -% \subsubsection*{The vertical rules} -% -% The following command will be executed in the internal |\CodeAfter|. The -% argument |#1| is a list of \textsl{key=value} pairs. -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline:n #1 - { -% \end{macrocode} -% The group is for the options. -% \begin{macrocode} - \group_begin: - \int_zero_new:N \l_@@_end_int - \int_set_eq:NN \l_@@_end_int \c@iRow - \keys_set_known:nnN { NiceMatrix / Rules } { #1 } \l_@@_other_keys_tl -% \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 \l_@@_position_int < { \c@jCol + 2 } - \@@_vline_i: - \group_end: - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline_i: - { - \int_zero_new:N \l_@@_local_start_int - \int_zero_new:N \l_@@_local_end_int -% \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 { \int_eval:n \l_@@_position_int } - \int_step_variable:nnNn \l_@@_start_int \l_@@_end_int - \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:nnnnn ##1 } - \seq_map_inline:Nn \g_@@_pos_of_xdots_seq - { \@@_test_vline_in_block:nnnnn ##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 - { - \int_compare:nNnT \l_@@_local_start_int = 0 -% \end{macrocode} -% We keep in memory that we have a rule to draw. |\l_@@_local_start_int| will be -% the starting row of the rule that we will have to draw. -% \begin{macrocode} - { \int_set:Nn \l_@@_local_start_int \l_tmpa_tl } - } - { - \int_compare:nNnT \l_@@_local_start_int > 0 - { - \int_set:Nn \l_@@_local_end_int { \l_tmpa_tl - 1 } - \@@_vline_ii: - \int_zero:N \l_@@_local_start_int - } - } - } - \int_compare:nNnT \l_@@_local_start_int > 0 - { - \int_set_eq:NN \l_@@_local_end_int \l_@@_end_int - \@@_vline_ii: - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_in_corner_v: - { - \int_compare:nNnTF \l_tmpb_tl = { \int_eval:n { \c@jCol + 1 } } - { - \seq_if_in:NxT - \l_@@_corners_cells_seq - { \l_tmpa_tl - \int_eval:n { \l_tmpb_tl - 1 } } - { \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 - \int_eval:n { \l_tmpb_tl - 1 } } - { \bool_set_false:N \g_tmpa_bool } - } - } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline_ii: - { - \keys_set:nV { NiceMatrix / RulesBis } \l_@@_other_keys_tl - \bool_if:NTF \l_@@_dotted_bool - \@@_vline_iv: - { - \tl_if_empty:NTF \l_@@_tikz_rule_tl - \@@_vline_iii: - \@@_vline_v: - } - } -% \end{macrocode} -% -% \bigskip -% First the case of a standard rule: the user has not used the key |dotted| nor -% the key |tikz|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline_iii: - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \@@_qpoint:n { row - \int_use:N \l_@@_local_start_int } - \dim_set_eq:NN \l_tmpa_dim \pgf@y - \@@_qpoint:n { col - \int_use:N \l_@@_position_int } - \dim_set:Nn \l_tmpb_dim - { - \pgf@x - - 0.5 \l_@@_rule_width_dim - + - ( \arrayrulewidth * \l_@@_multiplicity_int - + \doublerulesep * ( \l_@@_multiplicity_int - 1 ) ) / 2 - } - \@@_qpoint:n { row - \int_eval:n { \l_@@_local_end_int + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y - \bool_lazy_all:nT - { - { \int_compare_p:nNn \l_@@_multiplicity_int > 1 } - { \cs_if_exist_p:N \CT@drsc@ } - { ! \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 ) - * ( \l_@@_multiplicity_int - 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 { \l_@@_multiplicity_int - 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 - \endpgfpicture - } -% \end{macrocode} -% -% -% \bigskip -% The following code is for the case of a dotted rule (with our system of -% rounded dots). -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline_iv: - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \@@_qpoint:n { col - \int_use:N \l_@@_position_int } - \dim_set:Nn \l_@@_x_initial_dim { \pgf@x - 0.5 \l_@@_rule_width_dim } - \dim_set_eq:NN \l_@@_x_final_dim \l_@@_x_initial_dim - \@@_qpoint:n { row - \int_use:N \l_@@_local_start_int } - \dim_set_eq:NN \l_@@_y_initial_dim \pgf@y - \@@_qpoint:n { row - \int_eval:n { \l_@@_local_end_int + 1 } } - \dim_set_eq:NN \l_@@_y_final_dim \pgf@y - \CT@arc@ - \@@_draw_line: - \endpgfpicture - } -% \end{macrocode} -% -% \bigskip -% The following code is for the case when the user uses the key |tikz| (in the -% definition of a customized rule by using the key |custom-line|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline_v: - { - \begin {tikzpicture } - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \@@_qpoint:n { row - \int_use:N \l_@@_local_start_int } - \dim_set_eq:NN \l_tmpa_dim \pgf@y - \@@_qpoint:n { col - \int_use:N \l_@@_position_int } - \dim_set:Nn \l_tmpb_dim { \pgf@x - 0.5 \l_@@_rule_width_dim } - \@@_qpoint:n { row - \int_eval:n { \l_@@_local_end_int + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y - \exp_args:NV \tikzset \l_@@_tikz_rule_tl - \use:x { \exp_not:N \draw [ \l_@@_tikz_rule_tl ] } - ( \l_tmpb_dim , \l_tmpa_dim ) -- - ( \l_tmpb_dim , \l_@@_tmpc_dim ) ; - \end { tikzpicture } - } -% \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 { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } - 1 2 - } - { - \bool_if:nTF { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } - { \int_eval:n { \c@jCol + 1 } } - \c@jCol - } - { - \tl_if_eq:NnF \l_@@_vlines_clist { all } - { \clist_if_in:NnT \l_@@_vlines_clist { ##1 } } - { \@@_vline:n { position = ##1 , total-width = \arrayrulewidth } } - } - } -% \end{macrocode} -% -% -% -% \subsubsection*{The horizontal rules} -% -% \bigskip -% The following command will be executed in the internal |\CodeAfter|. The -% argument |#1| is a list of \textsl{key=value} pairs of the form -% |{NiceMatrix/Rules}|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_hline:n #1 - { -% \end{macrocode} -% The group is for the options. -% \begin{macrocode} - \group_begin: - \int_zero_new:N \l_@@_end_int - \int_set_eq:NN \l_@@_end_int \c@jCol - \keys_set_known:nnN { NiceMatrix / Rules } { #1 } \l_@@_other_keys_tl - \@@_hline_i: - \group_end: - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_hline_i: - { - \int_zero_new:N \l_@@_local_start_int - \int_zero_new:N \l_@@_local_end_int -% \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:Nx \l_tmpa_tl { \int_use:N \l_@@_position_int } - \int_step_variable:nnNn \l_@@_start_int \l_@@_end_int - \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:nnnnn ##1 } - \seq_map_inline:Nn \g_@@_pos_of_xdots_seq - { \@@_test_hline_in_block:nnnnn ##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 - { - \int_compare:nNnT \l_@@_local_start_int = 0 -% \end{macrocode} -% We keep in memory that we have a rule to draw. |\l_@@_local_start_int| will be -% the starting row of the rule that we will have to draw. -% \begin{macrocode} - { \int_set:Nn \l_@@_local_start_int \l_tmpb_tl } - } - { - \int_compare:nNnT \l_@@_local_start_int > 0 - { - \int_set:Nn \l_@@_local_end_int { \l_tmpb_tl - 1 } - \@@_hline_ii: - \int_zero:N \l_@@_local_start_int - } - } - } - \int_compare:nNnT \l_@@_local_start_int > 0 - { - \int_set_eq:NN \l_@@_local_end_int \l_@@_end_int - \@@_hline_ii: - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_in_corner_h: - { - \int_compare:nNnTF \l_tmpa_tl = { \int_eval:n { \c@iRow + 1 } } - { - \seq_if_in:NxT - \l_@@_corners_cells_seq - { \int_eval:n { \l_tmpa_tl - 1 } - \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 - { \int_eval:n { \l_tmpa_tl - 1 } - \l_tmpb_tl } - { \bool_set_false:N \g_tmpa_bool } - } - } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_hline_ii: - { - % \bool_set_false:N \l_@@_dotted_bool - \keys_set:nV { NiceMatrix / RulesBis } \l_@@_other_keys_tl - \bool_if:NTF \l_@@_dotted_bool - \@@_hline_iv: - { - \tl_if_empty:NTF \l_@@_tikz_rule_tl - \@@_hline_iii: - \@@_hline_v: - } - } -% \end{macrocode} -% -% \bigskip -% First the case of a standard rule (without the keys |dotted| and |tikz|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_hline_iii: - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \@@_qpoint:n { col - \int_use:N \l_@@_local_start_int } - \dim_set_eq:NN \l_tmpa_dim \pgf@x - \@@_qpoint:n { row - \int_use:N \l_@@_position_int } - \dim_set:Nn \l_tmpb_dim - { - \pgf@y - - 0.5 \l_@@_rule_width_dim - + - ( \arrayrulewidth * \l_@@_multiplicity_int - + \doublerulesep * ( \l_@@_multiplicity_int - 1 ) ) / 2 - } - \@@_qpoint:n { col - \int_eval:n { \l_@@_local_end_int + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x - \bool_lazy_all:nT - { - { \int_compare_p:nNn \l_@@_multiplicity_int > 1 } - { \cs_if_exist_p:N \CT@drsc@ } - { ! \tl_if_blank_p:V \CT@drsc@ } - } - { - \group_begin: - \CT@drsc@ - \dim_set:Nn \l_@@_tmpd_dim - { - \l_tmpb_dim - ( \doublerulesep + \arrayrulewidth ) - * ( \l_@@_multiplicity_int - 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 { \l_@@_multiplicity_int - 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 - \endpgfpicture - } -% \end{macrocode} -% -% \bigskip -% The following code is for the case of a dotted rule (with our system of -% rounded dots). -% 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}$ -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_hline_iv: - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \@@_qpoint:n { row - \int_use:N \l_@@_position_int } - \dim_set:Nn \l_@@_y_initial_dim { \pgf@y - 0.5 \l_@@_rule_width_dim } - \dim_set_eq:NN \l_@@_y_final_dim \l_@@_y_initial_dim - \@@_qpoint:n { col - \int_use:N \l_@@_local_start_int } - \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x - \int_compare:nNnT \l_@@_local_start_int = 1 - { - \dim_sub:Nn \l_@@_x_initial_dim \l_@@_left_margin_dim - \bool_if:NT \g_@@_NiceArray_bool - { \dim_sub:Nn \l_@@_x_initial_dim \arraycolsep } -% \end{macrocode} -% For reasons purely aesthetic, we do an adjustment in the case of a rounded -% bracket. The correction by |0.5 \l_@@_xdots_inter_dim| is \emph{ad hoc} for a -% better result. -% \begin{macrocode} - \tl_if_eq:NnF \g_@@_left_delim_tl ( - { \dim_add:Nn \l_@@_x_initial_dim { 0.5 \l_@@_xdots_inter_dim } } - } - \@@_qpoint:n { col - \int_eval:n { \l_@@_local_end_int + 1 } } - \dim_set_eq:NN \l_@@_x_final_dim \pgf@x - \int_compare:nNnT \l_@@_local_end_int = \c@jCol - { - \dim_add:Nn \l_@@_x_final_dim \l_@@_right_margin_dim - \bool_if:NT \g_@@_NiceArray_bool - { \dim_add:Nn \l_@@_x_final_dim \arraycolsep } - \tl_if_eq:NnF \g_@@_right_delim_tl ) - { \dim_gsub:Nn \l_@@_x_final_dim { 0.5 \l_@@_xdots_inter_dim } } - } - \CT@arc@ - \@@_draw_line: - \endpgfpicture - } -% \end{macrocode} -% -% \bigskip -% The following code is for the case when the user uses the key |tikz| (in the -% definition of a customized rule by using the key |custom-line|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_hline_v: - { - \begin { tikzpicture } - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \@@_qpoint:n { col - \int_use:N \l_@@_local_start_int } - \dim_set_eq:NN \l_tmpa_dim \pgf@x - \@@_qpoint:n { row - \int_use:N \l_@@_position_int } - \dim_set:Nn \l_tmpb_dim { \pgf@y - 0.5 \l_@@_rule_width_dim } - \@@_qpoint:n { col - \int_eval:n { \l_@@_local_end_int + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x - \exp_args:NV \tikzset \l_@@_tikz_rule_tl - \use:x { \exp_not:N \draw [ \l_@@_tikz_rule_tl ] } - ( \l_tmpa_dim , \l_tmpb_dim ) -- - ( \l_@@_tmpc_dim , \l_tmpb_dim ) ; - \end { tikzpicture } - } -% \end{macrocode} -% -% -% \bigskip -% The command |\@@_draw_hlines:| draws all the horizontal rules excepted in the -% blocks (even the virtual blocks 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 { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } - 1 2 - } - { - \bool_if:nTF { \g_@@_NiceArray_bool && ! \l_@@_except_borders_bool } - { \int_eval:n { \c@iRow + 1 } } - \c@iRow - } - { - \tl_if_eq:NnF \l_@@_hlines_clist { all } - { \clist_if_in:NnT \l_@@_hlines_clist { ##1 } } - { \@@_hline:n { position = ##1 , total-width = \arrayrulewidth } } - } - } -% \end{macrocode} -% -% -% \medskip -% The command |\@@_Hline:| will be linked to |\Hline| in the environments of -% \pkg{nicematrix}. -% \begin{macrocode} -\cs_set:Npn \@@_Hline: { \noalign \bgroup \@@_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_remove_spaces:n - { - \peek_meaning: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 - { - \peek_meaning:NTF [ - { \@@_Hline_iv:nw { #1 } } - { \@@_Hline_iv:nw { #1 } [ ] } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_set:Npn \@@_Hline_iv:nw #1 [ #2 ] - { - \@@_compute_rule_width:n { multiplicity = #1 , #2 } - \skip_vertical:n { \l_@@_rule_width_dim } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { - \@@_hline:n - { - multiplicity = #1 , - position = \int_eval:n { \c@iRow + 1 } , - total-width = \dim_use:N \l_@@_rule_width_dim , - #2 - } - } - \egroup - } -% \end{macrocode} -% -% \subsubsection*{Customized rules defined by the final user} -% -% The final user can define a customized rule by using the key |custom-line| in -% |\NiceMatrixOptions|. That key takes in as value a list of \textsl{key=value} -% pairs. -% -% -% -% \medskip -% Among the keys avalaible in that list, there is the key |letter| to specify a -% letter that the final user will use in the preamble of the array. All the -% letters defined by this way by the final user for such customized rules are -% added in the set of keys |{NiceMatrix / ColumnTypes}|. That set of keys is -% used to store the characteristics of those types of rules for convenience: the -% keys of that set of keys won't never be used as keys by the final user (he -% will use, instead, letters in the preamble of its array). -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / ColumnTypes } { } -% \end{macrocode} -% -% -% \medskip -% The following command will create the customized rule (it is executed when the -% final user uses the key |custom-line|, for example in |\NiceMatrixOptions|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_custom_line:n #1 - { - \str_clear_new:N \l_@@_command_str - \str_clear_new:N \l_@@_ccommand_str - \str_clear_new:N \l_@@_letter_str - \keys_set_known:nnN { NiceMatrix / custom-line } { #1 } \l_@@_other_keys_tl -% \end{macrocode} -% If the final user only wants to draw horizontal rules, he does not need to -% specify a letter (for the vertical rules in the preamble of the array). On the -% other hand, if he only wants to draw vertical rules, he does not need to -% define a command (which is the tool to draw horizontal rules in the array). Of -% course, a definition of custom lines with no letter and no command would be point-less. -% -% \begin{macrocode} - \bool_lazy_all:nTF - { - { \str_if_empty_p:N \l_@@_letter_str } - { \str_if_empty_p:N \l_@@_command_str } - { \str_if_empty_p:N \l_@@_ccommand_str } - } - { \@@_error:n { No~letter~and~no~command } } - { \exp_args:NV \@@_custom_line_i:n \l_@@_other_keys_tl } - } -% \end{macrocode} -% -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / custom-line } - { - % here, we will use change in the future to use .str_set:N - letter .code:n = \str_set:Nn \l_@@_letter_str { #1 } , - letter .value_required:n = true , - command .code:n = \str_set:Nn \l_@@_command_str { #1 } , - command .value_required:n = true , - ccommand .code:n = \str_set:Nn \l_@@_ccommand_str { #1 } , - ccommand .value_required:n = true , - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_custom_line_i:n #1 - { -% \end{macrocode} -% The following flags will be raised when the keys |tikz|, |dotted| and |color| -% are used (in the |custom-line|). -% \begin{macrocode} - \bool_set_false:N \l_@@_tikz_rule_bool - \bool_set_false:N \l_@@_dotted_rule_bool - \bool_set_false:N \l_@@_color_bool -% \end{macrocode} -% \begin{macrocode} - \keys_set:nn { NiceMatrix / custom-line-bis } { #1 } - \bool_if:NT \l_@@_tikz_rule_bool - { -% \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:NF \tikzpicture - { \@@_error:n { tikz~in~custom-line~without~tikz } } - \bool_if:NT \l_@@_color_bool - { \@@_error:n { color~in~custom-line~with~tikz } } - } - \bool_if:nT - { - \int_compare_p:nNn \l_@@_multiplicity_int > 1 - && \l_@@_dotted_rule_bool - } - { \@@_error:n { key~multiplicity~with~dotted } } - \str_if_empty:NF \l_@@_letter_str - { - \int_compare:nTF { \str_count:N \l_@@_letter_str != 1 } - { \@@_error:n { Several~letters } } - { - \exp_args:NnV \tl_if_in:NnTF - \c_@@_forbidden_letters_str \l_@@_letter_str - { \@@_error:n { Forbidden~letter } } - { -% \end{macrocode} -% The final user can, locally, redefine a letter of column type. That's -% compatible with the use of |\keys_define:nn|: the definition is local and may -% overwrite a previous definition. -% \begin{macrocode} - \keys_define:nx { NiceMatrix / ColumnTypes } - { - \l_@@_letter_str .code:n = - { \@@_v_custom_line:n { \exp_not:n { #1 } } } - } - } - } - } - \str_if_empty:NF \l_@@_command_str { \@@_h_custom_line:n { #1 } } - \str_if_empty:NF \l_@@_ccommand_str { \@@_c_custom_line:n { #1 } } - } -% \end{macrocode} -% -% -% \begin{macrocode} -\str_const:Nn \c_@@_forbidden_letters_str { lcrpmbVX|()[]!@<> } -% \end{macrocode} -% -% \medskip -% The previous command |\@@_custom_line_i:n| uses the following set of keys. -% However, the whole definition of the customized lines (as provided by the -% final user as argument of |custom-line|) will also be used further with -% other sets of keys (for instance |{NiceMatrix/Rules}|). That's why the -% following set of keys has some keys which are no-op. -% \begin{macrocode} -\keys_define:nn { NiceMatrix / custom-line-bis } - { - multiplicity .int_set:N = \l_@@_multiplicity_int , - multiplicity .initial:n = 1 , - multiplicity .value_required:n = true , - color .code:n = \bool_set_true:N \l_@@_color_bool , - color .value_required:n = true , - tikz .code:n = \bool_set_true:N \l_@@_tikz_rule_bool , - tikz .value_required:n = true , - dotted .code:n = \bool_set_true:N \l_@@_dotted_rule_bool , - dotted .value_forbidden:n = true , - total-width .code:n = { } , - total-width .value_required:n = true , - width .code:n = { } , - width .value_required:n = true , - sep-color .code:n = { } , - sep-color .value_required:n = true , - unknown .code:n = \@@_error:n { Unknown~key~for~custom-line } - } -% \end{macrocode} -% -% The following keys will indicate whether the keys |dotted|, |tikz| and |color| -% are used in the use of a |custom-line|. -% \begin{macrocode} -\bool_new:N \l_@@_dotted_rule_bool -\bool_new:N \l_@@_tikz_rule_bool -\bool_new:N \l_@@_color_bool -% \end{macrocode} -% -% \bigskip -% The following keys are used to determine the total width of the line -% (including the spaces on both sides of the line). The key |width| is -% deprecated and has been replaced by the key |total-width|. -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / custom-line-width } - { - multiplicity .int_set:N = \l_@@_multiplicity_int , - multiplicity .initial:n = 1 , - multiplicity .value_required:n = true , - tikz .code:n = \bool_set_true:N \l_@@_tikz_rule_bool , - total-width .code:n = \dim_set:Nn \l_@@_rule_width_dim { #1 } - \bool_set_true:N \l_@@_total_width_bool , - total-width .value_required:n = true , - width .meta:n = { total-width = #1 } , - dotted .code:n = \bool_set_true:N \l_@@_dotted_rule_bool , - } -% \end{macrocode} -% -% \bigskip -% The following command will create the command that the final user will use in -% its array to draw an horizontal rule (hence the `|h|` in the name) with the -% full width of the array. |#1| is the whole set of keys to pass to the command -% |\@@_hline:n| (which is in the internal |\CodeAfter|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_h_custom_line:n #1 - { -% \end{macrocode} -% We use |\cs_set:cpn| and not |\cs_new:cpn| because we want a local definition. -% Moreover, the command must \emph{not} be protected since it begins with |\noalign|. -% \begin{macrocode} - \cs_set:cpn { nicematrix - \l_@@_command_str } - { - \noalign - { - \@@_compute_rule_width:n { #1 } - \skip_vertical:n { \l_@@_rule_width_dim } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { - \@@_hline:n - { - #1 , - position = \int_eval:n { \c@iRow + 1 } , - total-width = \dim_use:N \l_@@_rule_width_dim - } - } - } - } - \seq_put_left:NV \l_@@_custom_line_commands_seq \l_@@_command_str - } -\cs_generate_variant:Nn \@@_h_custom_line:nn { n V } -% \end{macrocode} -% -% \bigskip -% \bigskip -% The following command will create the command that the final user will use in -% its array to draw an horizontal rule on only some of the columns of the array -% (hence the letter |c| as in |\cline|). |#1| is the whole set of keys to pass -% to the command |\@@_hline:n| (which is in the internal |\CodeAfter|). -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_c_custom_line:n #1 - { -% \end{macrocode} -% Here, we need an expandable command since it begins with an |\noalign|. -% \begin{macrocode} - \exp_args:Nc \NewExpandableDocumentCommand - { nicematrix - \l_@@_ccommand_str } - { O { } m } - { - \noalign - { - \@@_compute_rule_width:n { #1 , ##1 } - \skip_vertical:n { \l_@@_rule_width_dim } - \clist_map_inline:nn - { ##2 } - { \@@_c_custom_line_i:nn { #1 , ##1 } { ####1 } } - } - } - \seq_put_left:NV \l_@@_custom_line_commands_seq \l_@@_ccommand_str - } -% \end{macrocode} -% The first argument is the list of key-value pairs characteristic of the line. -% The second argument is the specification of columns for the |\cline| with the -% syntax $a$-$b$. -% \begin{macrocode} -\cs_new_protected:Npn \@@_c_custom_line_i:nn #1 #2 - { - \str_if_in:nnTF { #2 } { - } - { \@@_cut_on_hyphen:w #2 \q_stop } - { \@@_cut_on_hyphen:w #2 - #2 \q_stop } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { - \@@_hline:n - { - #1 , - start = \l_tmpa_tl , - end = \l_tmpb_tl , - position = \int_eval:n { \c@iRow + 1 } , - total-width = \dim_use:N \l_@@_rule_width_dim - } - } - } -\cs_generate_variant:Nn \@@_c_custom_line:nn { n V } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_compute_rule_width:n #1 - { - \bool_set_false:N \l_@@_tikz_rule_bool - \bool_set_false:N \l_@@_total_width_bool - \bool_set_false:N \l_@@_dotted_rule_bool - \keys_set_known:nn { NiceMatrix / custom-line-width } { #1 } - \bool_if:NF \l_@@_total_width_bool - { - \bool_if:NTF \l_@@_dotted_rule_bool - { \dim_set:Nn \l_@@_rule_width_dim { 2 \l_@@_xdots_radius_dim } } - { - \bool_if:NF \l_@@_tikz_rule_bool - { - \dim_set:Nn \l_@@_rule_width_dim - { - \arrayrulewidth * \l_@@_multiplicity_int - + \doublerulesep * ( \l_@@_multiplicity_int - 1 ) - } - } - } - } - } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_v_custom_line:n #1 - { - \@@_compute_rule_width:n { #1 } -% \end{macrocode} -% In the following line, the |\dim_use:N| is mandatory since we do an expansion. -% \begin{macrocode} - \tl_gput_right:Nx \g_@@_preamble_tl - { \exp_not:N ! { \skip_horizontal:n { \dim_use:N \l_@@_rule_width_dim } } } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { - \@@_vline:n - { - #1 , - position = \int_eval:n { \c@jCol + 1 } , - total-width = \dim_use:N \l_@@_rule_width_dim - } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_custom_line:n - { letter = : , command = hdottedline , ccommand = cdottedline, dotted } -% \end{macrocode} -% -% \subsubsection*{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:nnnnn #1 #2 #3 #4 #5 - { - \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:nnnnn #1 #2 #3 #4 #5 - { - \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 } ) - || ( \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} -% -% \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 } ) - || ( \int_compare_p:nNn \l_tmpb_tl = { #4 + 1 } ) - } - } - { \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| 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 #7 - { - \int_compare:nNnT { #3 } < { \int_eval:n { #1 + 1 } } - { - \int_compare:nNnT { #1 } < { \int_eval:n { #5 + 1 } } - { - \int_compare:nNnT { #4 } < { \int_eval:n { #2 + 1 } } - { - \int_compare:nNnT { #2 } < { \int_eval:n { #6 + 1 } } - { \bool_set_true:N \l_tmpb_bool } - } - } - } - } -% \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 _ \int_eval:n { \@@_i: + 1 } _ max _ dim } - ) - / 2 - } - \dim_set_eq:cc { l_@@_row _ \int_eval:n { \@@_i: + 1 } _ 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 _ \int_eval:n { \@@_j: + 1 } _ min _ dim } - ) - / 2 - } - \dim_set_eq:cc { l_@@_column _ \int_eval:n { \@@_j: + 1 } _ 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_str t , - t .value_forbidden:n = true , - b .code:n = \str_set:Nn \l_@@_vpos_of_block_str b , - b .value_forbidden:n = true , - color .tl_set:N = \l_@@_color_tl , - color .value_required:n = true , - respect-arraystretch .bool_set:N = \l_@@_respect_arraystretch_bool , - respect-arraystretch .default: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 } - { - \int_compare:nNnTF { \char_value_catcode:n { 45 } } = { 13 } - \@@_Block_i_czech \@@_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} -% -% With \pkg{babel} with the key |czech|, the character |-| (hyphen) is active. -% That's why we need a special version. Remark that we could not use a -% preprocessor in the command |\@@_Block:| to do the job because the command -% |\@@_Block:| is defined with the command |\NewExpandableDocumentCommand|. -% \begin{macrocode} -{ - \char_set_catcode_active:N - - \cs_new:Npn \@@_Block_i_czech #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 -% \textsl{key=values} pairs, |#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_@@_pre_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:V \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 - { - \int_compare:nNnTF \c@iRow = 0 - \l_@@_code_for_first_row_tl - { - \int_compare:nNnT \c@iRow = \l_@@_last_row_int - \l_@@_code_for_last_row_tl - } - \g_@@_row_style_tl - } - \group_begin: - \bool_if:NF \l_@@_respect_arraystretch_bool - { \cs_set:Npn \arraystretch { 1 } } - \dim_zero:N \extrarowheight - #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 alignment 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_all:nTF - { - { \int_compare_p:nNn { #2 } = 1 } - { \dim_compare_p:n { \l_@@_col_width_dim >= \c_zero_dim } } - { ! \g_@@_rotate_bool } - } -% \end{macrocode} -% When the block is mono-column in a column with a fixed width (eg |p{3cm}|). -% \begin{macrocode} - { - \use:x - { - \exp_not:N \begin { minipage }% - [ \str_lowercase:V { \l_@@_vpos_of_block_str } ] - { \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 }% - [ \str_lowercase:V { \l_@@_vpos_of_block_str } ] - { @ { } \l_@@_hpos_block_str @ { } } - } - #5 - \end { tabular } - } - } - { - \c_math_toggle_token - \use:x - { - \exp_not:N \begin { array }% - [ \str_lowercase:V { \l_@@_vpos_of_block_str } ] - { @ { } \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 -% alignment 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 } } - { - \bool_if:NTF \l_@@_NiceTabular_bool - { - \group_begin: - \bool_if:NF \l_@@_respect_arraystretch_bool - { \cs_set:Npn \exp_not:N \arraystretch { 1 } } - \exp_not:n - { - \dim_zero:N \extrarowheight - #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 alignment 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_str ] - { @ { } \l_@@_hpos_block_str @ { } } - } - #5 - \end { tabular } - } - \group_end: - } - { - \group_begin: - \bool_if:NF \l_@@_respect_arraystretch_bool - { \cs_set:Npn \exp_not:N \arraystretch { 1 } } - \exp_not:n - { - \dim_zero:N \extrarowheight - #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_str ] - { @ { } \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 .code:n = - \tl_set_rescan:Nnn - \l_@@_fill_tl - { \char_set_catcode_other:N ! } - { #1 } , - fill .value_required:n = true , - draw .code:n = - \tl_set_rescan:Nnn - \l_@@_draw_tl - { \char_set_catcode_other:N ! } - { #1 } , - draw .default:n = default , - rounded-corners .dim_set:N = \l_@@_rounded_corners_dim , - rounded-corners .default:n = 4 pt , - color .code:n = - \@@_color:n { #1 } - \tl_set_rescan:Nnn - \l_@@_draw_tl - { \char_set_catcode_other:N ! } - { #1 } , - color .value_required:n = true , - borders .clist_set:N = \l_@@_borders_clist , - borders .value_required:n = true , - hvlines .meta:n = { vlines , hlines } , - vlines .bool_set:N = \l_@@_vlines_block_bool, - vlines .default:n = true , - hlines .bool_set:N = \l_@@_hlines_block_bool, - hlines .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_str t , - t .value_forbidden:n = true , - T .code:n = \str_set:Nn \l_@@_vpos_of_block_str T , - T .value_forbidden:n = true , - b .code:n = \str_set:Nn \l_@@_vpos_of_block_str b , - b .value_forbidden:n = true , - B .code:n = \str_set:Nn \l_@@_vpos_of_block_str B , - B .value_forbidden:n = true , - v-center .code:n = \str_set:Nn \l_@@_vpos_of_block_str { c } , - v-center .value_forbidden:n = true , - name .tl_set:N = \l_@@_block_name_str , - name .value_required:n = true , - name .initial:n = , - respect-arraystretch .bool_set:N = \l_@@_respect_arraystretch_bool , - respect-arraystretch .default:n = true , - transparent .bool_set:N = \l_@@_transparent_bool , - transparent .default:n = true , - transparent .initial:n = false , - 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 } - \@@_msg_redirect_name:nn { columns~not~used } { none } - } - { \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} -% -% -% \medskip -% |#1| is the first row of the block; -% |#2| is the first column of the block; -% |#3| is the last row of the block; -% |#4| is the last column of the block; -% |#5| is a list of \textsl{key=value} options; -% |#6| is the label -% \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: - \int_compare:nNnT { #1 } = { #3 } - { \str_set:Nn \l_@@_vpos_of_block_str { t } } - \keys_set:nn { NiceMatrix / Block / SecondPass } { #5 } -% \end{macrocode} -% -% \begin{macrocode} - \bool_if:NT \l_@@_vlines_block_bool - { - \tl_gput_right:Nx \g_nicematrix_code_after_tl - { - \@@_vlines_block:nnn - { \exp_not:n { #5 } } - { #1 - #2 } - { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } - } - } - \bool_if:NT \l_@@_hlines_block_bool - { - \tl_gput_right:Nx \g_nicematrix_code_after_tl - { - \@@_hlines_block:nnn - { \exp_not:n { #5 } } - { #1 - #2 } - { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } - } - } - \bool_if:nF - { - \l_@@_transparent_bool - || ( \l_@@_vlines_block_bool && \l_@@_hlines_block_bool ) - } - { -% \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:Nx \g_@@_pos_of_blocks_seq - { { #1 } { #2 } { #3 } { #4 } { \l_@@_block_name_str } } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \bool_lazy_and:nnT - { ! (\tl_if_empty_p:N \l_@@_draw_tl) } - { \l_@@_hlines_block_bool || \l_@@_vlines_block_bool } - { \@@_error:n { hlines~with~color } } -% \end{macrocode} -% \bigskip -% \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 - { - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { - \exp_not:N \roundedrectanglecolor - \exp_args:NV \tl_if_head_eq_meaning:nNTF \l_@@_fill_tl [ - { \l_@@_fill_tl } - { { \l_@@_fill_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_@@_pre_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 - \int_eval:n { \l_@@_last_row_int + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y - \@@_qpoint:n { col - \int_eval:n { \l_@@_last_col_int + 1 } } - \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} - \@@_pgf_rect_node:nnnnn - { \@@_env: - #1 - #2 - block } - \l_tmpb_dim \l_tmpa_dim \l_@@_tmpd_dim \l_@@_tmpc_dim - \str_if_empty:NF \l_@@_block_name_str - { - \pgfnodealias - { \@@_env: - \l_@@_block_name_str } - { \@@_env: - #1 - #2 - block } - \str_if_empty:NF \l_@@_name_str - { - \pgfnodealias - { \l_@@_name_str - \l_@@_block_name_str } - { \@@_env: - #1 - #2 - block } - } - } -% \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 - \int_eval:n { \l_@@_last_col_int + 1 } } - \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. -% \begin{macrocode} - \bool_lazy_any:nTF - { - { \str_if_eq_p:Vn \l_@@_vpos_of_block_str { c } } - { \str_if_eq_p:Vn \l_@@_vpos_of_block_str { T } } - { \str_if_eq_p:Vn \l_@@_vpos_of_block_str { B } } - } -% \medskip -% \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 } - } -% \end{macrocode} -% \begin{macrocode} - \tl_set:Nx \l_tmpa_tl - { - \str_case:Vn \l_@@_vpos_of_block_str - { - c { - \str_case:Vn \l_@@_hpos_block_str - { - c { center } - l { west } - r { east } - } - - } - T { - \str_case:Vn \l_@@_hpos_block_str - { - c { north } - l { north~west } - r { north~east } - } - - } - B { - \str_case:Vn \l_@@_hpos_block_str - { - c { south} - l { south~west } - r { south~east } - } - - } - } - } -% \end{macrocode} -% \begin{macrocode} - \pgftransformshift - { - \pgfpointanchor - { - \@@_env: - #1 - #2 - block - \bool_if:NF \l_@@_hpos_of_block_cap_bool { - short } - } - { \l_tmpa_tl } - } - \pgfset - { - inner~xsep = \c_zero_dim , - inner~ysep = \l_@@_block_ysep_dim - } - \pgfnode - { rectangle } - { \l_tmpa_tl } - { \box_use_drop:N \l_@@_cell_box } { } { } - } -% \end{macrocode} -% -% \begin{macrocode} - { -% \end{macrocode} -% -% \begin{macrocode} - \pgfextracty \l_tmpa_dim - { - \@@_qpoint:n - { - row - \str_if_eq:VnTF \l_@@_vpos_of_block_str { b } { #3 } { #1 } - - base - } - } - \dim_sub:Nn \l_tmpa_dim { 0.5 \arrayrulewidth } % added 2023-02-21 -% \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} -% -% \begin{macrocode} - \endpgfpicture - \group_end: - } -% \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@ } - { \@@_color:V \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 - \int_eval:n { \l_tmpa_tl + 1 } } - \dim_set:Nn \l_tmpa_dim { \pgf@y } - \@@_qpoint:n { col - \int_eval:n { \l_tmpb_tl + 1 } } - \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 } - \dim_compare:nNnTF \l_@@_rounded_corners_dim = \c_zero_dim - { \pgfusepathqstroke } - { \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 |\@@_vlines_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 \@@_vlines_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:n - { - position = ##1 , - start = \l_@@_tmpc_tl , - end = \int_eval:n { \l_tmpa_tl - 1 } , - total-width = \dim_use:N \l_@@_line_width_dim % added 2022-08-06 - } - } - } - } -\cs_new_protected:Npn \@@_hlines_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_@@_tmpc_tl \l_tmpa_tl - { - \use:x - { - \@@_hline:n - { - position = ##1 , - start = \l_@@_tmpd_tl , - end = \int_eval:n { \l_tmpb_tl - 1 } , - total-width = \dim_use:N \l_@@_line_width_dim % added 2022-08-06 - } - } - } - } -% \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 } } - { - \tl_clear_new:N \l_@@_borders_tikz_tl - \keys_set:nV - { NiceMatrix / OnlyForTikzInBorders } - \l_@@_borders_clist - \@@_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 } } - \@@_stroke_borders_block_i: - } - } -% \end{macrocode} -% -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \cs_new_protected:Npx \@@_stroke_borders_block_i: - { - \c_@@_pgfortikzpicture_tl - \@@_stroke_borders_block_ii: - \c_@@_endpgfortikzpicture_tl - } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_stroke_borders_block_ii: - { - \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 } - } -% \end{macrocode} -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / OnlyForTikzInBorders } - { - tikz .code:n = - \cs_if_exist:NTF \tikzpicture - { \tl_set:Nn \l_@@_borders_tikz_tl { #1 } } - { \@@_error:n { tikz~in~borders~without~tikz } } , - tikz .value_required:n = true , - top .code:n = , - bottom .code:n = , - left .code:n = , - right .code:n = , - unknown .code:n = \@@_error:n { bad~border } - } -% \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 } - \tl_if_empty:NTF \l_@@_borders_tikz_tl - { - \pgfpathmoveto { \pgfpoint \pgf@x \l_tmpb_dim } - \pgfpathlineto { \pgfpoint \pgf@x \l_@@_tmpc_dim } - \pgfusepathqstroke - } - { - \use:x { \exp_not:N \draw [ \l_@@_borders_tikz_tl ] } - ( \pgf@x , \l_tmpb_dim ) -- ( \pgf@x , \l_@@_tmpc_dim ) ; - } - } -% \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 } - \tl_if_empty:NTF \l_@@_borders_tikz_tl - { - \pgfpathmoveto { \pgfpoint \l_tmpa_dim \pgf@y } - \pgfpathlineto { \pgfpoint \l_tmpb_dim \pgf@y } - \pgfusepathqstroke - } - { - \use:x { \exp_not:N \draw [ \l_@@_borders_tikz_tl ] } - ( \l_tmpa_dim , \pgf@y ) -- ( \l_tmpb_dim , \pgf@y ) ; - } - } -% \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 - ( \int_eval:n { #3 + 1 } -| \int_eval:n { #4 + 1 } ) ; - } - \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} -% -% -% -% We will extract the potential keys |columns-type|, |l|, |c|, |r| and pass -% the other keys to the environment |{NiceArrayWithDelims}|. -% \begin{macrocode} -\keys_define:nn { NiceMatrix / Auto } - { - columns-type .code:n = \@@_set_preamble:Nn \l_@@_columns_type_tl { #1 } , - columns-type .value_required:n = true , - l .meta:n = { columns-type = l } , - r .meta:n = { columns-type = r } , - c .meta:n = { columns-type = c } , - delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , - delimiters / color .value_required:n = true , - delimiters / max-width .bool_set:N = \l_@@_delimiters_max_width_bool , - delimiters / max-width .default:n = true , - delimiters .code:n = \keys_set:nn { NiceMatrix / delimiters } { #1 } , - delimiters .value_required:n = true , - } -% \end{macrocode} -% -% \begin{macrocode} -\NewDocumentCommand \AutoNiceMatrixWithDelims - { m m O { } > { \SplitArgument { 1 } { - } } m O { } m ! O { } } - { \@@_auto_nice_matrix:nnnnnn { #1 } { #2 } #4 { #6 } { #3 , #5 , #7 } } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_auto_nice_matrix:nnnnnn #1 #2 #3 #4 #5 #6 - { -% \end{macrocode} -% The group is for the protection of the keys. -% \begin{macrocode} - \group_begin: - \bool_set_true:N \l_@@_Matrix_bool - \keys_set_known:nnN { NiceMatrix / Auto } { #6 } \l_tmpa_tl -% \end{macrocode} -% We nullify the command |\@@_transform_preamble:| because we will provide a -% preamble which is yet transformed (by using |\l_@@_columns_type_tl| which is -% yet nicematrix-ready). -% -% \begin{macrocode} - \cs_set_eq:NN \@@_transform_preamble: \prg_do_nothing: - \use:x - { - \exp_not:N \begin { NiceArrayWithDelims } { #1 } { #2 } - { * { #4 } { \exp_not:V \l_@@_columns_type_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 { #4 - 1 } { & } - \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\ - } - \prg_replicate:nn { #3 } - { - \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 { #4 - 1 } { { } #5 & } #5 - \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 { #4 - 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 } - { - \bool_gset_false:N \g_@@_NiceArray_bool - \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_gset_true:N \g_@@_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 - \tl_gput_right:Nn \g_@@_cell_after_hook_tl \@@_dotfill_i: - } -% \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_i: - { \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_@@_pre_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} -% The last argument is for the name of the block. -% \begin{macrocode} - { } - } - } -% \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 other two 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 - \int_eval:n { #3 + 1 } } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@y - \@@_qpoint:n { col - \int_eval:n { #4 + 1 } } - \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 } - { - \begin { minipage } { 20 cm } - \@@_math_toggle_token: #5 \@@_math_toggle_token: - \end { minipage } - } - { } - { } - \endpgfscope - \pgftransformshift { \pgfpoint \l_@@_tmpd_dim \l_tmpa_dim } - \pgfnode { rectangle } { north~east } - { - \begin { minipage } { 20 cm } - \raggedleft - \@@_math_toggle_token: #6 \@@_math_toggle_token: - \end { minipage } - } - { } - { } - \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 \textsl{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_ii:n } -% \end{macrocode} -% -% \medskip -% However, in each cell of the environment, the command |\CodeAfter| will be -% linked to the following command |\@@_CodeAfter_ii:n| which begins -% with |\\|. -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_CodeAfter_i: { \\ \omit \@@_CodeAfter_ii:n } -% \end{macrocode} -% -% \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_ii:n #1 \end - { - \tl_gput_right:Nn \g_nicematrix_code_after_tl { #1 } - \@@_CodeAfter_iv:n - } -% \end{macrocode} -% -% We catch the argument of the command |\end| (in |#1|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_CodeAfter_iv: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_ii: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_@@_pre_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 - \int_eval:n { \c@iRow + 1 } } - \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 - \@@_color:V \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 } - { - delimiters / color .tl_set:N = \l_@@_delimiters_color_tl , - delimiters / color .value_required: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 , - name .code:n = - \tl_if_empty:nTF { #1 } - { \@@_error:n { Invalid~name } } - { - \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 } } - } , - name .value_required:n = true , - 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 , - 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 - { - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { - \SubMatrix { #1 } { #2 } { #3 } { #4 } - [ - delimiters / color = \l_@@_delimiters_color_tl , - hlines = \l_@@_submatrix_hlines_clist , - vlines = \l_@@_submatrix_vlines_clist , - extra-height = \dim_use:N \l_@@_submatrix_extra_height_dim , - left-xshift = \dim_use:N \l_@@_submatrix_left_xshift_dim , - right-xshift = \dim_use:N \l_@@_submatrix_right_xshift_dim , - slim = \bool_to_str:N \l_@@_submatrix_slim_bool , - #5 - ] - } - \@@_SubMatrix_in_code_before_i { #2 } { #3 } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\NewDocumentCommand \@@_SubMatrix_in_code_before_i - { > { \SplitArgument { 1 } { - } } m > { \SplitArgument { 1 } { - } } m } - { \@@_SubMatrix_in_code_before_i:nnnn #1 #2 } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_SubMatrix_in_code_before_i:nnnn #1 #2 #3 #4 - { - \seq_gput_right:Nx \g_@@_submatrix_seq - { -% \end{macrocode} -% We use |\str_if_eq:nnTF| because it is fully expandable. -% \begin{macrocode} - { \str_if_eq:nnTF { #1 } { last } { \int_use:N \c@iRow } { #1 } } - { \str_if_eq:nnTF { #2 } { last } { \int_use:N \c@jCol } { #2 } } - { \str_if_eq:nnTF { #3 } { last } { \int_use:N \c@iRow } { #3 } } - { \str_if_eq:nnTF { #4 } { last } { \int_use:N \c@jCol } { #4 } } - } - } -% \end{macrocode} -% -% -% \bigskip -% In the pre-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} -\hook_gput_code:nnn { begindocument } { . } - { - \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} -% -% \medskip -% The following macro will compute |\l_@@_first_i_tl|, |\l_@@_first_j_tl|, -% |\l_@@_last_i_tl| and |\l_@@_last_j_tl| from the arguments of the command as -% provided by the user (for example |2-3| and |5-last|). -% \begin{macrocode} -\NewDocumentCommand \@@_compute_i_j:nn - { > { \SplitArgument { 1 } { - } } m > { \SplitArgument { 1 } { - } } m } - { \@@_compute_i_j:nnnn #1 #2 } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_compute_i_j:nnnn #1 #2 #3 #4 - { - \tl_set:Nn \l_@@_first_i_tl { #1 } - \tl_set:Nn \l_@@_first_j_tl { #2 } - \tl_set:Nn \l_@@_last_i_tl { #3 } - \tl_set:Nn \l_@@_last_j_tl { #4 } - \tl_if_eq:NnT \l_@@_first_i_tl { last } - { \tl_set:NV \l_@@_first_i_tl \c@iRow } - \tl_if_eq:NnT \l_@@_first_j_tl { last } - { \tl_set:NV \l_@@_first_j_tl \c@jCol } - \tl_if_eq:NnT \l_@@_last_i_tl { last } - { \tl_set:NV \l_@@_last_i_tl \c@iRow } - \tl_if_eq:NnT \l_@@_last_j_tl { last } - { \tl_set:NV \l_@@_last_j_tl \c@jCol } - } -% \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} - \@@_compute_i_j:nn { #2 } { #3 } - \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:nn { Construct~too~large } { \SubMatrix } } - { - \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 - { - \fp_to_dim:n - { - \pgf@y - + ( \box_ht:N \strutbox + \extrarowheight ) * \arraystretch - } - } % modified 6.13c - \@@_qpoint:n { row - \l_@@_last_i_tl - base } - \dim_set:Nn \l_@@_y_final_dim - { \fp_to_dim:n { \pgf@y - ( \box_dp:N \strutbox ) * \arraystretch } } - % modified 6.13c - \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_zero:N \nulldelimiterspace -% \end{macrocode} -% -% \bigskip -% We will draw the rules in the |\SubMatrix|. -% \begin{macrocode} - \group_begin: - \pgfsetlinewidth { 1.1 \arrayrulewidth } - \@@_set_CT@arc@:V \l_@@_rules_color_tl - \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 or 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 - \@@_color:V \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 - \@@_color:V \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*{Les commandes \textbackslash UnderBrace et \textbackslash -% OverBrace} -% -% The following commands will be linked to |\UnderBrace| and |\OverBrace| in the -% |\CodeAfter|. -% -% \begin{macrocode} -\NewDocumentCommand \@@_UnderBrace { O { } m m m O { } } - { - \peek_remove_spaces:n - { \@@_brace:nnnnn { #2 } { #3 } { #4 } { #1 , #5 } { under } } - } -% \end{macrocode} -% -% \begin{macrocode} -\NewDocumentCommand \@@_OverBrace { O { } m m m O { } } - { - \peek_remove_spaces:n - { \@@_brace:nnnnn { #2 } { #3 } { #4 } { #1 , #5 } { over } } - } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\keys_define:nn { NiceMatrix / Brace } - { - left-shorten .bool_set:N = \l_@@_brace_left_shorten_bool , - left-shorten .default:n = true , - right-shorten .bool_set:N = \l_@@_brace_right_shorten_bool , - shorten .meta:n = { left-shorten , right-shorten } , - right-shorten .default:n = true , - yshift .dim_set:N = \l_@@_brace_yshift_dim , - yshift .value_required:n = true , - yshift .initial:n = \c_zero_dim , - color .tl_set:N = \l_tmpa_tl , - color .value_required:n = true , - unknown .code:n = \@@_error:n { Unknown~key~for~Brace } - } -% \end{macrocode} -% -% \medskip -% |#1| is the first cell of the rectangle (with the syntax $i$\verb+-|+$j$; -% |#2| is the last cell of the rectangle; -% |#3| is the label of the text; -% |#4| is the optional argument (a list of \textsl{key}-\textsl{value} pairs); -% |#5| is equal to |under| or |over|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_brace:nnnnn #1 #2 #3 #4 #5 - { - \group_begin: -% \end{macrocode} -% The four following token lists correspond to the position of the sub-matrix to -% which a brace will be attached. -% \begin{macrocode} - \@@_compute_i_j:nn { #1 } { #2 } - \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 } - { - \str_if_eq:nnTF { #5 } { under } - { \@@_error:nn { Construct~too~large } { \UnderBrace } } - { \@@_error:nn { Construct~too~large } { \OverBrace } } - } - { - \tl_clear:N \l_tmpa_tl - \keys_set:nn { NiceMatrix / Brace } { #4 } - \tl_if_empty:NF \l_tmpa_tl { \color { \l_tmpa_tl } } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \bool_if:NT \l_@@_brace_left_shorten_bool - { - \dim_set_eq:NN \l_@@_x_initial_dim \c_max_dim - \int_step_inline:nnn \l_@@_first_i_tl \l_@@_last_i_tl - { - \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 } - } - } - } - \bool_lazy_or:nnT - { \bool_not_p:n \l_@@_brace_left_shorten_bool } - { \dim_compare_p:nNn \l_@@_x_initial_dim = \c_max_dim } - { - \@@_qpoint:n { col - \l_@@_first_j_tl } - \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x - } - \bool_if:NT \l_@@_brace_right_shorten_bool - { - \dim_set:Nn \l_@@_x_final_dim { - \c_max_dim } - \int_step_inline:nnn \l_@@_first_i_tl \l_@@_last_i_tl - { - \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 } - } - } - } - \bool_lazy_or:nnT - { \bool_not_p:n \l_@@_brace_right_shorten_bool } - { \dim_compare_p:nNn \l_@@_x_final_dim = { - \c_max_dim } } - { - \@@_qpoint:n { col - \int_eval:n { \l_@@_last_j_tl + 1 } } - \dim_set_eq:NN \l_@@_x_final_dim \pgf@x - } - \pgfset { inner~sep = \c_zero_dim } - \str_if_eq:nnTF { #5 } { under } - { \@@_underbrace_i:n { #3 } } - { \@@_overbrace_i:n { #3 } } - \endpgfpicture - } - \group_end: - } -% \end{macrocode} -% -% \medskip -% The argument is the text to put above the brace. -% \begin{macrocode} -\cs_new_protected:Npn \@@_overbrace_i:n #1 - { - \@@_qpoint:n { row - \l_@@_first_i_tl } - \pgftransformshift - { - \pgfpoint - { ( \l_@@_x_initial_dim + \l_@@_x_final_dim) / 2 } - { \pgf@y + \l_@@_brace_yshift_dim - 3 pt} - } - \pgfnode - { rectangle } - { south } - { - \vbox_top:n - { - \group_begin: - \everycr { } - \halign - { - \hfil ## \hfil \crcr - \@@_math_toggle_token: #1 \@@_math_toggle_token: \cr - \noalign { \skip_vertical:n { 3 pt } \nointerlineskip } - \c_math_toggle_token - \overbrace - { - \hbox_to_wd:nn - { \l_@@_x_final_dim - \l_@@_x_initial_dim } - { } - } - \c_math_toggle_token - \cr - } - \group_end: - } - } - { } - { } - } -% \end{macrocode} -% -% -% \medskip -% The argument is the text to put under the brace. -% \begin{macrocode} -\cs_new_protected:Npn \@@_underbrace_i:n #1 - { - \@@_qpoint:n { row - \int_eval:n { \l_@@_last_i_tl + 1 } } - \pgftransformshift - { - \pgfpoint - { ( \l_@@_x_initial_dim + \l_@@_x_final_dim) / 2 } - { \pgf@y - \l_@@_brace_yshift_dim + 3 pt } - } - \pgfnode - { rectangle } - { north } - { - \group_begin: - \everycr { } - \vbox:n - { - \halign - { - \hfil ## \hfil \crcr - \c_math_toggle_token - \underbrace - { - \hbox_to_wd:nn - { \l_@@_x_final_dim - \l_@@_x_initial_dim } - { } - } - \c_math_toggle_token - \cr - \noalign { \skip_vertical:n { 3 pt } \nointerlineskip } - \@@_math_toggle_token: #1 \@@_math_toggle_token: \cr - } - } - \group_end: - } - { } - { } - } -% \end{macrocode} -% -% \bigskip -% \subsection*{The command \textbackslash ShowCellNames} -% -% \begin{macrocode} -\NewDocumentCommand \@@_ShowCellNames_CodeBefore { } - { - \dim_zero_new:N \g_@@_tmpc_dim - \dim_zero_new:N \g_@@_tmpd_dim - \dim_zero_new:N \g_@@_tmpe_dim - \int_step_inline:nn \c@iRow - { - \begin { pgfpicture } - \@@_qpoint:n { row - ##1 } - \dim_set_eq:NN \l_tmpa_dim \pgf@y - \@@_qpoint:n { row - \int_eval:n { ##1 + 1 } } - \dim_gset:Nn \g_tmpa_dim { ( \l_tmpa_dim + \pgf@y ) / 2 } - \dim_gset:Nn \g_tmpb_dim { \l_tmpa_dim - \pgf@y } - \bool_if:NTF \l_@@_in_code_after_bool - \end { pgfpicture } - \int_step_inline:nn \c@jCol - { - \hbox_set:Nn \l_tmpa_box - { \normalfont \Large \color { red ! 50 } ##1 - ####1 } - \begin { pgfpicture } - \@@_qpoint:n { col - ####1 } - \dim_gset_eq:NN \g_@@_tmpc_dim \pgf@x - \@@_qpoint:n { col - \int_eval:n { ####1 + 1 } } - \dim_gset:Nn \g_@@_tmpd_dim { \pgf@x - \g_@@_tmpc_dim } - \dim_gset_eq:NN \g_@@_tmpe_dim \pgf@x - \endpgfpicture - \end { pgfpicture } - \fp_set:Nn \l_tmpa_fp - { - \fp_min:nn - { - \fp_min:nn - { \dim_ratio:nn { \g_@@_tmpd_dim } { \box_wd:N \l_tmpa_box } } - { \dim_ratio:nn { \g_tmpb_dim } { \box_ht_plus_dp:N \l_tmpa_box } } - } - { 1.0 } - } - \box_scale:Nnn \l_tmpa_box { \fp_use:N \l_tmpa_fp } { \fp_use:N \l_tmpa_fp } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \pgftransformshift - { - \pgfpoint - { 0.5 * ( \g_@@_tmpc_dim + \g_@@_tmpe_dim ) } - { \dim_use:N \g_tmpa_dim } - } - \pgfnode - { rectangle } - { center } - { \box_use:N \l_tmpa_box } - { } - { } - \endpgfpicture - } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\NewDocumentCommand \@@_ShowCellNames { } - { - \bool_if:NT \l_@@_in_code_after_bool - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \pgfpathrectanglecorners - { \@@_qpoint:n { 1 } } - { \@@_qpoint:n { \int_eval:n { \c@iRow + 1 } } } - \pgfsetfillopacity { 0.75 } - \pgfsetfillcolor { white } - \pgfusepathqfill - \endpgfpicture - } - \dim_zero_new:N \g_@@_tmpc_dim - \dim_zero_new:N \g_@@_tmpd_dim - \dim_zero_new:N \g_@@_tmpe_dim - \int_step_inline:nn \c@iRow - { - \bool_if:NTF \l_@@_in_code_after_bool - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - } - { \begin { pgfpicture } } - \@@_qpoint:n { row - ##1 } - \dim_set_eq:NN \l_tmpa_dim \pgf@y - \@@_qpoint:n { row - \int_eval:n { ##1 + 1 } } - \dim_gset:Nn \g_tmpa_dim { ( \l_tmpa_dim + \pgf@y ) / 2 } - \dim_gset:Nn \g_tmpb_dim { \l_tmpa_dim - \pgf@y } - \bool_if:NTF \l_@@_in_code_after_bool - { \endpgfpicture } - { \end { pgfpicture } } - \int_step_inline:nn \c@jCol - { - \hbox_set:Nn \l_tmpa_box - { - \normalfont \Large \sffamily \bfseries - \bool_if:NTF \l_@@_in_code_after_bool - { \color { red } } - { \color { red ! 50 } } - ##1 - ####1 - } - \bool_if:NTF \l_@@_in_code_after_bool - { - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - } - { \begin { pgfpicture } } - \@@_qpoint:n { col - ####1 } - \dim_gset_eq:NN \g_@@_tmpc_dim \pgf@x - \@@_qpoint:n { col - \int_eval:n { ####1 + 1 } } - \dim_gset:Nn \g_@@_tmpd_dim { \pgf@x - \g_@@_tmpc_dim } - \dim_gset_eq:NN \g_@@_tmpe_dim \pgf@x - \bool_if:NTF \l_@@_in_code_after_bool - { \endpgfpicture } - { \end { pgfpicture } } - \fp_set:Nn \l_tmpa_fp - { - \fp_min:nn - { - \fp_min:nn - { \dim_ratio:nn { \g_@@_tmpd_dim } { \box_wd:N \l_tmpa_box } } - { \dim_ratio:nn { \g_tmpb_dim } { \box_ht_plus_dp:N \l_tmpa_box } } - } - { 1.0 } - } - \box_scale:Nnn \l_tmpa_box { \fp_use:N \l_tmpa_fp } { \fp_use:N \l_tmpa_fp } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgf@relevantforpicturesizefalse - \pgftransformshift - { - \pgfpoint - { 0.5 * ( \g_@@_tmpc_dim + \g_@@_tmpe_dim ) } - { \dim_use:N \g_tmpa_dim } - } - \pgfnode - { rectangle } - { center } - { \box_use:N \l_tmpa_box } - { } - { } - \endpgfpicture - } - } - } -% \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:nnnn { nicematrix } { Unknown~key~for~package } - { - The~key~'\l_keys_key_str'~is~unknown. \\ - That~key~will~be~ignored. \\ - For~a~list~of~the~available~keys,~type~H~. - } - { - The~available~keys~are~(in~alphabetic~order):~ - footnote,~ - footnotehyper,~ - messages-for-Overleaf,~ - no-test-for-array,~ - renew-dots,~and - renew-matrix. - } -% \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 , - messages-for-Overleaf .bool_set:N = \c_@@_messages_for_Overleaf_bool , - footnote .bool_set:N = \c_@@_footnote_bool , - footnotehyper .bool_set:N = \c_@@_footnotehyper_bool , - no-test-for-array .bool_set:N = \c_@@_no_test_for_array_bool , - no-test-for-array .default:n = true , - 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.\\ - 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.\\ - 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*{About the package underscore} -% -% -% \begin{macrocode} -\bool_new:N \l_@@_underscore_loaded_bool -\@ifpackageloaded { underscore } - { \bool_set_true:N \l_@@_underscore_loaded_bool } - { } -% \end{macrocode} -% -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \bool_if:NF \l_@@_underscore_loaded_bool - { - \@ifpackageloaded { underscore } - { \@@_error:n { underscore~after~nicematrix } } - } - } -% \end{macrocode} -% -% \bigskip -% \subsection*{Error messages of the package} -% -% \begin{macrocode} -\bool_if:NTF \c_@@_messages_for_Overleaf_bool - { \str_const:Nn \c_@@_available_keys_str { } } - { - \str_const:Nn \c_@@_available_keys_str - { For~a~list~of~the~available~keys,~type~H~. } - } -% \end{macrocode} -% -% \begin{macrocode} -\seq_new:N \g_@@_types_of_matrix_seq -\seq_gset_from_clist:Nn \g_@@_types_of_matrix_seq - { - NiceMatrix , - pNiceMatrix , bNiceMatrix , vNiceMatrix, BNiceMatrix, VNiceMatrix - } -\seq_gset_map_x:NNn \g_@@_types_of_matrix_seq \g_@@_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 -% triggered. This command raises an error but also tries 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 \g_@@_types_of_matrix_seq \g_@@_name_env_str - { - \int_compare:nNnTF \l_@@_last_col_int = { -2 } - { \@@_fatal:n { too~much~cols~for~matrix } } - { - \int_compare:nNnTF \l_@@_last_col_int = { -1 } - { \@@_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 } } - } - } - } - { - \bool_lazy_and:nnTF - { \bool_if_p:n \c_@@_tabularx_loaded_bool } - { ! \str_if_eq_p:Vn \g_@@_name_env_str { NiceTabularX } } - { - \int_compare:nNnTF \c@iRow = \c_zero_int - { \@@_fatal:n { X~columns~with~tabularx } } - { - \@@_fatal:nn { too~much~cols~for~array } - { - However,~this~message~may~be~erroneous:~ - maybe~you~have~used~X~columns~while~'tabularx'~is~loaded,~ - ~which~is~forbidden~(however,~it's~still~possible~to~use~ - X~columns~in~{NiceTabularX}). - } - } - } - { \@@_fatal:nn { 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 { negative~weight } - { - Negative~weight.\\ - The~weight~of~the~'X'~columns~must~be~positive~and~you~have~used~ - the~value~'\int_use:N \l_@@_weight_int'.\\ - The~absolute~value~will~be~used. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { last~col~not~used } - { - Column~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 { too~much~cols~for~matrix~with~last~col } - { - Too~much~columns.\\ - In~the~row~\int_eval:n { \c@iRow },~ - 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 } - { - Too~much~columns.\\ - In~the~row~\int_eval:n { \c@iRow },~ - 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~(excepted~the~potential~exterior~ - columns)~is~fixed~by~the~LaTeX~counter~'MaxMatrixCols'.~ - Its~current~value~is~\int_use:N \c@MaxMatrixCols\ (use~ - \token_to_str:N \setcounter\ to~change~that~value).~ - This~error~is~fatal. - } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\@@_msg_new:nn { too~much~cols~for~array } - { - Too~much~columns.\\ - In~the~row~\int_eval:n { \c@iRow },~ - ~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).~#1 - This~error~is~fatal. - } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\@@_msg_new:nn { X~columns~with~tabularx } - { - There~is~a~problem.\\ - You~have~probably~used~X~columns~in~your~environment~{\g_@@_name_env_str}.~ - That's~not~allowed~because~'tabularx'~is~loaded~(however,~you~can~use~X~columns~ - in~an~environment~{NiceTabularX}).\\ - This~error~is~fatal. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { columns~not~used } - { - 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.\\ - The~columns~you~did~not~used~won't~be~created.\\ - We~won't~have~similar~error~till~the~end~of~the~document. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { in~first~col } - { - Erroneous~use.\\ - You~can't~use~the~command~#1 in~the~first~column~(number~0)~of~the~array.\\ - That~command~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { in~last~col } - { - Erroneous~use.\\ - You~can't~use~the~command~#1 in~the~last~column~(exterior)~of~the~array.\\ - That~command~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { in~first~row } - { - Erroneous~use.\\ - You~can't~use~the~command~#1 in~the~first~row~(number~0)~of~the~array.\\ - That~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.\\ - That~command~will~be~ignored. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { caption~outside~float } - { - Key~caption~forbidden.\\ - You~can't~use~the~key~'caption'~because~you~are~not~in~a~floating~ - environment.~This~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { short-caption~without~caption } - { - You~should~not~use~the~key~'short-caption'~without~'caption'.~ - However,~your~'short-caption'~will~be~used~as~'caption'. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { double~closing~delimiter } - { - Double~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 } - { - Double~delimiter.\\ - You~can't~put~a~second~delimiter~"#1"~just~after~a~first~opening~ - delimiter.~That~delimiter~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { bad~option~for~line-style } - { - Bad~line~style.\\ - Since~you~haven't~loaded~Tikz,~the~only~value~you~can~give~to~'line-style'~ - is~'standard'.~That~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Identical~notes~in~caption } - { - Identical~tabular~notes.\\ - You~can't~put~several~notes~with~the~same~content~in~ - \token_to_str:N \caption\ (but~you~can~in~the~main~tabular).\\ - If~you~go~on,~the~output~will~probably~be~erroneous. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { tabularnote~below~the~tabular } - { - \token_to_str:N \tabularnote\ forbidden\\ - You~can't~use~\token_to_str:N \tabularnote\ in~the~caption~ - of~your~tabular~because~the~caption~will~be~composed~below~ - the~tabular.~If~you~want~the~caption~above~the~tabular~use~the~ - key~'caption-above'~in~\token_to_str:N \NiceMatrixOptions.\\ - Your~\token_to_str:N \tabularnote\ will~be~discarded~and~ - no~similar~error~will~raised~in~this~document. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Unknown~key~for~rules } - { - Unknown~key.\\ - There~is~only~two~keys~available~here:~width~and~color.\\ - You~key~'\l_keys_key_str'~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~custom-line } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~in~a~'custom-line'.~ - It~you~go~on,~you~will~probably~have~other~errors. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - ccommand,~ - color,~ - command,~ - dotted,~ - letter,~ - multiplicity,~ - sep-color,~ - tikz,~and~total-width. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~xdots } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~a~command~for~drawing~dotted~rules.\\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - 'color',~ - 'inter',~ - 'line-style',~ - 'radius',~ - 'shorten',~ - 'shorten-end'~and~'shorten-start'. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { Unknown~key~for~rowcolors } - { - Unknown~key.\\ - As~for~now,~there~is~only~two~keys~available~here:~'cols'~and~'respect-blocks'~ - (and~you~try~to~use~'\l_keys_key_str')\\ - That~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { label~without~caption } - { - You~can't~use~the~key~'label'~in~your~'{NiceTabular}'~because~ - you~have~not~used~the~key~'caption'.~The~key~'label'~will~be~ignored. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { W~warning } - { - Line~\msg_line_number:.~The~cell~is~too~wide~for~your~column~'W'~ - (row~\int_use:N \c@iRow). - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Construct~too~large } - { - Construct~too~large.\\ - Your~command~\token_to_str:N #1 - can't~be~drawn~because~your~matrix~is~too~small.\\ - That~command~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { underscore~after~nicematrix } - { - Problem~with~'underscore'.\\ - The~package~'underscore'~should~be~loaded~before~'nicematrix'.~ - You~can~go~on~but~you~won't~be~able~to~write~something~such~as:\\ - '\token_to_str:N \Cdots\token_to_str:N _{n~\token_to_str:N \text{~times}}'. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { ampersand~in~light-syntax } - { - Ampersand~forbidden.\\ - You~can't~use~an~ampersand~(\token_to_str:N &)~to~separate~columns~because~ - ~the~key~'light-syntax'~is~in~force.~This~error~is~fatal. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { double-backslash~in~light-syntax } - { - Double~backslash~forbidden.\\ - You~can't~use~\token_to_str:N - \\~to~separate~rows~because~the~key~'light-syntax'~ - is~in~force.~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 { hlines~with~color } - { - Incompatible~keys.\\ - You~can't~use~the~keys~'hlines',~'vlines'~or~'hvlines'~for~a~ - '\token_to_str:N \Block'~when~the~key~'color'~or~'draw'~is~used.\\ - Maybe~it~will~possible~in~future~version.\\ - Your~key~will~be~discarded. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { bad~value~for~baseline } - { - 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'~or~of~ - the~form~'line-i'.\\ - A~value~of~1~will~be~used. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { ragged2e~not~loaded } - { - You~have~to~load~'ragged2e'~in~order~to~use~the~key~'\l_keys_key_str'~in~ - your~column~'\l_@@_vpos_col_str'~(or~'X').~The~key~'\str_lowercase:V - \l_keys_key_str'~will~be~used~instead. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Invalid~name } - { - Invalid~name.\\ - You~can't~give~the~name~'\l_keys_value_tl'~to~a~\token_to_str:N - \SubMatrix\ of~your~\@@_full_name_env:.\\ - A~name~must~be~accepted~by~the~regular~expression~[A-Za-z][A-Za-z0-9]*.\\ - This~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Wrong~line~in~SubMatrix } - { - Wrong~line.\\ - 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.~It~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Impossible~delimiter } - { - 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'. } \\ - 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.~ - That~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { key~multiplicity~with~dotted } - { - Incompatible~keys. \\ - You~have~used~the~key~'multiplicity'~with~the~key~'dotted'~ - in~a~'custom-line'.~They~are~incompatible. \\ - The~key~'multiplicity'~will~be~discarded. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { empty~environment } - { - Empty~environment.\\ - Your~\@@_full_name_env:\ is~empty.~This~error~is~fatal. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { No~letter~and~no~command } - { - Erroneous~use.\\ - Your~use~of~'custom-line'~is~no-op~since~you~don't~have~used~the~ - key~'letter'~(for~a~letter~for~vertical~rules)~nor~the~keys~'command'~or~ - ~'ccommand'~(to~draw~horizontal~rules).\\ - However,~you~can~go~on. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Forbidden~letter } - { - Forbidden~letter.\\ - You~can't~use~the~letter~'\l_@@_letter_str'~for~a~customized~line.\\ - It~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Several~letters } - { - Wrong~name.\\ - You~must~use~only~one~letter~as~value~for~the~key~'letter'~(and~you~ - have~used~'\l_@@_letter_str').\\ - It~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Delimiter~with~small } - { - Delimiter~forbidden.\\ - 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 } - { - Unknown~cell.\\ - Your~command~\token_to_str:N\line\{#1\}\{#2\}~in~ - the~\token_to_str:N \CodeAfter\ of~your~\@@_full_name_env:\ - can't~be~executed~because~a~cell~doesn't~exist.\\ - This~command~\token_to_str:N \line\ will~be~ignored. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nnn { Duplicate~name~for~SubMatrix } - { - Duplicate~name.\\ - The~name~'#1'~is~already~used~for~a~\token_to_str:N \SubMatrix\ - in~this~\@@_full_name_env:.\\ - This~key~will~be~ignored.\\ - \bool_if:NF \c_@@_messages_for_Overleaf_bool - { 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 } - { - Erroneous~use.\\ - 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:.\\ - This~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Hdotsfor~in~col~0 } - { - Erroneous~use.\\ - 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 } - { - Bad~corner.\\ - #1~is~an~incorrect~specification~for~a~corner~(in~the~key~ - 'corners').~The~available~values~are:~NW,~SW,~NE~and~SE.\\ - This~specification~of~corner~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { bad~border } - { - Bad~border.\\ - \l_keys_key_str\space~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~(and~you~can~ - also~use~the~key~'tikz' - \bool_if:nF \c_@@_tikz_loaded_bool - {~if~you~load~the~LaTeX~package~'tikz'}).\\ - This~specification~of~border~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { tikz~key~without~tikz } - { - Tikz~not~loaded.\\ - You~can't~use~the~key~'tikz'~for~the~command~'\token_to_str:N - \Block'~because~you~have~not~loaded~tikz.~ - This~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { last-col~non~empty~for~NiceArray } - { - Erroneous~use.\\ - 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 } - { - Erroneous~use.\\ - 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 } - { - Block~too~large.\\ - 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 } - { - Block~too~large.\\ - 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:.\\ - This~block~and~maybe~others~will~be~ignored. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nn { unknown~column~type } - { - Bad~column~type.\\ - The~column~type~'#1'~in~your~\@@_full_name_env:\ - is~unknown. \\ - This~error~is~fatal. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { unknown~column~type~S } - { - Bad~column~type.\\ - The~column~type~'S'~in~your~\@@_full_name_env:\ is~unknown. \\ - If~you~want~to~use~the~column~type~'S'~of~siunitx,~you~should~ - load~that~package. \\ - This~error~is~fatal. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { tabularnote~forbidden } - { - Forbidden~command.\\ - You~can't~use~the~command~\token_to_str:N\tabularnote\ - ~here.~This~command~is~available~only~in~ - \{NiceTabular\},~\{NiceTabular*\}~and~\{NiceTabularX\}~or~in~ - the~argument~of~a~command~\token_to_str:N \caption\ included~ - in~an~environment~{table}. \\ - This~command~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { borders~forbidden } - { - Forbidden~key.\\ - 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.\\ - This~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { bottomrule~without~booktabs } - { - booktabs~not~loaded.\\ - You~can't~use~the~key~'tabular/bottomrule'~because~you~haven't~ - loaded~'booktabs'.\\ - This~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { enumitem~not~loaded } - { - enumitem~not~loaded.\\ - You~can't~use~the~command~\token_to_str:N\tabularnote\ - ~because~you~haven't~loaded~'enumitem'.\\ - All~the~commands~\token_to_str:N\tabularnote\ will~be~ - ignored~in~the~document. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { tikz~in~custom-line~without~tikz } - { - Tikz~not~loaded.\\ - You~have~used~the~key~'tikz'~in~the~definition~of~a~ - customized~line~(with~'custom-line')~but~tikz~is~not~loaded.~ - You~can~go~on~but~you~will~have~another~error~if~you~actually~ - use~that~custom~line. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { tikz~in~borders~without~tikz } - { - Tikz~not~loaded.\\ - You~have~used~the~key~'tikz'~in~a~key~'borders'~(of~a~ - command~'\token_to_str:N\Block')~but~tikz~is~not~loaded.~ - That~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { color~in~custom-line~with~tikz } - { - Erroneous~use.\\ - In~a~'custom-line',~you~have~used~both~'tikz'~and~'color',~ - which~is~forbidden~(you~should~use~'color'~inside~the~key~'tikz').~ - The~key~'color'~will~be~discarded. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Wrong~last~row } - { - Wrong~number.\\ - 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 } - { - Nested~environments.\\ - Environments~of~nicematrix~can't~be~nested.\\ - This~error~is~fatal. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Outside~math~mode } - { - 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 } - { - Bad~name.\\ - The~value~of~key~'\l_keys_key_str'~must~be~of~length~1.\\ - It~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { TabularNote~in~CodeAfter } - { - Environment~{TabularNote}~forbidden.\\ - You~must~use~{TabularNote}~at~the~end~of~your~{NiceTabular}~ - but~*before*~the~\token_to_str:N \CodeAfter.\\ - This~environment~{TabularNote}~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { varwidth~not~loaded } - { - varwidth~not~loaded.\\ - You~can't~use~the~column~type~'V'~because~'varwidth'~is~not~ - loaded.\\ - Your~column~will~behave~like~'p'. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknow~key~for~RulesBis } - { - Unkown~key.\\ - Your~key~'\l_keys_key_str'~is~unknown~for~a~rule.\\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - color,~ - dotted,~ - multiplicity,~ - sep-color,~ - tikz,~and~total-width. - } - -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~Block } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~command~\token_to_str:N - \Block.\\ It~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~b,~B,~borders,~c,~draw,~fill,~ - hlines,~hvlines,~l,~line-width,~name,~rounded-corners,~r,~respect-arraystretch,~ - t,~T,~tikz,~transparent~and~vlines. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Version~of~siunitx~too~old } - { - siunitx~too~old.\\ - You~can't~use~'S'~columns~because~your~version~of~'siunitx'~ - is~too~old.~You~need~at~least~v~3.0~and~your~log~file~says:~"siunitx,~ - \use:c { ver @ siunitx.sty }". \\ - This~error~is~fatal. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~Brace } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~commands~\token_to_str:N - \UnderBrace\ and~\token_to_str:N \OverBrace.\\ - It~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~color,~left-shorten,~ - right-shorten,~shorten~(which~fixes~both~left-shorten~and~ - right-shorten)~and~yshift. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~CodeAfter } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown.\\ - It~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - 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~CodeBefore } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown.\\ - It~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - create-cell-nodes,~ - delimiters/color~and~ - sub-matrix~(several~subkeys). - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~SubMatrix } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown.\\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - 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 } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown.\\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - bottomrule,~ - code-after,~ - code-before,~ - detect-duplicates,~ - enumitem-keys,~ - enumitem-keys-para,~ - para,~ - label-in-list,~ - label-in-tabular~and~ - style. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~RowStyle } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~command~ - \token_to_str:N \RowStyle. \\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - 'bold',~ - 'cell-space-top-limit',~ - 'cell-space-bottom-limit',~ - 'cell-space-limits',~ - 'color',~ - 'nb-rows'~and~ - 'rowcolor'. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~NiceMatrixOptions } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~command~ - \token_to_str:N \NiceMatrixOptions. \\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - allow-duplicate-names,~ - caption-above,~ - 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,~ - custom-key,~ - create-extra-nodes,~ - create-medium-nodes,~ - create-large-nodes,~ - delimiters~(several~subkeys),~ - end-of-row,~ - first-col,~ - first-row,~ - hlines,~ - hvlines,~ - hvlines-except-borders,~ - last-col,~ - last-row,~ - left-margin,~ - light-syntax,~ - matrix/columns-type,~ - notes~(several~subkeys),~ - nullify-dots,~ - pgf-node-code,~ - renew-dots,~ - renew-matrix,~ - respect-arraystretch,~ - right-margin,~ - rules~(with~the~subkeys~'color'~and~'width'),~ - small,~ - sub-matrix~(several~subkeys),~ - vlines,~ - xdots~(several~subkeys). - } -% \end{macrocode} -% -% For `|{NiceArray}|`, the set of keys is the same as for |{NiceMatrix}| -% excepted that there is no |l| and |r|. -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~NiceArray } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~environment~ - \{NiceArray\}. \\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - 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,~ - hvlines-except-borders,~ - last-col,~ - last-row,~ - left-margin,~ - light-syntax,~ - name,~ - nullify-dots,~ - pgf-node-code,~ - renew-dots,~ - respect-arraystretch,~ - right-margin,~ - rules~(with~the~subkeys~'color'~and~'width'),~ - small,~ - t,~ - vlines,~ - xdots/color,~ - xdots/shorten-start,~ - xdots/shorten-end,~ - 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 no |l| and |r|). -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~NiceMatrix } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~ - \@@_full_name_env:. \\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - 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-type,~ - columns-width,~ - corners,~ - create-extra-nodes,~ - create-medium-nodes,~ - create-large-nodes,~ - extra-left-margin,~ - extra-right-margin,~ - first-col,~ - first-row,~ - hlines,~ - hvlines,~ - hvlines-except-borders,~ - l,~ - last-col,~ - last-row,~ - left-margin,~ - light-syntax,~ - name,~ - nullify-dots,~ - pgf-node-code,~ - r,~ - renew-dots,~ - respect-arraystretch,~ - right-margin,~ - rules~(with~the~subkeys~'color'~and~'width'),~ - small,~ - t,~ - vlines,~ - xdots/color,~ - xdots/shorten-start,~ - xdots/shorten-end,~ - xdots/shorten~and~ - xdots/line-style. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nnn { Unknown~key~for~NiceTabular } - { - Unknown~key.\\ - The~key~'\l_keys_key_str'~is~unknown~for~the~environment~ - \{NiceTabular\}. \\ - That~key~will~be~ignored. \\ - \c_@@_available_keys_str - } - { - The~available~keys~are~(in~alphabetic~order):~ - b,~ - baseline,~ - c,~ - caption,~ - 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,~ - custom-line,~ - create-extra-nodes,~ - create-medium-nodes,~ - create-large-nodes,~ - extra-left-margin,~ - extra-right-margin,~ - first-col,~ - first-row,~ - hlines,~ - hvlines,~ - hvlines-except-borders,~ - label,~ - last-col,~ - last-row,~ - left-margin,~ - light-syntax,~ - name,~ - notes~(several~subkeys),~ - nullify-dots,~ - pgf-node-code,~ - renew-dots,~ - respect-arraystretch,~ - right-margin,~ - rounded-corners,~ - rules~(with~the~subkeys~'color'~and~'width'),~ - short-caption,~ - t,~ - tabularnote,~ - vlines,~ - xdots/color,~ - xdots/shorten-start,~ - xdots/shorten-end,~ - xdots/shorten~and~ - xdots/line-style. - } -% \end{macrocode} -% -% -% \begin{macrocode} -\@@_msg_new:nnn { Duplicate~name } - { - 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'.\\ - \c_@@_available_keys_str - } - { - 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 } - { - Erroneous~use.\\ - You~can't~give~the~value~'auto'~to~the~key~'columns-width'~here.~ - That~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:\par\nobreak -% -% \smallskip -% { -% \small -% \nolinkurl{https:www.tug.org/svn/texlive/trunk/Master/texmf-dist/tex/latex/nicematrix/nicematrix.sty} -% } -% -% \subsection*{Changes between version 6.17 and 6.18} -% -% New key |opacity| in the commands to color cells, rows and columns. -% -% New key |rounded-corners| for a whole tabular. -% -% -% \subsection*{Changes between version 6.16 and 6.17} -% -% New PGF/Tikz style |nicematrix/cell-node|. -% -% New key |pgf-node-code| -% -% \subsection*{Changes between version 6.15 and 6.16} -% -% It's now possible to put any LaTeX extensible delimiter (|\lgroup|, |\langle|, -% etc.) in the preamble of an environment with preamble (such as |{NiceArray}|) -% by prefixing them by |\left| and |\right|. -% -% New key |code| for the command |\SubMatrix| in the |\CodeAfter|. -% -% \subsection*{Changes between version 6.14 and 6.15} -% -% New key |transparent| for the command |\Block| (with that key, the rules are -% drawn within the block). -% -% \subsection*{Changes between version 6.13 and 6.14} -% -% New keys for the command |\Block| for the vertical position of the content of -% that block. -% -% \subsection*{Changes between version 6.12 and 6.13} -% -% New environment |{TabularNote}| in |{NiceTabular}| with the same semantic as -% the key |tabularnote| (for legibility). -% -% The command |\Hline| nows accepts options (between square brackets). -% -% \subsection*{Changes between version 6.11 and 6.12} -% -% New keys |caption|, |short-caption| and |label| in the environment -% |{NiceTabular}|. -% -% In |{NiceTabular}|, a caption specified by the key |caption| is wrapped to the -% width of the tabular. -% -% Correction of a bug: it's now possible to use |\OverBrace| and |\UnderBrace| -% with \pkg{unicode-math} (with XeLaTeX or LuaLaTeX). -% -% \subsection*{Changes between version 6.10 and 6.11} -% -% New key |matrix/columns-type| to specify the type of columns of the matrices. -% -% New key |ccommand| in |custom-line| and new command |\cdottedline|. -% -% \subsection*{Changes between version 6.9 and 6.10} -% -% New keys |xdots/shorten-start| and |xdots/shorten-end|. -% -% It's possible to use |\line| in the |\CodeAfter| between two blocks (and not -% only two cells). -% -% \subsection*{Changes between version 6.8 and 6.9} -% -% New keys |xdots/radius| and |xdots/inter| for customisation of the continuous -% dotted lines. -% -% New command |\ShowCellNames| available in the |\CodeBefore| and in the |\CodeAfter|. -% -% \subsection*{Changes between version 6.7 and 6.8} -% -% In the notes of a tabular (with the command |\tabularnote|), the duplicates -% are now detected: when several commands |\tabularnote| are used with the same -% argument, only one note is created at the end of the tabular (but all the -% labels are present, of course). -% -% \subsection*{Changes between version 6.6 and 6.7} -% -% Key |color| for |\OverBrace| and |\UnderBrace| in the |\CodeAfter| -% -% Key |tikz| in the key |borders| of a command |\Block| -% -% \subsection*{Changes between version 6.5 and 6.6} -% -% Keys |tikz| and |width| in |custom-line|. -% -% \subsection*{Changes between versions 6.4 and 6.5} -% -% Key |custom-line| in |\NiceMatrixOptions|. -% -% Key |respect-arraystretch|. -% -% \subsection*{Changes between versions 6.3 and 6.4} -% -% New commands |\UnderBrace| and |\OverBrace| in the |\CodeAfter|. -% -% Correction of a bug of the key |baseline| (cf. question 623258 on TeX StackExchange). -% -% Correction of a bug with the columns |V| of \pkg{varwidth}. -% -% Correction of a bug: the use of |\hdottedline| and |:| in the preamble of the -% array (of another letter specified by |letter-for-dotted-lines|) was -% incompatible with the key |xdots/line-style|. -% -% \subsection*{Changes between versions 6.2 and 6.3} -% -% Keys |nb-rows|, |rowcolor| and |bold| for the command |\RowStyle| -% -% Key |name| for the command |\Block|. -% -% Support for the columns |V| of \pkg{varwidth}. -% -% \subsection*{Changes between versions 6.1 and 6.2} -% -% Better compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}. -% -% Key |vlines-in-sub-matrix|. -% -% \subsection*{Changes between versions 6.0 and 6.1} -% -% Better computation of the widths of the |X| columns. -% -% Key |\color| for the command |\RowStyle|. -% -% \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 5.18 and 5.19} -% -% New key |tikz| for the command |\Block|. -% -% \subsection*{Changes between versions 5.17 and 5.18} -% -% New command |\RowStyle| -% -% \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.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.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.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.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.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.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.9 and 5.10} -% -% New command |\SubMatrix| available in the |\CodeAfter|. -% -% It's possible to provide options (between brackets) to the keyword |\CodeAfter|. -% -% \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.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.6 and 5.7} -% -% New key |delimiters-color| -% -% Keys |fill|, |draw| and |line-width| for the command |\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.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.3 and 5.4} -% -% Key |tabularnote|. -% -% Different behaviour for the mono-column blocks. -% -% \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.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.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 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 4.3 and 4.4} -% -% New key |hvlines-except-corners| (now deprecated). -% -% \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.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.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 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 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.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.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.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.10 and 3.11} -% -% Correction of a bug linked to |first-row| and |last-row|. -% -% \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 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.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.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.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.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.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.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 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.1 and 3.2 (and 3.2a)} -% -% Option |small|. -% -% \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 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 2.2.1 and 2.3} -% -% Compatibility with the column type |S| of \pkg{siunitx}. -% -% Option |hlines|. -% -% \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.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.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.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.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 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.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 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 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.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 versions 1.1 and 1.2} -% -% New environment |{NiceArray}| with column types |L|, |C| and |R|. -% -% \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. -% -% -% -% \newpage -% \tableofcontents -% -% \endinput -% Local Variables: -% TeX-fold-mode: t -% TeX-fold-preserve-comments: nil -% fill-column: 80 -% End: - - diff --git a/macros/latex/contrib/nicematrix/nicematrix.ins b/macros/latex/contrib/nicematrix/nicematrix.ins index 814600f7c2..2fff6fcb8c 100644 --- a/macros/latex/contrib/nicematrix/nicematrix.ins +++ b/macros/latex/contrib/nicematrix/nicematrix.ins @@ -30,7 +30,7 @@ and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. \endpreamble -\generate{\file{nicematrix.sty}{\from{nicematrix.dtx}{package}}} +\generate{\file{nicematrix.sty}{\from{nicematrix-code.dtx}{package}}} \Msg{*********************************************************} \Msg{*} \Msg{* To finish the installation you have to move the} diff --git a/macros/latex/contrib/nicematrix/nicematrix.pdf b/macros/latex/contrib/nicematrix/nicematrix.pdf index 7b447a8a11..474dac2ee0 100644 Binary files a/macros/latex/contrib/nicematrix/nicematrix.pdf and b/macros/latex/contrib/nicematrix/nicematrix.pdf differ diff --git a/macros/latex/contrib/nicematrix/nicematrix.tex b/macros/latex/contrib/nicematrix/nicematrix.tex new file mode 100644 index 0000000000..6cf322afa9 --- /dev/null +++ b/macros/latex/contrib/nicematrix/nicematrix.tex @@ -0,0 +1,7484 @@ +% -*- coding: utf-8 ; -*- This file should be compiled with XeLaTeX only +\documentclass[dvipsnames]{article}% dvipsnames is for xcolor (loaded by Tikz, loaded by nicematrix) +\usepackage{xltxtra} + +\usepackage{geometry} +\geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}} + +\usepackage{nicematrix} + +\usepackage{tikz} +\usetikzlibrary{fit,patterns,arrows.meta,decorations.pathmorphing} + +\usepackage{enumitem} +\usepackage{siunitx} +\usepackage{verbatim} +\usepackage{caption} +\usepackage{tocloft} +\setlength{\cftsubsecnumwidth}{3em} % for the numbers of subsections of the TOC + +% On utilise \MakeShortVerb de shortvrb et pas \DefineShortVerb de fancyvrb +% car on ne veut pas que le contenu des petits Ă©lĂ©ments en verbatim soit coloriĂ© +% en gris +\usepackage{shortvrb} +\MakeShortVerb{\|} + +\usepackage{fancyvrb} +\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} + +\def\LetterAt{@} + +\def\interitem{\vspace{7mm plus 2 mm minus 3mm}} +\def\emphase{\bgroup\color{RoyalPurple}\let\next=} + +\usepackage{footnote} +\usepackage{booktabs} +\usepackage{varwidth} +\usepackage{tcolorbox} +\usepackage{adjustbox} +\usepackage[auto-lang=false]{lipsum} + +\NewDocumentEnvironment {scope} {} {} {} + +\NewDocumentCommand {\pkg} {m} {\textsf{#1}} +\NewDocumentCommand {\cls} {m} {\textsf{#1}} + +\setlength{\parindent}{0pt} +\skip \footins = 2 \bigskipamount + + +\NewDocumentCommand{\Definition}{m} + {{\setlength{\fboxsep}{1pt}\colorbox{gray!20}{\ttfamily \vphantom{gl}#1}}} + +\usepackage{makeidx} +\makeindex + +\NewDocumentCommand{\indexcommand}{m}{\index{#1@\texttt{\textbackslash #1}}} + +\NewDocumentCommand{\indexenv}{m}{\index{#1@\texttt{\{#1\}}}} + +\usepackage[hyperfootnotes = false]{hyperref} + +\hypersetup + { + pdfinfo = + { + Title = The package 'nicematrix' , + Subject = A LaTeX package , + Author = F. Pantigny + } + } + + + +\begin{document} + +\VerbatimFootnotes + + +\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}} + + +\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, TeX Live or MacTeX. + +\medskip +\emph{Remark}\par\nobreak + +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}} + +\medskip +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.} + +\medskip +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}|. + + +\medskip +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 +a sufficient number of compilations.} + +\medskip +Most features of \pkg{nicematrix} may be used without explicit use of +\textsc{pgf} or Tikz (which, in fact, is not loaded by default). + +\medskip +\indexcommand{NiceMatrixOptions} +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 +The environment |{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 environment |{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} +\index{cell-space-top-limit} +\index{cell-space-bottom-limit} +\index{cell-space-limits} + + +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} +\frac{1}{2} & -\frac{1}{2} \\ +\frac{1}{3} & \frac{1}{4} \\ +\end{pmatrix}$ +\end{BVerbatim} +$\begin{pmatrix} +\frac{1}{2} & -\frac{1}{2} \\ +\frac{1}{3} & \frac{1}{4} \\ +\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 of \pkg{cellspace} called +|\cellspacetoplimit| and +|\cellspacebottomlimit|.\index{cellspace@\pkg{cellspace} (package)} + +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} + +\index{baseline (key for an environment)} + +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]@ +\dfrac{1}{A} & \dfrac{1}{B} & 0 & 0 \\ +\dfrac{1}{C} & \dfrac{1}{D} & 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] +\dfrac{1}{A} & \dfrac{1}{B} & 0 & 0 \\ +\dfrac{1}{C} & \dfrac{1}{D} & 0 & 0 \\ +\hline +0 & 0 & A & B \\ +0 & 0 & D & D \\ +\end{pNiceArray}$} +\end{scope} + + +\section{The blocks} +\label{Block} + +\index{Blocks@\textbf{Blocks in the tabulars}|(} +\indexcommand{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}|, +|{NiceTabular*}| and |{NiceTabularX}|, 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}{cw{c}{1cm}c|c}[margin] +~emphase#\Block{3-3}{A}@ & & & 0 \\ +& & & \Vdots \\ +& & & 0 \\ +\hline +0 & \Cdots& 0 & 0 +\end{bNiceArray}$ +\end{BVerbatim} +$\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] +\Block{3-3}{A} & & & 0 \\ +& & & \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}{cw{c}{1cm}c|c}[margin] +\Block{3-3}~emphase#<\Large>@{A} & & & 0 \\ +0 & & & \Vdots \\ +& & & 0 \\ +\hline +0 & \Cdots& 0 & 0 +\end{bNiceArray}$ +\end{BVerbatim} +\begin{scope} +$\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] +\Block{3-3}<\Large>{A} & & & 0 \\ +& & & \Vdots \\ +& & & 0 \\ +\hline +0 & \Cdots& 0 & 0 +\end{bNiceArray}$ +\end{scope} + + + +\interitem +In fact, the command |\Block| accepts as first optional argument (between +square brackets) a list of couples \textsl{key=value}. The available keys are as +follows: +\begin{itemize} +\item \index{fill (key of \texttt{\textbackslash Block})} +the key \Definition{fill} takes in as value a color and fills the block +with that color; +\item \index{draw (key of \texttt{\textbackslash Block})} +the key \Definition{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 \index{color!key of \texttt{\textbackslash Block}} +the key \Definition{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 \index{vlines!key of \texttt{\textbackslash Block}} +\index{hvlines!key of \texttt{\textbackslash Block}} +\index{hlines!key of \texttt{\textbackslash Block}} +the keys \Definition{hlines}, \Definition{vlines} and +\Definition{hvlines} draw all the corresponding rules in the +block;\footnote{However, the rules are not drawn in the sub-blocks of the +block, as always with \pkg{nicematrix}: the rules are not drawn in the blocks +(cf. section~\ref{rules} p.~\pageref{rules}).} +\item \index{line-width (key of \texttt{\textbackslash Block})} +the key \Definition{line-width} is the width of the rules (is relevant +only when one of the keys |draw|, |hvlines|, |vlines| and |hlines| is used); +\item \index{rounded-corners!key of \texttt{\textbackslash Block}} +\index{Corners (rounded ---)!for a block} +the key \Definition{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 \index{tikzz@tikz!key of \texttt{\textbackslash Block}} +when the key \Definition{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}; +\item \index{name!key of \texttt{\textbackslash Block}} +the key \Definition{name} provides a name to the rectangular Tikz node +corresponding to the block; it's possible to use that name with Tikz in the +|\CodeAfter| of the environment (cf.~p.~\pageref{code-after}); +\item \index{respect-arraystretch (key of \texttt{\textbackslash Block})} +the key \Definition{respect-arraystretch} prevents the setting of +|\arraystretch| to $1$ at the beginning of the block (which is the behaviour +by default) ; +\item \index{borders (key of \texttt{\textbackslash Block})} +\index{tikzz@tikz!key of ``borders'' de \texttt{\textbackslash Block}} +the key \Definition{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|; it's possible, in +fact, in the list which is the value of the key |borders|, to add an entry of +the form |tikz={|\textsl{list}|}| where \textsl{list} is a list of couples +\textsl{key=value} of Tikz specifying the graphical characteristics of the +lines that will be drawn (for an example, see p.~\pageref{dashed}). +\item \index{transparent (key of \texttt{\textbackslash Block})} +By default, the rules are not drawn in the blocks (see the section about +the rules: section~\ref{rules} p.~\pageref{rules}). However, if the key +\Definition{transparent} is used, the rules are drawn. For an example, see +section~\ref{tikz-key-examples} on page~\pageref{tikz-key-examples}. Caution: +that key does not imply that the content of the block will be transparent! +\end{itemize} + +There is also keys for the horizontal and vertical positions of the content of +the block: cf.~\ref{horizontal-block} p.~\pageref{horizontal-block}. + +\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 |w{c}{...}| of \pkg{array}). + +\bigskip +\begin{BVerbatim} +\begin{NiceTabular}{cw{c}{2cm}w{c}{3cm}c} +rose & tulip & daisy & dahlia \\ +violet +& ~emphase#\Block[draw=red,fill=[RGB]{204,204,255},rounded-corners]{2-2}@ + ~emphase#{\LARGE Some beautiful flowers}@ + & & marigold \\ +iris & & & lis \\ +arum & periwinkle & forget-me-not & hyacinth +\end{NiceTabular} +\end{BVerbatim} + +\medskip +\begin{center} +\begin{NiceTabular}{cw{c}{2cm}w{c}{3cm}c} +rose & tulip & daisy & dahlia \\ +violet & \Block[draw=red,fill=[RGB]{204,204,255},rounded-corners]{2-2} + {\LARGE Some beautiful flowers} & & marigold \\ + iris & & & lis \\ + arum & periwinkle & forget-me-not & hyacinth +\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. + +In the columns with a fixed width (columns |w{...}{...}|, |W{...}{...}|, +|p{...}|, |b{...}|, |m{...}|, |V| 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 (but the +|\Block| may have its own specification of alignment: +cf.~\ref{horizontal-block} p.~\pageref{horizontal-block}). + +\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} + +\label{horizontal-block} + +The command |\Block| accepts the keys |l|, |c| and |r| for the horizontal +position of its content. + +\medskip +\begin{BVerbatim}[baseline=c,boxwidth=10.6cm] +$\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] +\Block~emphase#[r]@{3-3}<\LARGE>{A} & & & 0 \\ +& & & \Vdots \\ +& & & 0 \\ +\hline +0 & \Cdots& 0 & 0 +\end{bNiceArray}$ +\end{BVerbatim} +$\begin{bNiceArray}{cw{c}{1cm}c|c}[margin] +\Block[r]{3-3}<\LARGE>{A} & & & 0 \\ +& & & \Vdots \\ +& & & 0 \\ +\hline +0 & \Cdots& 0 & 0 +\end{bNiceArray}$ + + +\medskip +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|. + +\medskip +Here is the same example with the key |C| for the first block. + +\medskip +\begin{center} +\fvset{commandchars=\~\#\+} +\begin{BVerbatim} +\begin{NiceTabular}{@{}c!{\qquad}ccc~emphase#!{\qquad}+ccc@{}} +\toprule +Rank & ~emphase#\Block[C]{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[C]{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} + + +\subsection{Vertical position of the content of the block} + + +For the vertical position, the command |\Blocks| accepts the keys +|v-center|\footnote{That key could not have been named |c| since the key |c| +is used for the horizontal alignement.}, +|t|, |b|, |T| and |B|. + + +\begin{itemize} +\item \index{v-center (key of \texttt{\textbackslash Block})} +With the key |v-center|, the content of the block is vertically centered. +\item With the key |t|, the baseline of the content of the block is aligned +With the basline of the first row concerned by the block). +\item with the key |b|, the baseline of the last row of the content of the +block (we recall that the content of a block may contains several lines +separated by |\\|) is aligned with the baseline of the last of the rows of the +array involved in the block. +\item With the key |T|, the content of the block is set upwards. + +\colorbox{yellow!50}{\textbf{Modification 6.18}}\enskip No vertical margin is +added. However, the contents of the block is (always) composed by +\pkg{nicematrix} in a |{minipage}|, a |{tabular}| or an |{array}| and, hence, +there will still remain a margin (in most cases). + +\item With the key |B|, the content of the block is set downwards. +\end{itemize} + +When no key is given, the key |v-center| applies (excepted in the mono-row blocks). + + + +\medskip +\begin{scope} +\NiceMatrixOptions{rules/color=[gray]{0.75}, hvlines} + +\begin{BVerbatim} +\NiceMatrixOptions{rules/color=[gray]{0.75}, hvlines} +\end{BVerbatim} + +\bigskip + +\begin{BVerbatim}[baseline=c,boxwidth=10cm] +\begin{NiceTabular}{ccc} +\Block[fill=red!10,~emphase#t@,l]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc} +\Block[fill=red!10,t,l]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} + + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=10cm] +\begin{NiceTabular}{ccc} +\Block[fill=red!10,~emphase#b@,r]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc} +\Block[fill=red!10,b,r]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=10cm] +\begin{NiceTabular}{ccc} +\Block[fill=red!10,~emphase#T@,l]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc} +\Block[fill=red!10,T,l]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} + + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=10cm] +\begin{NiceTabular}{ccc} +\Block[fill=red!10,~emphase#B@,r]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc} +\Block[fill=red!10,B,r]{4-2}{two\\lines} + & & \Huge Un\\ + & & deux \\ + & & trois \\ + & & \Huge quatre \\ +text & text \\ +\end{NiceTabular} + + +\end{scope} + +\index{Blocks@\textbf{Blocks in the tabulars}|)} + + +\section{The rules} + +\label{rules} +\index{Rules@\textbf{Rules in the tabulars}|(} +\index{Lines in the tabulars|see{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 the package~\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}) nor in the potential exterior rows (created by the +keys |first-row| and |last-row|: cf.~p.~\pageref{exterior}). + +\bigskip +\index{booktabs@\pkg{booktabs} (package)} +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} + + +\bigskip +\subsubsection{The command \textbackslash cline} + +\label{remark-cline} +\index{cline@\texttt{\textbackslash cline} (LaTeX command)} + +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 +\index{standard-cline} +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}@ +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} +A&B&C&D \\ +\hline +\end{NiceTabular} +\end{scope} + +\medskip +In the environments of \pkg{nicematrix}, an instruction |\cline{|\textsl{\texttt{i}}|}| +is equivalent to |\cline{|\textsl{\texttt{i}}|-|\textsl{\texttt{i}}|}|. + + +\subsection{The thickness and the color of the rules} + +\indexcommand{arrayrulewidth} +\index{Colour!of the rules} +\index{width!subkey of ``rules''} +\index{rules (key for an environment)} + +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 +\indexcommand{arrayrulecolor} +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} + + + +\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 \indexcommand{Hline} +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), nor in the exterior rows and +columns.} +\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}). +\item For the exterior rows and columns, see~p.~\pageref{exterior}. +\end{itemize} + +In particular, this remark explains the difference between the standard +command |\hline| and the command |\Hline| provided by \pkg{nicematrix}. + +The key |\Hline| takes in an optional argument (between square brackets) which +is a list of \textsl{key=value} pairs. For the description of those keys, see +|custom-line| on p.~\pageref{custom-line}. + +\subsubsection{The keys hlines and vlines} + +\index{hlines|see{Rules}} +\index{hlines!key for an environment} +\index{vlines|see{Rules}} +\index{vlines!key for an environment} + +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.\footnote{It's possible to put in that list some intervals of integers +with the syntax $i$|-|$j$.} + +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} + +\index{hvlines|see{Rules}} +\index{hvlines!key for an environment} +\index{hvlines-except-borders} + + +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 +It's worth noting that, when the key |rounded-corners| is used for the +environment |{NiceTabular}|, the key |hvlines| draws rounded corners for the +exterior frame of the tabular: cf. part~\ref{tabular-rounded-corners}, +p.~\pageref{tabular-rounded-corners}. + +\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. For an +example of use of that key, see the part ``Use with tcolorbox'', +p.~\pageref{tcolorbox}. + +\subsubsection{The (empty) corners} + +\label{corners} +\index{Corners (the empty ---)} +\index{corners (key of an environment)} + +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. The precise definition of a ``non-empty cell'' is given below (cf. +p.~\pageref{empty-cells}).} + +However, it's possible, for a cell without content, to require \pkg{nicematrix} +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|\footnote{The key |corners| that we describe now +has no direct link with the key |rounded-corners| described in the part +\ref{tabular-rounded-corners}, p.~\pageref{tabular-rounded-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). + +\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} + +\indexcommand{diagbox} + +The command |\diagbox| (inspired by the package \pkg{diagbox}), allows, when +it is used in a cell, to slash that cell diagonally downwards. + +\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{Commands for customized rules} + +\label{custom-line} +\index{command (key of ``custom-line'')} +\index{ccommand (key of ``custom-line'')} +\index{letter (key of ``custom-line'')} +\index{custom-line|(} + + +It's also possible to define commands and letters for customized rules with +the key |custom-line| available in |\NiceMatrixOptions| and in the options of +individual environments. That key takes in as argument a list of +\textsl{key=value} pairs. First, there is three keys to define the tools which +will be used to use that new type of rule. + +\begin{itemize} +\item the key |command| is the name (without the backslash) of a command that +will be created by \pkg{nicematrix} and that will be available for the final +user in order to draw horizontal rules (similarly to |\hline|); + +\item the key |ccommand| is the name (without the backslash) of a command +that will be created by \pkg{nicematrix} and that will be available for the +final user to order to draw partial horizontal rules (similarly to |\cline|, +hence the name |ccommand|): the argument of that command is a list of +intervals of columns specified by the syntax~$i$ or $i$-$j$.\footnote{It's +recommended to use such commands only once in a row because each use will +create space between the rows corresponding to the total width of the rule.} + +\item the key |letter| takes in as argument a letter\footnote{The following +letters are forbidden: \verb+lcrpmbVX|()[]!@<>+} that the user will use in +the preamble of an environment with preamble (such as |{NiceTabular}| in order +to specify a vertical rule. +\end{itemize} + +\bigskip +We will now speak of the keys which describe the rule itself. Those keys may +also be used in the (optional) argument of an individual command |\Hline|. + +There is three possibilities. + +\begin{itemize} +\item \emph{First possibility}\par\nobreak + +It's possible to specify composite rules, with a color and a color for the +inter-rule space (as possible with \pkg{colortbl} for instance). + +\begin{itemize} +\index{multiplicity (key of ``custom-line'')} +\index{color!key of ``custom-line''} +\index{sep-color (key of ``custom-line'')} +\item the key |multiplicity| is the number of consecutive rules that will be +drawn: for instance, a value of $2$ will create double rules such those +created by |\hline\hline| or \verb+||+ in the preamble of an environment; + +\item the key |color| sets the color of the rules ; + +\item the key |sep-color| sets the color between two successive rules (should be +used only in conjonction with |multiplicity|). +\end{itemize} + +\medskip +That system may be used, in particular, for the definition of commands and +letters to draw rules with a specific color (and those rules will respect the +blocks and corners as do all the rules of \pkg{nicematrix}). + +\medskip +\begin{Verbatim} +\begin{NiceTabular}{lcIcIc}~emphase#[custom-line = {letter=I, color=blue}]@ +\hline + & \Block{1-3}{dimensions} \\ + & L & l & h \\ +\hline +Product A & 3 & 1 & 2 \\ +Product B & 1 & 3 & 4 \\ +Product C & 5 & 4 & 1 \\ +\hline +\end{NiceTabular} +\end{Verbatim} + + +\begin{center} +\begin{NiceTabular}{lcIcIc}[custom-line = {letter=I, color=blue}] +\hline + & \Block{1-3}{dimensions} \\ + & L & l & H \\ +\hline +Product A & 3 & 1 & 2 \\ +Product B & 1 & 3 & 4 \\ +Product C & 5 & 4 & 1 \\ +\hline +\end{NiceTabular} +\end{center} + + +\bigskip +\item \emph{Second possibility}\par\nobreak + +\index{tikzz@tikz!key of ``custom-line''} +\index{total-width (key of ``custom-line'')} + +It's possible to use the key |tikz| (if Tikz is loaded). In that case, the +rule is drawn directly with Tikz by using as parameters the value of the key +|tikz| which must be a list of \textsl{key=value} pairs which may be applied +to a Tikz path. + +By default, no space is reserved for the rule that will be drawn with Tikz. It +is possible to specify a reservation (horizontal for a vertical rule and +vertical for an horizontal one) with the key |total-width|. That value of that +key, is, in some ways, the width of the rule that will be drawn +(\pkg{nicematrix} does not compute that width from the characteristics of the +rule specified in |tikz|). + + + +\bigskip +Here is an example with the key |dotted| of Tikz. + +\begin{BVerbatim}[boxwidth=9cm,baseline=c] +\NiceMatrixOptions + { + custom-line = + { + letter = I , + ~emphase#tikz = dotted@ , + ~emphase#total-width = \pgflinewidth@ + } + } + +\begin{NiceTabular}{cIcIc} +one & two & three \\ +four & five & six \\ +seven & eight & nine +\end{NiceTabular} +\end{BVerbatim} +\begin{scope} +\NiceMatrixOptions + { + custom-line = + { + letter = I , + tikz = dotted , + total-width = \pgflinewidth + } + } +\begin{NiceTabular}{cIcIc} +one & two & three \\ +four & five & six \\ +seven & eight & nine +\end{NiceTabular} +\end{scope} + +\bigskip +\item \emph{Third possibility} : the key |dotted| +\label{dotted} +\index{dotted (key of ``custom-line'')} +\indexcommand{hdottedline} +\indexcommand{cdottedline} + +As one can see, the dots of a dotted line of Tikz have the shape of a square, +and not a circle. That's why the extension \pkg{nicematrix} provides in the +key |custom-line| a key |dotted| which will draw rounded dots. The initial +value of the key |total-width| is, in this case, equal to the diameter of the dots +(but the user may change the value with the key |total-width| if needed). Those +dotted rules are also used by \pkg{nicematrix} to draw continuous dotted rules +between cells of the matrix with |\Cdots|, |\Vdots|, etc. (cf. p.~\pageref{Cdots}). + +In fact, \pkg{nicematrix} defines by default the commands |\hdottedline| and +|\cdottedline |and the letter ``|:|'' for those dotted +rules.\footnote{However, it's possible to overwrite those definitions with a +|custom-line| (in order, for example, to switch to dashed lines).} + +\smallskip +\begin{BVerbatim} + +\NiceMatrixOptions % ~textsl#present in nicematrix.sty@ + { + custom-line = + { + letter = : , + command = hdottedline , + ccommand = cdottedline , + ~emphase#dotted@ + } + } +\end{BVerbatim} + +Thus, it's possible to use the commands |\hdottedline| and |\cdottedline |to +draw horizontal dotted rules. + +\medskip +\begin{BVerbatim}[baseline=c,boxwidth=9.5cm] +\begin{pNiceMatrix} +1 & 2 & 3 & 4 & 5 \\ +~emphase#\hdottedline@ +6 & 7 & 8 & 9 & 10 \\ +~emphase#\cdottedline{1,4-5}@ +11 & 12 & 13 & 14 & 15 +\end{pNiceMatrix} +\end{BVerbatim} +$\begin{pNiceMatrix} +1 & 2 & 3 & 4 & 5 \\ +\hdottedline +6 & 7 & 8 & 9 & 10 \\ +\cdottedline{1,4-5} +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)$ + +\end{itemize} + +\index{custom-line|)} +\index{Rules@\textbf{Rules in the tabulars}|)} + + +\section{The color of the rows and columns} + +\index{Colour!of the cells} + +\subsection{Use of colortbl} + +\index{colortbl@\pkg{colortbl} (package)} + +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} +\index{code-before!key for an environment} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}} +\index{Body@\texttt{\textbackslash Body}|see{\texttt{\textbackslash CodeBefore}}} + +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 a sufficient 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#options@]@ + ~textsl#instructions of the code-before@ +~emphase#\Body@ + ~textsl#contents of the environment@ +\end{pNiceArray} +\end{Verbatim} + +\smallskip +The optional argument between square brackets is a list of \textsl{key=value} +pairs which will be presented progressively in this +documentation.\footnote{The available keys are |create-cell-nodes|, +|sub-matrix| (and its subkeys) and \texttt{delimiters-color}.} + +\medskip +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} + +\index{cellcolor@\texttt{\textbackslash cellcolor}!command of + \texttt{\textbackslash CodeBefore}} +\index{rectanglecolor@\texttt{\textbackslash rectanglecolor} (command of + \texttt{\textbackslash CodeBefore})} +\index{rowcolor@\texttt{\textbackslash rowcolor}!command of \texttt{\textbackslash CodeBefore}} +\index{columncolor@\texttt{\textbackslash columncolor}!command of + \texttt{\textbackslash CodeBefore}} +\index{rowcolors@\texttt{\textbackslash rowcolors} (command of \texttt{\textbackslash CodeBefore})} +\index{rowlistcolor@\texttt{\textbackslash rowlistcolors} (command of + \texttt{\textbackslash CodeBefore})} +\index{chessboardcolors@\texttt{\textbackslash chessboardcolors}!(commande + du \texttt{\textbackslash CodeBefore})} +\index{arraycolor@\texttt{\textbackslash arraycolor} (command of \texttt{\textbackslash + CodeBefore)}} + +\medskip +These commands don't color the cells which are in the ``corners'' if the key +|corners| is used. That key has been described p.~\pageref{corners}. + +\medskip +These commands respect the rounded corners if the key |rounded-corners| +(described in the part \ref{tabular-rounded-corners} at the +page~\pageref{tabular-rounded-corners}) has been used. + +\medskip +All these commands accept an optional argument, between square brackets and +in first position. That optional argument may contain two elements (separated +by a comma) +\begin{itemize} +\item the colorimetric space (|RGB|, |rgb|, |HTML|, etc) as specified by the +the extension \pkg{xcolor}; +\item \index{opacity (key of commands such as\newline \texttt{\textbackslash rowcolor}, etc.)} +\colorbox{yellow!50}{\textbf{New 6.18}}\par\nobreak +a specification of opacity f the form \texttt{opacity = \textsl{value}}. +\end{itemize} + +\bigskip + +We describe now in detail those commands. + +\medskip +\begin{itemize} +\item The command \Definition{\textbackslash 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. In fact, despite its name, this command may +be used to color a whole row (with the syntax $i$-) or a whole column (with the +syntax -$j$). + +\medskip +\begin{scope} +\hfuzz=10cm +\begin{BVerbatim}[boxwidth=10cm,baseline=c] +\begin{NiceTabular}{ccc}[hvlines] +\CodeBefore + ~emphase#\cellcolor[HTML]{FFFF88}{3-1,2-2,-3}@ +\Body +a & b & c \\ +e & f & g \\ +h & i & j \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc}[hvlines] +\CodeBefore + \cellcolor[HTML]{FFFF88}{3-1,2-2,-3} +\Body +a & b & c \\ +e & f & g \\ +h & i & j \\ +\end{NiceTabular} +\end{scope} + +\bigskip +\item The command \Definition{\textbackslash 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}{ccc}[hvlines] +\CodeBefore + ~emphase#\rectanglecolor{blue!15}{2-2}{3-3}@ +\Body +a & b & c \\ +e & f & g \\ +h & i & j \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc}[hvlines] +\CodeBefore + \rectanglecolor{blue!15}{2-2}{3-3} +\Body +a & b & c \\ +e & f & g \\ +h & i & j \\ +\end{NiceTabular} +\end{scope} + +\bigskip +\item The command \Definition{\textbackslash 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 \Definition{\textbackslash 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{columns-width}). + + +\bigskip +\item The command \Definition{\textbackslash 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 \Definition{\textbackslash columncolor} takes its name from +the command |\columncolor| of \pkg{colortbl}. Its syntax is similar to the +syntax of |\rowcolor|. + +\bigskip +\item The command \Definition{\textbackslash rowcolors} (with a \emph{s}) +takes its name from the command |\rowcolors| of \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 two 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 +\textsl{key=value} (the optional argument in the first position corresponds to +the colorimetric space). The available keys are |cols|, |restart| and +|respect-blocks|. + +\index{cols (key of \texttt{\textbackslash rowcolors} of \texttt{\textbackslash CodeBefore})} +\index{restart (key of \texttt{\textbackslash rowcolors} of \texttt{\textbackslash CodeBefore})} +\index{respect-blocks (key of \texttt{\textbackslash rowcolors} du\newline \texttt{\textbackslash CodeBefore})} + +\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 The extension \pkg{nicematrix} provides also a command +\Definition{\textbackslash 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. + +\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} + +\bigskip +It's also possible to use in the command |\rowlistcolors| a color series +defined by the command |\definecolorseries| of \pkg{xcolor} (and initialized +with the command |\resetcolorseries|\footnote{For the initialization, in the +following example, you have used the counter |iRow| which, when used in the +|\CodeBefore| (and in the |\CodeAfter|) corresponds to the number of rows of +the array: cf.~p~\pageref{iRow}. That leads to an adjustement of the gradation +of the colors to the size of the tabular.}). + +\index{definecolorseries@\texttt{\textbackslash definecolorseries} (command of \pkg{xcolor})} +\index{resetcolorseries@\texttt{\textbackslash resetcolorseries} (command of \pkg{xcolor})} + +\smallskip +\begin{BVerbatim}[boxwidth=12.5cm,baseline=c] +\begin{NiceTabular}{c} +\CodeBefore + ~emphase#\definecolorseries{BlueWhite}{rgb}{last}{blue}{white}@ + ~emphase#\resetcolorseries{\value{iRow}}{BlueWhite}@ + ~emphase#\rowlistcolors{1}{BlueWhite!!+}@ +\Body +Peter \\ +James \\ +Abigail \\ +Elisabeth \\ +Claudius \\ +Jane \\ +Alexandra \\ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{c} +\CodeBefore + \definecolorseries{BlueWhite}{rgb}{last}{blue}{white} + \resetcolorseries[\value{iRow}]{BlueWhite} + \rowlistcolors{1}{BlueWhite!!+} +\Body +Peter \\ +James \\ +Abigail \\ +Elisabeth \\ +Claudius \\ +Jane \\ +Alexandra \\ +\end{NiceTabular} +\end{itemize} + +\vspace{1cm} +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 +\index{corners (key of an environment)|textit} +\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 \emph{not} loaded by \pkg{nicematrix}. + +\medskip +\index{rotate@\texttt{\textbackslash rotate}|textit} +\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} + +\index{S (the columns S of \pkg{siunitx})|textit} +\medskip +We have used the type of column |S| of \pkg{siunitx}. + + +\subsection{Color tools with the syntax of colortbl} + +\index{colortbl-like} +\index{cellcolor@\texttt{\textbackslash cellcolor}!command in tabular} +\index{rowcolor@\texttt{\textbackslash rowcolor}!command in tabular} +\index{columncolor@\texttt{\textbackslash columncolor}!command in the preamble + of an environment} + + +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;\footnote{However, this command +|\cellcolor| will delete the following spaces, which does not the command +|\cellcolor| of \pkg{colortbl}.} +\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} + +\smallskip +\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} +\indexcommand{RowStyle} +\index{cell-space-top-limit} +\index{cell-space-bottom-limit} +\index{cell-space-limits} + + +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 \textsl{key=value} pairs. +\begin{itemize} +\item \index{nb-rows (key of \texttt{\textbackslash RowStyle})} The key |nb-rows| sets +the number of rows to which the specifications of the current command will +apply (with the special value |*|, it will apply to all the following rows). +\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 \index{rowcolor (key of \texttt{\textbackslash RowStyle})} +\index{color!key of \texttt{\textbackslash RowStyle}} +The key |rowcolor| sets +the color of the background and 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|, |X| and |V| (which start in +vertical mode).} +\item \index{bold (key of \texttt{\textbackslash RowStyle})} The key |bold| +enforces bold characters for the cells of the row, both in math and text mode. +\end{itemize} + +\medskip +\begin{BVerbatim}[boxwidth=12cm,baseline=c] +\begin{NiceTabular}{cccc} +\hline +~emphase#\RowStyle[cell-space-limits=3pt]{\rotate}@ +first & second & third & fourth \\ +~emphase#\RowStyle[nb-rows=2,rowcolor=blue!50,color=white]{\sffamily}@ +1 & 2 & 3 & 4 \\ +I & II & III & IV +\end{NiceTabular} +\end{BVerbatim} +\index{rotate@\texttt{\textbackslash rotate}|textit} +\begin{NiceTabular}{cccc} +\hline +\RowStyle[cell-space-limits=3pt]{\rotate} +first & second & third & fourth \\ +\RowStyle[nb-rows=2,rowcolor=blue!50,color=white]{\sffamily} +1 & 2 & 3 & 4 \\ +I & II & III & IV \\ +\end{NiceTabular} + +\medskip +The command |\rotate| is described p.~\pageref{rotate}. + +\section{The width of the columns} + +\label{width} +\index{width@\textbf{Width of the columns}|(} + +\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#W{c}{2cm}@cc}[hvlines] +Paris & New York & Madrid \\ +Berlin & London & Roma \\ +Rio & Tokyo & Oslo +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{W{c}{2cm}cc}[hvlines] +Paris & New York & Madrid \\ +Berlin & London & Roma \\ +Rio & Tokyo & Oslo +\end{NiceTabular} + + +\bigskip +\index{columns-width} +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 +\index{NiceMatrixBlock@\texttt{\{NiceMatrixBlock\}}} +\index{auto-columns-width!(key of \texttt{\{NiceMatrixBlock\}})} +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} +\index{tabularx@\pkg{tabularx} (package)} +\index{NiceTabularX@\texttt{\{NiceTabularX\}}} +\index{X (the columns X)} +\index{width!key of \texttt{\{NiceTabular\}}} + +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| (in +|{NiceTabular}| or in |\NiceMatrixOptions|). The initial value of this +parameter is |\linewidth| (and not |\textwidth|). + +For sake of similarity with the environment |{tabularx}|, \pkg{nicematrix} +also provides an environment |{NiceTabularX}| with a syntax similar to the +syntax of |{tabularx}|, that is to say with a first mandatory argument +which is the width of the tabular.\footnote{If \pkg{tabularx} is loaded, one +must use |{NiceTabularX}| (and not |{NiceTabular}|) in order to use the +columns |X| (this point comes from a conflict in the definitions of the +specifier |X|).} + +As with the packages \pkg{tabu}\footnote{The extension \pkg{tabu} is now +considered as deprecated.} 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 a positive +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$).\footnote{The negative values of the weight, as provided +by \pkg{tabu} (which is now obsolete), are \emph{not} supported by \pkg{nicematrix}. +If such a value is used, an error will be raised.} +\item It's possible to specify an horizontal alignment with one of the +letters |l|, |c| and |r| (which insert respectively |\raggedright|, +|\centering| and |\raggedleft| followed by |\arraybackslash|). +\item It's possible to specify a vertical alignment 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} + + +\subsection{The columns V of varwidth} + +\label{varwidth} +\index{varwidth@\pkg{varwidth} (package)} +\index{V (the columns V of \pkg{varwidth})} + + +Let's recall first the behaviour of the environment |{varwidth}| of the +eponymous package \pkg{varwidth}. That environment is similar to the classical +environment |{minipage}| but the width provided in the argument is only the +\emph{maximal} width of the created box. In the general case, the width of the +box constructed by an environment |{varwidth}| is the natural width of its +contents. + +\medskip +That point is illustrated on the following examples. + +\medskip +\begin{BVerbatim}[baseline=c,boxwidth=6cm] +\fbox{% +\begin{~emphase#varwidth@}{8cm} +\begin{itemize} +\item first item +\item second item +\end{itemize} +\end{~emphase#varwidth@}} +\end{BVerbatim} +\fbox{\begin{varwidth}{8cm} +\begin{itemize} +\item first item +\item second item +\end{itemize} +\end{varwidth}} + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=6cm] +\fbox{% +\begin{~emphase#minipage@}{8cm} +\begin{itemize} +\item first item +\item second item +\end{itemize} +\end{~emphase#minipage@}} +\end{BVerbatim} +\fbox{\begin{minipage}{8cm} +\begin{itemize} +\item first item +\item second item +\end{itemize} +\end{minipage}} + + +\bigskip +The package \pkg{varwidth} provides also the column type |V|. A column of type +|V{|$\langle$\textsl{dim}$\rangle$|}| encapsulates all its cells in a +|{varwidth}| with the argument $\langle$\textsl{dim}$\rangle$ (and does also some tuning). + +\smallskip +When the package \pkg{varwidth} is loaded, the columns |V| of \pkg{varwidth} +are supported by \pkg{nicematrix}. + +\medskip +\begin{Verbatim} +\begin{NiceTabular}[corners=NW,hvlines]{~emphase#V{3cm}V{3cm}V{3cm}@} +& some text & some very very very long text \\ +some very very very long text \\ +some very very very long text +\end{NiceTabular} +\end{Verbatim} + +\medskip +\begin{center} +\begin{NiceTabular}[corners=NW,hvlines]{V{3cm}V{3cm}V{3cm}} +& some text & some very very very long text \\ +some very very very long text \\ +some very very very long text +\end{NiceTabular} +\end{center} + +\bigskip +Concerning \pkg{nicematrix}, one of the +interests of this type of columns is that, for a cell of a column of type~|V|, +the PGF/Tikz node created by \pkg{nicematrix} for the content of that cell has +a width adjusted to the content of the cell : cf. p.~\pageref{node-V}. + + +\bigskip +The columns |V| of \pkg{nicematrix} supports the keys |t|, |p|, |m|, |b|, |l|, +|c| and |r| also supported by the columns |X|: see their description in the +section~\ref{X-columns}, p.~\pageref{X-columns}. + +\bigskip +One should remark that the extension \pkg{varwidth} (at least in its version +0.92) has some problems: for instance, with LuaLaTeX, it does not work when +the content begins with |\color|. + +\index{width@\textbf{Width of the columns}|)} + + +\bigskip +\section{The exterior rows and columns} + +\index{first-row} +\index{last-row} +\index{first-col} +\index{last-col} + +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 (mathematical) +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 exterior 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 and 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 +\index{code-for-first-row} +\index{code-for-first-col} +\index{code-for-last-row} +\index{code-for-last-col} +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. This remark also applies to the +customized rules created by the key |custom-line| +(cf.~p.~\pageref{custom-line}). + +\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} +\index{dotted@\textbf{Dotted lines}|(} +\indexcommand{Ldots} +\indexcommand{Cdots} +\index{Ddots@\texttt{\textbackslash Ddots}|textbf} +\index{Iddots@\texttt{\textbackslash Iddots}|textbf} +\indexcommand{Vdots} +\index{mathdots@\pkg{mathdots} (package)} +\index{xdots (and its subkeys)} + +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 example, 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}} + +\indexcommand{Hspace} +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} + +\index{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} + +\indexcommand{Hdotsfor} +\indexcommand{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} + +\index{renew-matrix} +\index{renew-dots} + +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|.} + +\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} +\index{color!key for the dotted rules} +\index{radius (key for the dotted rules)} +\index{inter (key for the dotted rules)} +\index{line-style (key for the dotted rules)} +\index{shorten (key for the dotted rules)} +\index{shorten-end (key for the dotted rules)} +\index{shorten-start (key for the dotted rules)} + +The dotted lines drawn by |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, |\Iddots|, +|\Hdotsfor| and |\Vdotsfor| (and by the command |\line| in the |\CodeAfter| +which is described p.~\pageref{line-in-code-after}) may be customized by the following +options (specified between square brackets after the command): +\begin{itemize} +\item |color|; +\item |radius|; +\item |shorten-start|, |shorten-end| and |shorten|; +\item |inter|; +\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| (\textsl{xdots} to remind that it works for +|\Cdots|, |\Ldots|, |\Vdots|, etc.), and, thus have for names: +\begin{itemize} +\item |xdots/color|; +\item |xdots/radius|; +\item |xdots/shorten-start|, |xdots/shorten-end| and |xdots/shorten|; +\item |xdots/inter|; +\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/radius}\par\nobreak + +The option |radius| fixes the radius of the dots. The initial value is 0.53~pt. + +\bigskip +\textbf{The option xdots/shorten}\par\nobreak + +\smallskip +The keys |xdots/shorten-start| and |xdots/shorten-end| fix the margin at the +extremities of the line. The key |xdots/shorten| fixes both parameters. +The initial value is 0.3~em (it is recommanded to use a unit of length +dependent of the current font). + +\bigskip +\textbf{The option xdots/inter}\par\nobreak + +\smallskip +The option |xdots/inter| fixes the length between the dots. The initial value +is 0.45~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. Nevertheless, you can +have a look at the following page to see how to have dotted rules with rounded +dots in Tikz:\newline \small +\url{https://tex.stackexchange.com/questions/52848/tikz-line-with-large-dots}} + +\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|, by the keys |hlines|, |vlines|, +|hvlines| and |hvlines-except-borders| and by the tools created by +|custom-line| 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}$ + +\index{dotted@\textbf{Dotted lines}|)} + +\section{Delimiters in the preamble of the environment} + +\index{blkarray@\pkg{blkarray} (package)} + +\label{delimiters-in-preamble} + +In the environments with preamble (|{NiceArray}|, |{pNiceArray}|, etc.), it's +possible to put vertical delimiters directly in the preamble of the +environment.\footnote{This syntax is inspired by the extension \pkg{blkarray}.} + +\smallskip +\index{left@\texttt{\textbackslash left} : used by \pkg{nicematrix} for\newline + delimiters in the preambles} +\index{right@\texttt{\textbackslash right} : used by \pkg{nicematrix} for\newline + delimiters in the preambles} +The opening delimiters should be prefixed by the keyword |\left| and the +closing delimiters by the keyword |\right|. It's not mandatory to use +|\left| and |\right| pair-wise. + +\smallskip +All the vertical extensible delimiters of LaTeX are allowed. + +\medskip +Here is a example which uses the delimiters |\lgroup| and |\rgroup|. + +\smallskip +\begin{BVerbatim} +$\begin{NiceArray}{~emphase#\left\lgroup@ ccc~emphase#\right\rgroup@ l} +1 & 2 & 3 & +4 & 1 & 6 & +7 & 8 & 9 & \scriptstyle L_3 \gets L_3 + L_1 + L_2 +\end{NiceArray}$ +\end{BVerbatim} + +\[\begin{NiceArray}{\left\lgroup ccc\right\rgroup l} +1 & 2 & 3 & \\ +4 & 1 & 6 & \\ +7 & 8 & 9 & \scriptstyle L_3 \gets L_3 + L_1 + L_2 +\end{NiceArray}\] + +\medskip +For this example, it would also have been possible to use the environment +|{NiceArrayWithDelims}| (cf. the section \ref{NiceArrayWithDelims}, +p.~\pageref{NiceArrayWithDelims}) and the key |last-col| (cf. p.~\pageref{exterior}). + +\bigskip +There is a particular case: for the delimiters |(|, |[| and |\{| (and the +corresponding closing delimiters), the prefixes |\left| et |\right| are +optional.\footnote{For the delimiters |[| and |]|, the prefixes remain mandatory +when there is a conflict of notation with the square brackets for the options +of some descriptors of columns.} + + + +\bigskip +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}\] + + +\bigskip +For more complex constructions, in particular with delimiters spanning only a +\emph{subset} of the rows of the array, one should consider the command +|\SubMatrix| available in the |\CodeAfter|. See the section~\ref{sub-matrix}, +p.~\pageref{sub-matrix}. + +\section{The \textbackslash CodeAfter} + +\index{CodeAfter@\texttt{\textbackslash CodeAfter}|(} +\index{code-after} + +\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 +\index{sub-matrix (key of \texttt{\textbackslash CodeAfter}, with subkeys)} +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).\footnote{Here are the keys accepted in that argument: +|delimiters/color|, |rules| and its sub-keys and |sub-matrix| (linked to the +command |\SubMatrix|) and its sub-keys.} + + +\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, several special commands are available in the |\CodeAfter|: |line|, +|\SubMatrix|, |\OverBrace| and |\UnderBrace|. We will now present these commands. + +\subsection{The command \textbackslash line in the \textbackslash CodeAfter} + +\label{line-in-code-after} +\index{line@\texttt{\textbackslash line} (command of \texttt{\textbackslash CodeAfter})} +The command |\line| draws directly dotted lines between cells or blocks. It takes in two +arguments for the cells or blocks to link. Both argument may be: +\begin{itemize} +\item a specification of cell of the form $i$-$j$ where is the +number of the row and $j$ is the number of the column; +\item the name of a block (created by the command |\Block| with the key |name| +of that command). +\end{itemize} +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 (and the \textbackslash CodeBefore)} + +\label{sub-matrix} +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})|textbf} + + +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 \textsl{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 \emph{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}$ + +\medskip +Eventually, in this example, it would probably have been easier to put the +delimiters directly in the preamble of |{NiceArray}| (see +section~\ref{delimiters-in-preamble}, p.~\pageref{delimiters-in-preamble}) +with the following construction. + +\medskip +\begin{scope} +\hfuzz=15cm +\begin{BVerbatim}[boxwidth=11cm,baseline=c] +$\begin{NiceArray}{~emphase#(ccc)(c)@}[cell-space-limits=2pt] + 1 & 1 & 1 & x \\ +\dfrac{1}{4} & \dfrac{1}{2} & \dfrac{1}{4} & y \\ + 1 & 2 & 3 & z +\end{NiceArray}$ +\end{BVerbatim} +\end{scope} +$\begin{NiceArray}{(ccc)(c)}[cell-space-limits=2pt] + 1 & 1 & 1 & x \\ +\dfrac{1}{4} & \dfrac{1}{2} & \dfrac{1}{4} & y \\ + 1 & 2 & 3 & z +\end{NiceArray}$ + +\bigskip +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 +\index{left-xshift (key of \texttt{\textbackslash SubMatrix})} +\index{right-xshift (key of \texttt{\textbackslash SubMatrix})} +\index{xshift (key of \texttt{\textbackslash SubMatrix})} +\Definition{left-xshift} and \Definition{right-xshift} shift +horizontally the delimiters (there exists also the key \Definition{xshift} +which fixes both parameters); +\item \index{extra-height (key of \texttt{\textbackslash SubMatrix})} +\Definition{extra-height} adds a quantity to the total height of the +delimiters (height |\ht| + depth |\dp|); +\item \index{delimiters!---/color pour \texttt{\textbackslash SubMatrix}} +\Definition{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 \index{slim (key of \texttt{\textbackslash SubMatrix})} +\Definition{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 \index{vlines!key of \texttt{\textbackslash SubMatrix}} +\Definition{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 \index{hlines!key of \texttt{\textbackslash SubMatrix}} +\Definition{hlines} is similar to |vlines| but for the horizontal rules; +\item \index{hvlines!key of \texttt{\textbackslash SubMatrix}} +\Definition{hvlines}, which must be used without value, draws all the +vertical and horizontal rules; +\item \index{code (key of \texttt{\textbackslash SubMatrix})} +\Definition{code} insert code, especially TikZ code, after the +construcion of the submatrix. That key is detailed below. +\end{itemize} +One should remark that the 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 +Despite its name, the command |\SubMatrix| may also be used within a +|{NiceTabular}|. Here is an example (which uses |\bottomrule| and +|\toprule| of \pkg{booktabs}). + +\medskip +\begin{BVerbatim}[baseline=c] +\begin{NiceTabular}{~@{}ll~@{}} +\toprule +Part A & the first part \\ +\Block{2-1}{Part B} & a first sub-part \\ + & a second sub-part \\ +\bottomrule +\CodeAfter + ~emphase#\SubMatrix{\{}{2-2}{3-2}{.}@ +\end{NiceTabular} +\end{BVerbatim} +\hspace{2cm} +\begin{NiceTabular}{@{}ll@{}} +\toprule +Part A & the first part \\ +\Block{2-1}{Part B} & a first sub-part \\ + & a second sub-part \\ +\bottomrule +\CodeAfter + \SubMatrix{\{}{2-2}{3-2}{.} +\end{NiceTabular} + +\bigskip +The command |\SubMatrix| is, in fact, also available in the |\CodeBefore|. By +using |\SubMatrix| in the |\CodeBefore|, the delimiters drawn by those +commands |\SubMatrix| are taken into account to limit the continuous dotted +lines (drawn by |\Cdots|, |\Vdots|, etc.) which have an open extremity. + +For an example, see voir \ref{submatrix-in-codebefore} +p.~\pageref{submatrix-in-codebefore}. + + +\vspace{1cm} +The key |code| of the command |\SubMatrix| allows the insertion of code after +the construction of the submatrix. It's meant to be used to insert TikZ +instructions because, in the TikZ instructions inserted by that code, the +nodes of the form |i-j| and \verb+i-|j+ are interpreted with |i| and |j| as +numbers of row and columns \emph{relative to the submatrix}.\footnote{Be +careful: the syntax \verb+j|-i+ is \emph{not} allowed.} + +\medskip +\begin{scope} +\fvset{commandchars=\~\#\!}% +\begin{Verbatim} +$\begin{NiceArray}{ccc@{}w{c}{5mm}@{}ccc} + & & && -1 & 1 & 2 \\ + & & && 0 & 3 & 4 \\ + & & && 0 & 0 & 5 \\ + 1 & 2 & 3 && -1 & 7 & 25 \\ + 0 & 4 & 5 && 0 & 12 & 41 \\ + 0 & 0 & 6 && 0 & 0 & 30 +\CodeAfter + ~emphase#\NewDocumentCommand{\MyDraw}{}{\tikz \draw [blue] (2-|1) -| (3-|2) -| (4-|3) ;}! + \SubMatrix({1-5}{3-7})[~emphase#code = \MyDraw!] + \SubMatrix({4-1}{6-3})[~emphase#code = \MyDraw!] + \SubMatrix({4-5}{6-7})[~emphase#code = \MyDraw!] +\end{NiceArray}$ +\end{Verbatim} +\end{scope} + + +\[\begin{NiceArray}{ccc@{}w{c}{5mm}@{}ccc} + & & && -1 & 1 & 2 \\ + & & && 0 & 3 & 4 \\ + & & && 0 & 0 & 5 \\ + 1 & 2 & 3 && -1 & 7 & 25 \\ + 0 & 4 & 5 && 0 & 12 & 41 \\ + 0 & 0 & 6 && 0 & 0 & 30 +\CodeAfter + \NewDocumentCommand{\MyDraw}{}{\tikz \draw [blue] (2-|1) -| (3-|2) -| (4-|3) ;} + \SubMatrix({1-5}{3-7})[code = \MyDraw ] + \SubMatrix({4-1}{6-3})[code = \MyDraw ] + \SubMatrix({4-5}{6-7})[code = \MyDraw ] +\end{NiceArray}\] + +\medskip +As we see, the drawing done by our command |\MyDraw| is \emph{relative} to the +submatrix to which it is applied. + +\subsection{The commands \textbackslash OverBrace and \textbackslash +UnderBrace in the \textbackslash CodeAfter} + +\index{UncerBrace@\texttt{\textbackslash UnderBrace} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})} +\index{OverBrace@\texttt{\textbackslash OverBrace} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})} + +The commands |\OverBrace| and |\UnderBrace| provide a way to put +horizontal braces on a part of the array. These commands take in three +arguments: +\begin{itemize} +\item the first 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 second argument is the lower-right corner with the same syntax; +\item the third argument is the label of the brace that will be put by +\pkg{nicematrix} (with \textsc{pgf}) above the brace (for the command +|\OverBrace|) or under the brace (for |\UnderBrace|). +\end{itemize} + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=9cm] +\begin{pNiceMatrix} +1 & 2 & 3 & 4 & 5 & 6 \\ +11 & 12 & 13 & 14 & 15 & 16 \\ +\CodeAfter + ~emphase#\OverBrace{1-1}{2-3}{A}@ + ~emphase#\OverBrace{1-4}{2-6}{B}@ +\end{pNiceMatrix} +\end{BVerbatim} +$\begin{pNiceMatrix} +1 & 2 & 3 & 4 & 5 & 6 \\ +11 & 12 & 13 & 14 & 15 & 16 \\ +\CodeAfter + \OverBrace{1-1}{2-3}{A} + \OverBrace{1-4}{2-6}{B} +\end{pNiceMatrix}$ + +\bigskip +Caution : There is no vertical space reserved for those braces.\footnote{See: + \url{https://tex.stackexchange.com/questions/685755}} + + +\bigskip +\index{color!key of \texttt{\textbackslash OverBrace} and \texttt{\textbackslash + UnderBrace}} +\index{yshift (key of \texttt{\textbackslash OverBrace} and \texttt{\textbackslash + UnderBrace})} +\index{left-shorten (key of \texttt{\textbackslash OverBrace} and\newline \texttt{\textbackslash + UnderBrace})} +\index{right-shorten (key of \texttt{\textbackslash OverBrace} and\newline \texttt{\textbackslash + UnderBrace})} + +In fact, the commands |\OverBrace| and |\UnderBrace| take in an optional +argument (in first position and between square brackets) for a list of +\textsl{key=value} pairs. The available keys are: +\begin{itemize} +\item |left-shorten| and |right-shorten| which do not take in value; when the +key |left-shorten| is used, the abscissa of the left extremity of the brace is +computed with the contents of the cells of the involved sub-array, otherwise, +the position of the potential vertical rule is used (idem for +|right-shorten|). + +\item |shorten|, which is the conjunction of the keys |left-shorten| and +|right-shorten|; + +\item |yshift|, which shifts vertically the brace (and its label); + +\item |color|, which sets the color of the brace (and its label). +\end{itemize} + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=9cm] +\begin{pNiceMatrix} +1 & 2 & 3 & 4 & 5 & 6 \\ +11 & 12 & 13 & 14 & 15 & 16 \\ +\CodeAfter + \OverBrace~emphase#[shorten,yshift=3pt]@{1-1}{2-3}{A} + \OverBrace~emphase#[shorten,yshift=3pt]@{1-4}{2-6}{B} +\end{pNiceMatrix} +\end{BVerbatim} +$\begin{pNiceMatrix} +1 & 2 & 3 & 4 & 5 & 6 \\ +11 & 12 & 13 & 14 & 15 & 16 \\ +\CodeAfter + \OverBrace[shorten,yshift=3pt]{1-1}{2-3}{A} + \OverBrace[shorten,yshift=3pt]{1-4}{2-6}{B} +\end{pNiceMatrix}$ + +\index{CodeAfter@\texttt{\textbackslash CodeAfter}|)} + +\section{Captions and notes in the tabulars} + +\label{s:notes} + +\subsection{Caption of a tabular} + +\label{s:caption} + +\index{caption (key of \texttt{\{NiceTabular\}})} +\index{short-caption} +\index{label (key of \texttt{\{NiceTabular\}})} +\index{caption-above} +\index{caption@\textbf{Captions of the tabulars}} + +\smallskip +The environment |{NiceTabular}| provides the keys |caption|, |short-caption| +and |label| which may be used when the tabular is inserted in a floating +environment (typically the environment |{table}|). + +\smallskip +With the key |caption|, the caption, when it is long, is wrapped at the width of +the tabular (excepted the potential exterior columns specified by |first-col| +and |last-col|: cf.~\ref{exterior}, p.~\pageref{exterior}), without the use of +the package \pkg{threeparttable} or the package \pkg{floatrow}. + +\smallskip +By default, the caption is composed below the tabular. With the key +|caption-above|, available in |\NiceMatrixOptions|, the caption will be +composed above the tabular. + +\smallskip +The key |short-caption| corresponds to the optional argument of the clasical +command |\caption| and the key |label| corresponds, of course, to the command +|\label|. + +\smallskip +See table \ref{t:tabularnote}, p.~\pageref{t:tabularnote}, for an example of +use the keys |caption| and |label|. + +\smallskip +These functionnalities are compatible with the extension \pkg{caption}. + +\subsection{The footnotes} + +\index{footnote@\pkg{footnote} (package)} +\index{footnote (key)} +\index{footnotehyper@\pkg{footnotehyper} (package)} +\index{footnotehyper (key)} + +\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 foot of the page +with the other notes of the document. + +\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} + +\index{nota@\textbf{Notes in the tabulars}|(} +\index{tabularnote@\texttt{\textbackslash tabularnote}} + + +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 specified by |first-col| and |last-col|: cf.~\ref{exterior}, +p.~\pageref{exterior}). With no surprise, that command is available only in the +environments |{NiceTabular}|, |{NiceTabular*}| and |{NiceTabularX}|. + +In fact, this command is available only if the extension \pkg{enumitem} +\index{enumitem@\pkg{enumitem} (package required to use\newline \texttt{\textbackslash tabularnote})} 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 \index{tabularnote (key of \texttt{\{NiceTabular\}})} +There is a key |tabularnote| which provides a way to insert some text in +the zone of the notes before the numbered tabular notes. + +\index{tabularnote@\texttt{\{TabularNote\}}} +An alternative syntax is available with the environment |{TabularNote}|. That +environment should be used at the end of the environment |{NiceTabular}| (but +\emph{before} a potential instruction |\CodeAfter|). + +\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 (or in a +command |\captionof| of the package \pkg{caption}). It's also possible, as +expected, to use the command |\tabularnote| in the caption provided by the +\emph{key} |caption| of the environment |{NiceTabaular}|. + +If several commands |\tabularnote| are used in a tabular with the same +argument, only one note is inserted at the end of the tabular (but all the +labels are composed, of course). It's possible to control that feature with +the key |notes/detect-duplicates|.\footnote{For technical reasons, the final +user is not allowed to put several commands |\tabularnote| with exactly the +same argument in the caption of the tabular.} + +\item It's possible to create a reference to a tabular note created by |\tabularnote| +(with the usual command |\label| used after the |\tabularnote|). + +\item \colorbox{yellow!50}{\textbf{New 6.19}} The command |\tabularnote| has an +optional argument (between square brackets) to change the symbol of the +reference of the note. + +\emph{Example}: |\tabularnote[$\star$]{A footnote...}| +\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 (the package \pkg{caption} has been loaded in this document). + +\begin{center} +\fvset{commandchars=\~\#\!} +\begin{Verbatim}[formatcom=\small\color{gray}] +\begin{table} +\centering +\NiceMatrixOptions{caption-above} +\begin{NiceTabular}{@{}llc@{} + [ + caption = A tabular whose caption has been specified by the key + \texttt{caption}~emphase#\tabularnote[$\star$]{It's possible to put a tabular note in the caption}! , + label = t:tabularnote , + tabularnote = Some text before the notes. , + notes/bottomrule + ] +\toprule +Last name & First name & Length of life \\ +\midrule +Churchill & Wiston & 91\\ +Nightingale~emphase#\tabularnote{Considered as the first nurse of history}!% +~emphase#\tabularnote{Nicknamed ``the Lady with the Lamp''.}! +& Florence~emphase#\tabularnote{This note is shared by two references.}! & 90 \\ +Schoelcher & Victor & 89~emphase#\tabularnote{The label of the note is overlapping.}!\\ +Touchet & Marie~emphase#\tabularnote{This note is shared by two references.}! & 89 \\ +Wallis & John & 87 \\ +\bottomrule +\end{NiceTabular} +\end{table} +\end{Verbatim} +\end{center} + + +\begin{table}[hbt] +\centering +\NiceMatrixOptions{caption-above} +\begin{NiceTabular}{@{}llc@{}}[ + caption = A tabular whose caption has been specified by the key + \texttt{caption}\tabularnote[$\star$]{It's possible to put a tabular note in the caption} , + label = t:tabularnote , + tabularnote = Some text before the notes. , + notes/bottomrule + ] +\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\tabularnote{This note is shared by two references.} & 90 \\ +Schoelcher & Victor & 89\tabularnote{The label of the note is overlapping.}\\ +Touchet & Marie\tabularnote{This note is shared by two references.} & 89 \\ +Wallis & John & 87 \\ +\bottomrule +\end{NiceTabular} +\end{table} + + +\subsection{Customisation of the tabular notes} + +\index{para (subkey of ``notes'')} +\index{bottomrule (subkey of ``notes'')} +\index{style (subkey of ``notes'')} +\index{label-in-tabular (subkey of ``notes'')} +\index{label-in-list (subkey of ``notes'')} +\index{enumitem-keys (subkey of ``notes'')} +\index{enumitem-keys-para (subkey of ``notes'')} +\index{code-before!subkey of ``notes''} +\index{detect-duplicates (subkey of ``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}. This style of list is defined as follows (with, of +course, keys of \pkg{enumitem}): + +|noitemsep , leftmargin = * , align = left , labelsep = 0pt| + +The specification |align = left| in that style 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}). + +\medskip +The key |notes/enumitem-keys| specifies a list of pairs +\textsl{key=value} (following the specifications of \pkg{enumitem}) to +customize that style of list (it uses internally the command |\setlist*| of +\pkg{enumitem}). + + +\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|. + +Initially, the style of list is defined by:\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}). + +\item The key |notes/detect-duplicates| activates the detection of the commands +|\tabularnotes| with the same argument. + +Initial value : |true| +\end{itemize} + +\index{nota@\textbf{Notes in the tabulars}|)} + +\bigskip +For an example of customisation of the tabular notes, see p.~\pageref{ex:notes}. + + +\subsection{Use of \{NiceTabular\} with threeparttable} + +\index{threeparttable@\pkg{threeparttable} (package)} + +If you wish to use an environment |{NiceTabular}|, |{NiceTabular*}| or +|{NiceTabularX}| in an environment |{threeparttable}| of the eponymous package, +you have to patch |{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} + +Nevertheless, the use of \pkg{threeparttable} in conjonction with +\pkg{nicematrix} seems rather point-less because of the functionalities +provided by \pkg{nicematrix} (see the key |caption| in the section +\ref{s:caption}, p.~\pageref{s:caption}). + + +\section{Other features} + +\subsection{The key rounded-corners of \{NiceTabular\}} + +\label{tabular-rounded-corners} +\index{rounded-corners!key of \texttt{\{NiceTabular\}}} +\index{Corners (rounded ---)!for a tabular} + +\colorbox{yellow!50}{\textbf{New 6.18}}\par\nobreak + +\smallskip +The key |rounded-corners| that we will describe now has no direct link with +the key |corners| (which is used to specify ``empty corners'') described in +the part~\ref{corners}, p.~\pageref{corners}. + +\smallskip +The environment |{NiceTabular}| provides a key |rounded-corners| which specify +that the tabular should have rounded corners 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.}). More precisely, that key has two +effects that we describe now. +\begin{itemize} +\item All the commands for coloring the cells, columns and rows (in the +|\CodeBefore| but also directly in the array when the key |colortbl-like| is +used) will respect those rounded corners. + +\item When the key |hvlines| is used, the exterior rules will be drawn with +rounded corners. +\end{itemize} + +\bigskip +\begin{BVerbatim}[baseline=c,boxwidth=9cm] +\begin{NiceTabular} + [hvlines,~emphase#rounded-corners@] + {ccc} +\CodeBefore + \rowcolor{red!15}{1} +\Body +Last name & First name & Profession \\ +Arvy & Jacques & Physicist \\ +Jalon & Amandine & Physicist +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc}[hvlines,rounded-corners] +\CodeBefore + \rowcolor{red!15}{1} +\Body +Last name & First name & Profession \\ +Arvy & Jacques & Physicist \\ +Jalon & Amandine & Physicist +\end{NiceTabular} + + +\subsection{Command \textbackslash ShowCellNames} + +\index{ShowCellNames@\texttt{\textbackslash ShowCellNames} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})} + + +The command |\ShowCellNames|, which may be used in the |\CodeBefore| and in +the |\CodeAfter| displays the name (with the form $i$-$j$) of each cell. When +used in the |\CodeAfter|, that command applies a semi-transparent white +rectangle to fade the array (caution: some \textsc{pdf} readers don't support +transparency). + +\medskip +\begin{BVerbatim}[baseline=c,boxwidth=10.6cm] +\begin{NiceTabular}{ccc}[hvlines,cell-space-limits=3pt] + \Block{2-2}{} & & test \\ + & & blabla \\ + & some text & nothing +~emphase#\CodeAfter \ShowCellNames@ +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc}[hvlines,cell-space-limits=3pt] + \Block{2-2}{} & & test \\ + & & blabla \\ + & some text & nothing +\CodeAfter \ShowCellNames +\end{NiceTabular} + + +\subsection{Use of the column type S of siunitx} + +\index{S (the columns S of \pkg{siunitx})} +\index{siunitx@\pkg{siunitx} (package)} + +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 = 11cm] +$\begin{pNiceArray}{~emphase#S@cW{c}{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}{ScW{c}{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{Default column type in \{NiceMatrix\}} + +\label{columns-width} +\index{columns-type (key of \texttt{\{NiceMatrix\}}, etc.)} + +The environments without preamble (|{NiceMatrix}|, |{pNiceMatrix}|, +|{bNiceMatrix}|, etc.) and the commande |\pAutoNiceMatrix| (and its variants) +provide an option |columns-type| to specify the type of column which will be +used (the initial value is, of course, |c|). + +The keys |l| and |r| are shortcuts for |columns-type=l| and |columns-type=r|. + + +\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}$ + +\medskip +The key |columns-type| is available in |\NiceMatrixOptions| but with the +prefix |matrix|, which means that its name is, within |\NiceMatrixOptions| : +|matrix/columns-type|. + +\subsection{The command \textbackslash rotate} + +\label{rotate} +\index{rotate@\texttt{\textbackslash 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 +\index{first-row|textit} +\index{last-row|textit} +\index{code-for-first-row|textit} +\index{code-for-last-row|textit} +\index{last-col|textit} +\index{code-for-last-col|textit} + +\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} +\index{small (key for an environment)} +\index{smallmatrix@\texttt{\{smallmatrix\}} (environment of \pkg{amsmath})} + + +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} + +\medskip +When the key |small| is in force, some functionalities of \pkg{nicematrix} are +no longer available: for example, it's no longer possible to put vertical +delimiters directly in the preamble of an environment with preamble (cf. +section \ref{delimiters-in-preamble}, p.~\pageref{delimiters-in-preamble}). + + +\subsection{The counters iRow and jCol} + +\label{iRow} +\index{iRow (LaTeX counter)} +\index{jCol (LaTeX counter)} + +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 +\indexcommand{AutoNiceMatrix} +\indexcommand{pAutoNiceMatrix} +\indexcommand{bAutoNiceMatrix} +\indexcommand{vAutoNiceMatrix} +\indexcommand{VAutoNiceMatrix} +\indexcommand{BAutoNiceMatrix} +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 key light-syntax} + +\label{light-syntax} +\index{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 +\index{end-of-row (to be used with light-syntax)} +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} + +\index{delimiters!---/color for an environment} +\index{color!for the delimiters of the matrices} +\index{Colour!of the delimiters of the matrices} + + +For the environments 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 color also applies to the delimiters drawn by the command |\SubMatrix| +(cf.~p.~\pageref{sub-matrix}) and for the delimiters directly specified in the +preamble of the environments with preamble +(cf.~p.~\pageref{delimiters-in-preamble}). + +\subsection{The environment \{NiceArrayWithDelims\}} + +\label{NiceArrayWithDelims} +\index{NiceArrayWithDelims@\texttt{\{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}$ + +\subsection{The command \textbackslash OnlyMainNiceMatrix} + +\indexcommand{OnlyMainNiceMatrix} + +The command |\OnlyMainNiceMatrix| executes its argument only when it is in the +main part of the array, that is to say when it is not in one of the exterior +rows. If it is used outside an environment of \pkg{nicematrix}, that command is +no-op. + +For an example of utilisation, see \url{tex.stackexchange.com/questions/488566} + +\section{Use of Tikz with nicematrix} + +\label{name}\label{PGF-nodes} +\index{tikza@TikZ (utilisation with \pkg{nicematrix})} +\index{node@\textbf{Nodes of PGF/Tikz}|(} + +\subsection{The nodes corresponding to the contents of the cells} + +The package \pkg{nicematrix} creates a PGF/Tikz node\footnote{We recall that Tikz +is a layer over PGF. The extension \pkg{nicematrix} loads PGF but does not +load Tikz. We speak of PGF/Tikz nodes to emphase the fact that the PGF nodes +created by \pkg{nicematrix} may be used with PGF but also with Tikz. The final +user will probably prefer to use Tikz rather than PGF.} 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 +\index{name!key for an environment} +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}$ + +\medskip +The nodes of the last column (excepted the potential ``last column'' specified +by |last-col|\footnote{For the exterior columns, cf. part~\ref{exterior}, +p.~\pageref{exterior}.}) may also be indicated by $i$-|last|. Similarly, the +nodes of the last row may be indicated by |last|-$j$. + +\bigskip +In the following example, we have underlined all the nodes of the matrix. + +\[ +\NiceMatrixOptions + { + pgf-node-code = + { + \pgfsetfillcolor{red!15}% + \pgfusepathqfill + } + } +\begin{pNiceMatrix} +a & a + b & a + b + c \\ +a & a & a + b \\ +a & a & a +\end{pNiceMatrix}\] + + +\bigskip +\colorbox{yellow!50}{\textbf{New 6.17}}\enskip Since those nodes are PGF +nodes, one won't be surprised to learn that they are drawn by using a specific +PGF style. That style is called |nicematrix/cell-node| and its definition in +the source file |nicematrix.sty| is as follows: + +\begin{Verbatim} +\pgfset + { + ~emphase#nicematrix / cell-node@ /.style = + { + inner sep = 0 pt , + minimum width = 0 pt + } + } +\end{Verbatim} + +The final user may modify that style by changing the values of the keys |text/rotate|, +|inner xsep|, |inner ysep|, |inner sep|, |outer xsep|, |outer ysep|, |outer sep|, +|minimum width|, |minimum height| and |minimum size|. + +\medskip +For an example of utilisation, see part~\ref{triangular}, p.~\pageref{triangular}. + + +\subsubsection{The key pgf-node-code} + +\index{pgf-node-code} + +\colorbox{yellow!50}{\textbf{New 6.17}}\enskip \textbf{For the experienced +users}, \pkg{nicematrix} provides the key |pgf-node-code| which corresponds to +some PGF node that will be executed at the creation, by PGF, of the nodes +corresponding to the cells of the array. More pricisely, the value given to +the key |pgf-node-code| will be passed in the fifth argument of the command +|\pgfnode|. That value should contain at least an instruction such as +|\pgfusepath|, |\pgfusepathqstroke|, |\pgfusepathqfill|, etc. + +\subsubsection{The columns V of varwidth} + +\label{node-V} +\index{V (the columns V of \pkg{varwidth})} +\index{varwidth@\pkg{varwidth} (package)} + +When the extension \pkg{varwidth} is loaded, the columns of the type |V| +defined by \pkg{varwidth} are supported by \pkg{nicematrix}. It may be +interessant to notice that, for a cell of a column of type |V|, the PGF/Tikz +node created by \pkg{nicematrix} for the content of that cell has a width +adjusted to the content of the cell. This is in contrast to the case of the +columns of type |p|, |m| or |b| for which the nodes have always a width equal +to the width of the column. In the following example, the command |\lipsum| is +provided by the eponymous package. + +\begin{Verbatim} +\begin{NiceTabular}{V{10cm}} +\bfseries \large +Titre \\ +\lipsum[1][1-4] +\CodeAfter + \tikz \draw [rounded corners] (1-1) -| (last-|2) -- (last-|1) |- (1-1) ; +\end{NiceTabular} +\end{Verbatim} + + +\begin{center} +\begin{NiceTabular}{V{10cm}} +\bfseries \large +Titre \\ +\lipsum[1][1-4] +\CodeAfter + \tikz \draw [rounded corners] (1-1) -| (last-|2) -- (last-|1) |- (1-1) ; +\end{NiceTabular} +\end{center} + +We have used the nodes corresponding to the position of the potential rules, +which are described below (cf. p.~\pageref{nodes-i}). + + +\subsection[The medium nodes and the large nodes]{The ``medium nodes'' and the ``large nodes''} + +\index{create-medium-nodes} +\index{create-large-nodes} +\index{create-extra-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 +\index{left-margin} +\index{right-margin} +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 +\index{extra-left-margin} +\index{extra-right-margin} +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 + +\index{create-cell-nodes (key of \texttt{\textbackslash CodeBefore})} +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). + +\bigskip +Here is an example which uses these nodes in the |\CodeAfter|. + +\begin{center} +\fvset{commandchars=\~\#\+} +\begin{Verbatim} +\begin{NiceArray}{c@{\;}c@{\;}c@{\;}c@{\;}c}[create-medium-nodes] + u_1 &-& u_0 &=& r \\ + u_2 &-& u_1 &=& r \\ + u_3 &-& u_2 &=& r \\ + u_4 &-& u_3 &=& r \\ + \phantom{u_5} & & \phantom{u_4} &\smash{\vdots} & \\ + u_n &-& u_{n-1} &=& r \\[3pt] + \hline + u_n &-& u_0 &=& nr \\ +\CodeAfter + \tikz[very thick, red, opacity=0.4, name suffix = -medium] + \draw (1-1.north west) -- (2-3.south east) + (2-1.north west) -- (3-3.south east) + (3-1.north west) -- (4-3.south east) + (4-1.north west) -- (5-3.south east) + (5-1.north west) -- (6-3.south east) ; +\end{NiceArray} +\end{Verbatim} +\end{center} + +\[\begin{NiceArray}{c@{\;}c@{\;}c@{\;}c@{\;}c}[create-medium-nodes] + u_1 &-& u_0 &=& r \\ + u_2 &-& u_1 &=& r \\ + u_3 &-& u_2 &=& r \\ + u_4 &-& u_3 &=& r \\ + \phantom{u_5} & & \phantom{u_4} &\smash{\vdots} & \\ + u_n &-& u_{n-1} &=& r \\[3pt] + \hline + u_n &-& u_0 &=& nr \\ + \CodeAfter + \tikz[very thick, red, opacity=0.4, name suffix = -medium] + \draw (1-1.north west) -- (2-3.south east) + (2-1.north west) --(3-3.south east) + (3-1.north west) -- (4-3.south east) + (4-1.north west) -- (5-3.south east) + (5-1.north west) -- (6-3.south east) ; +\end{NiceArray}\] + + + +\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} +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})} +\index{name!key of \texttt{\textbackslash SubMatrix}} + + +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}\] + +\index{node@\textbf{Nodes of PGF/Tikz}|)} + +\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_before_tl|. + +\index{crossbox@\texttt{\textbackslash crossbox} (defined in an example)|textit} + +\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_before_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_before_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] +\CodeBefore + \arraycolor{gray!10} +\Body +merlan & requin & cabillaud \\ +baleine & ~emphase#\crossbox[red]@ & morue \\ +mante & raie & poule +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{ccc}[hvlines] +\CodeBefore + \arraycolor{gray!10} +\Body +merlan & requin & cabillaud \\ +baleine & \crossbox[red] & morue \\ +mante & raie & poule +\end{NiceTabular} + + + +\section{Technical remarks} + +First remark: the package \pkg{underscore} must be loaded before +\pkg{nicematrix}. If it is loaded after, an error will be raised. + +\subsection{Diagonal lines} + +\label{parallelization} +\index{parallelize-diags} +\index{Ddots@\texttt{\textbackslash Ddots}} +\index{Iddots@\texttt{\textbackslash Iddots}} + +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]{The ``empty'' cells} + +\label{empty-cells} +An instruction like |\Ldots|, |\Cdots|, etc. tries to determine the first +non-empty cell on both sides. When the key |corners| is used +(cf.~p.~\pageref{corners}), \pkg{nicematrix} computes corners consisting of +empty cells. 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 For the columns of type |p|, |m|, |b|, |V|\footnote{The columns of type +|V| are provided by \pkg{varwidth}: cf.~p.~\pageref{varwidth}.} and +|X|\footnote{See p.~\pageref{X-columns}}, the cell is empty if (and only if) +its content in the TeX code is empty (there is only spaces between the +ampersands |&|). + +\medskip +\item For the columns of type |c|, |l|, |r| and |w{...}{...}|, the cell is +empty if (and only if) its TeX output has a width equal to zero. + +\medskip +\item \indexcommand{NotEmpty} +A cell containing the command |\NotEmpty| is not empty (and a PGF/Tikz +node is created in that cell). + +\medskip +\item A cell with only 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}. +\end{itemize} + + +\subsection{The option exterior-arraycolsep} + +\index{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 +\pkg{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} + +\index{Incompatibilities} + +The package \pkg{nicematrix} is not compatible with the class \cls{ieeeaccess} +(because that class is not compatible with PGF/Tikz).\footnote{See + \url{https://tex.stackexchange.com/questions/528975/error-loading-tikz-in-ieeeaccess-class}} + +\bigskip +In order to use \pkg{nicematrix} with the class \cls{aastex631} +(of the \emph{American Astronomical Society}), you have to +add the following lines in the preamble of your document : + +\begin{Verbatim} +\BeforeBegin{NiceTabular}{\let\begin\BeginEnvironment\let\end\EndEnvironment} +\BeforeBegin{NiceArray}{\let\begin\BeginEnvironment} +\BeforeBegin{NiceMatrix}{\let\begin\BeginEnvironment} +\end{Verbatim} + +\bigskip +In order to use \pkg{nicematrix} with the class \cls{sn-jnl} (of +\emph{Springer Nature}), \pkg{pgf} must +be loaded before the |\documentclass| with |\RequirePackage|: + +\begin{Verbatim} +\RequirePackage{pgf} +\documentclass{sn-jnl} +\end{Verbatim} + +\bigskip +The package \pkg{nicematrix} is not fully compatible with the packages and classes +of \LuaTeX-ja: the detection of the empty corners (cf. % p.~\pageref{corners}) +may be wrong in some circonstances. + +\bigskip +The package \pkg{nicematrix} is not fully compatible with the package +\pkg{arydshln} (because this package redefines many internals of \pkg{array}). +By any means, in the context of \pkg{nicematrix}, it's recommended to draw +dashed rules with the tools provided by \pkg{nicematrix}, by creating a +customized line style with |custom-line|: cf.~p.~\pageref{custom-line}. + +\bigskip +The columns |d| of \pkg{dcolumn} are not supported (but it's possible to use +the colums |S| of \pkg{siunitx}). + +\section{Examples} + +\subsection[{Utilisation of the key 'tikz' of the command \textbackslash +Block}]{Utilisation of the key ``tikz'' of the command \textbackslash Block} +\label{tikz-key-examples} + +\index{tikzz@tikz!key of \texttt{\textbackslash Block}|textit} + +The key |tikz| of the command |\Block| is available only when Tikz is +loaded.\footnote{By default, \pkg{nicematrix} only loads \textsc{pgf}, which is +a sub-layer of Tikz.} + +For the following example, we also need the Tikz library |patterns|. + +\begin{Verbatim} +\usetikzlibrary{patterns} +\end{Verbatim} + + +\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} + +\bigskip +In the following example, we use the key |tikz| to hatch a row of the tabular. +Remark that you use the key |transparent| of the command |\Block| in order to +have the rules drawn in the block.\footnote{By default, the rules are not +drawn in the blocks created by the command |\Block|: cf.~section~\ref{rules} +p.~\pageref{rules}} + +\index{transparent (key of \texttt{\textbackslash Block})|textit} +\index{columncolor@\texttt{\textbackslash columncolor}!command of + \texttt{\textbackslash CodeBefore}|textit} + + +\begin{Verbatim} +\begin{NiceTabular}{ccc}[hvlines] +\CodeBefore + \columncolor[RGB]{169,208,142}{2} +\Body +one & two & three \\ +\Block[~emphase#transparent, tikz={pattern = north west lines, pattern color = gray}@]{1-*}{} +four & five & six \\ +seven & eight & nine +\end{Verbatim} + +\begin{center} +\begin{NiceTabular}{ccc}[hvlines] +\CodeBefore + \columncolor[RGB]{169,208,142}{2} +\Body +one & two & three \\ +\Block[transparent, tikz={pattern = north west lines, pattern color = gray}]{1-*}{} +four & five & six \\ +seven & eight & nine +\end{NiceTabular} +\end{center} + +\subsection{Use with tcolorbox} + +\label{tcolorbox} +\index{tcolorbox@\pkg{tcolorbox} (package)|textit} + +Here is an example of use of |{NiceTabular}| within a command |\tcbox| of +\pkg{tcolorbox}. We have used the key |hvlines-except-borders| in order all +the rules excepted on the borders (which are, of course, added by \pkg{tcolorbox}) + +\medskip +\begin{BVerbatim} +\tcbset + { + colframe = blue!50!black , + colback = white , + colupper = red!50!black , + fonttitle = \bfseries , + nobeforeafter , + center title + } + +\tcbox + [ + left = 0mm , + right = 0mm , + top = 0mm , + bottom = 0mm , + boxsep = 0mm , + toptitle = 0.5mm , + bottomtitle = 0.5mm , + title = My table + ] + { + \renewcommand{\arraystretch}{1.2}% <-- the % is mandatory here + \begin{NiceTabular}{rcl}[~emphase#hvlines-except-borders@,rules/color=blue!50!black] + \CodeBefore + \rowcolor{red!15}{1} + \Body + One & Two & Three \\ + Men & Mice & Lions \\ + Upper & Middle & Lower + \end{NiceTabular} + } +\end{BVerbatim} + + +\index{hvlines-except-borders|textit} +\index{rules (key for an environment)|textit} +\index{rowcolor@\texttt{\textbackslash rowcolor}!command of \texttt{\textbackslash CodeBefore}|textit} + +\medskip +\begin{center} +\tcbset + { + colframe = blue!50!black , + colback = white , + colupper = red!50!black , + fonttitle = \bfseries , + nobeforeafter , + center title + } + +\tcbox + [ + left = 0mm , + right = 0mm , + top = 0mm , + bottom = 0mm , + boxsep = 0mm , + toptitle = 0.5mm , + bottomtitle = 0.5mm , + title = My table + ] + { + \renewcommand{\arraystretch}{1.2}\begin{NiceTabular}{rcl}[hvlines-except-borders,rules/color=blue!50!black] + \CodeBefore + \rowcolor{red!15}{1} + \Body + One & Two & Three \\ + Men & Mice & Lions \\ + Upper & Middle & Lower + \end{NiceTabular} + } +\end{center} + + + +\vspace{1cm} +That example shows the use of \pkg{nicematrix} in conjunction with +\pkg{tcolorbox}. If one wishes a tabular with an exterior frame with rounded +corners, it's not necessary to use \pkg{tcolorbox}: it's possible to use the +command |\Block| with the key |rounded-corners|. + +\medskip +\begin{BVerbatim}[baseline=c,boxwidth=10.5cm] +\begin{NiceTabular}{rcl}[hvlines-except-borders] +\Block[draw,transparent,~emphase#rounded-corners@]{*-*}{} + One & Two & Three \\ + Men & Mice & Lions \\ + Upper & Middle & Lower +\end{NiceTabular} +\end{BVerbatim} +\begin{NiceTabular}{rcl}[hvlines-except-borders] +\Block[draw,transparent,rounded-corners]{*-*}{} + One & Two & Three \\ + Men & Mice & Lions \\ + Upper & Middle & Lower +\end{NiceTabular} + +\medskip +We have used the key |transparent| to have the rules specified by +|hvlines-except-borders| drawn in the blocks (by default, the rules are not +drawn in the blocks). + +\subsection{Notes in the tabulars} + +\index{nota@\textbf{Notes in the tabulars}|textit} +\index{tabularnote@\texttt{\textbackslash tabularnote}|textit} +\index{notes (key to customize the notes of a\newline tabular)|textit} +\index{style (subkey of ``notes'')|textit} +\index{enumitem-keys (subkey of ``notes'')|textit} +\index{enumitem@\pkg{enumitem} (package required to use\newline \texttt{\textbackslash tabularnote})|textit} + + +\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} + +\index{dotted@\textbf{Dotted lines}|textit} + +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 +\index{Ddots@\texttt{\textbackslash Ddots}|textit} + +\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 + +\index{last-col|textit} +\index{code-for-last-col|textit} + +\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. + +\index{line-style (key for the dotted rules)|textit} + +\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} + +\index{code-for-first-row|textit} +\index{code-for-last-col|textit} + + +\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.\footnote{In this document, the Tikz library \pkg{arrows.meta} +has been loaded, which impacts the shape of the arrow tips.} + +\begin{Verbatim} +\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{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{Dashed rules} +\label{dashed} +\index{tikzz@tikz!key of ``borders'' de \texttt{\textbackslash Block}|textit} + +In the following example, we use the command |\Block| to draw dashed rules. +For that example, Tikz should be loaded (by |\usepackage{tikz}|). + + +\begin{Verbatim} +\begin{pNiceMatrix} +~emphase#\Block[borders={bottom,right,tikz=dashed}]{2-2}{}@ +1 & 2 & 0 & 0 & 0 & 0 \\ +4 & 5 & 0 & 0 & 0 & 0 \\ +0 & 0 & ~emphase#\Block[borders={bottom,top,right,left,tikz=dashed}]{2-2}{}@ + 7 & 1 & 0 & 0 \\ +0 & 0 & -1 & 2 & 0 & 0 \\ +0 & 0 & 0 & 0 & ~emphase#\Block[borders={left,top,tikz=dashed}]{2-2}{}@ + 3 & 4 \\ +0 & 0 & 0 & 0 & 1 & 4 +\end{pNiceMatrix} +\end{Verbatim} + + +\[\begin{pNiceMatrix} +\Block[borders={bottom,right,tikz=dashed}]{2-2}{} +1 & 2 & 0 & 0 & 0 & 0 \\ +4 & 5 & 0 & 0 & 0 & 0 \\ +0 & 0 & \Block[borders={bottom,top,right,left,tikz=dashed}]{2-2}{} + 7 & 1 & 0 & 0 \\ +0 & 0 & -1 & 2 & 0 & 0 \\ +0 & 0 & 0 & 0 & \Block[borders={left,top,tikz=dashed}]{2-2}{} + 3 & 4 \\ +0 & 0 & 0 & 0 & 1 & 4 +\end{pNiceMatrix}\] + + +\subsection{Stacks of matrices} + +\index{NiceMatrixBlock@\texttt{\{NiceMatrixBlock\}}|textit} + +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 +\index{auto-columns-width!(key of \texttt{\{NiceMatrixBlock\}})|textit} +\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 +\index{max-width (subkey of ``delimiters'')} +\index{delimiters!---/max-width} +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 +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})|textit} + +\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} + +\bigskip +In this tabular, the instructions |\SubMatrix| are executed after the +composition of the tabular and, thus, the vertical rules are drawn without +adding space between the columns. + + +\bigskip +In fact, it's possible, with the key |vlines-in-sub-matrix|, to choice a +letter in the preamble of the array to specify vertical rules which will be +drawn in the |\SubMatrix| only (by adding space between the columns). + +\index{vlines-in-sub-matrix} +\medskip +\begin{Verbatim} +\setlength{\extrarowheight}{1mm} +\[\begin{NiceArray} + [ + ~emphase#vlines-in-sub-matrix=I@, + last-col, + code-for-last-col = \scriptstyle \color{blue} + ] + {rrrrIr} +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 + \SubMatrix({1-1}{4-5}) + \SubMatrix({5-1}{8-5}) + \SubMatrix({9-1}{11-5}) + \SubMatrix({12-1}{13-5}) +\end{NiceArray}\] +\end{Verbatim} + + +\medskip +\begin{scope} +\setlength{\extrarowheight}{1mm} +\[\begin{NiceArray} + [ + vlines-in-sub-matrix=I, + last-col, + code-for-last-col = \scriptstyle \color{blue} + ] + {rrrrIr} +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 + \SubMatrix({1-1}{4-5}) + \SubMatrix({5-1}{8-5}) + \SubMatrix({9-1}{11-5}) + \SubMatrix({12-1}{13-5}) +\end{NiceArray}\] +\end{scope} + + + + + +\subsection{How to highlight cells of a matrix} + + +\label{highlight} +\index{draw (key of \texttt{\textbackslash Block})|textit} + +\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 ``\verb+|+'' 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). + +\index{colortbl-like|textit} +\index{rowcolor@\texttt{\textbackslash rowcolor}!command in tabular|textit} + + +\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. + +\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 +\index{highlight (TikZ style defined in\newline an example)|textit} +\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} +\index{create-cell-nodes (key of \texttt{\textbackslash CodeBefore})|textit} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}|textit} + +\[\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, margin = 2pt] +\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, margin = 2pt] +\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''. + +\index{create-medium-nodes|textit} +\index{create-cell-nodes (key of \texttt{\textbackslash CodeBefore})|textit} + + +\begin{Verbatim} +\[\begin{pNiceArray}{ccc}[last-col, margin = 2pt, 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, margin = 2pt, 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} + +\label{submatrix-in-codebefore} + +\index{SubMatrix@\texttt{\textbackslash SubMatrix} (command of +\texttt{\textbackslash CodeAfter}\newline and +\texttt{\textbackslash CodeBefore})|textit} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}|textit} +\index{CodeAfter@\texttt{\textbackslash CodeAfter}|textit} +\index{create-cell-nodes (key of \texttt{\textbackslash CodeBefore})|textit} + + +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-last}) + \SubMatrix({7-2}{last-6}) + \SubMatrix({7-7}{last-last}) + \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-last}) + \SubMatrix({7-2}{last-6}) + \SubMatrix({7-7}{last-last}) + \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} + + + +\subsection{A triangular tabular} + +\label{triangular} + +\index{pgf-node-code|textit} +\index{Corners (the empty ---)|textit} +\index{chessboardcolors@\texttt{\textbackslash chessboardcolors}!(commande + du \texttt{\textbackslash CodeBefore})|textit} +\index{CodeBefore@\texttt{\textbackslash CodeBefore}...\texttt{\textbackslash Body}|textit} + +In the following example, we use the style PGF/TikZ |nicematrix/cell-node| +to rotate the contents of the cells (and, then, we compensate that rotation by +a rotation of the whole tabular with the command |\adjustbox| of the eponymous +package, which must be loaded previously). + + +\medskip +\begin{Verbatim} +\pgfset + { + ~emphase#nicematrix/cell-node@/.append style = + { text/rotate = 45, minimum size = 6 mm } + } + +\setlength{\tabcolsep}{0pt} + +~emphase#\adjustbox@{rotate = -45, set depth = 6mm + 1.414 \arrayrulewidth} + {\begin{NiceTabular} [ hvlines, corners=SE, baseline = line-9 ] { cccccccc } + \CodeBefore + \chessboardcolors{red!15}{blue!15} + \Body + 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ + 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ + 1 & 3 & 6 & 10 & 15 & 21 \\ + 1 & 4 & 10 & 20 & 35 \\ + 1 & 5 & 15 & 35 \\ + 1 & 6 & 21 \\ + 1 & 7 \\ + 1 + \end{NiceTabular}} +\end{Verbatim} + + +\begin{center} +\pgfset + { + nicematrix/cell-node/.append style = + { text/rotate = 45, minimum size = 6 mm } + }% +\setlength{\tabcolsep}{0pt}% +\adjustbox{rotate = -45, set depth = 6mm + 1.414 \arrayrulewidth} + {\begin{NiceTabular} [ hvlines, corners=SE, baseline = line-9 ] { cccccccc } + \CodeBefore + \chessboardcolors{red!15}{blue!15} + \Body + 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ + 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ + 1 & 3 & 6 & 10 & 15 & 21 \\ + 1 & 4 & 10 & 20 & 35 \\ + 1 & 5 & 15 & 35 \\ + 1 & 6 & 21 \\ + 1 & 7 \\ + 1 + \end{NiceTabular}} +\end{center} + + +\newpage +\vspace{1cm} +\section{History} + +The successive versions of the file |nicematrix.sty| provided by TeXLive are available on the +\textsc{svn} server of TeXLive:\par\nobreak + +\smallskip +{ +\small +\nolinkurl{https:www.tug.org/svn/texlive/trunk/Master/texmf-dist/tex/latex/nicematrix/nicematrix.sty} +} + +\subsection*{Changes between version 6.18 and 6.19} + +The command |\tabularnote| now supports an optional argument (between square +brackets) to change the symbol of the reference of the note. + +\subsection*{Changes between version 6.17 and 6.18} + +New key |opacity| in the commands to color cells, rows and columns. + +New key |rounded-corners| for a whole tabular. + + +\subsection*{Changes between version 6.16 and 6.17} + +New PGF/Tikz style |nicematrix/cell-node|. + +New key |pgf-node-code| + +\subsection*{Changes between version 6.15 and 6.16} + +It's now possible to put any LaTeX extensible delimiter (|\lgroup|, |\langle|, +etc.) in the preamble of an environment with preamble (such as |{NiceArray}|) +by prefixing them by |\left| and |\right|. + +New key |code| for the command |\SubMatrix| in the |\CodeAfter|. + +\subsection*{Changes between version 6.14 and 6.15} + +New key |transparent| for the command |\Block| (with that key, the rules are +drawn within the block). + +\subsection*{Changes between version 6.13 and 6.14} + +New keys for the command |\Block| for the vertical position of the content of +that block. + +\subsection*{Changes between version 6.12 and 6.13} + +New environment |{TabularNote}| in |{NiceTabular}| with the same semantic as +the key |tabularnote| (for legibility). + +The command |\Hline| nows accepts options (between square brackets). + +\subsection*{Changes between version 6.11 and 6.12} + +New keys |caption|, |short-caption| and |label| in the environment +|{NiceTabular}|. + +In |{NiceTabular}|, a caption specified by the key |caption| is wrapped to the +width of the tabular. + +Correction of a bug: it's now possible to use |\OverBrace| and |\UnderBrace| +with \pkg{unicode-math} (with XeLaTeX or LuaLaTeX). + +\subsection*{Changes between version 6.10 and 6.11} + +New key |matrix/columns-type| to specify the type of columns of the matrices. + +New key |ccommand| in |custom-line| and new command |\cdottedline|. + +\subsection*{Changes between version 6.9 and 6.10} + +New keys |xdots/shorten-start| and |xdots/shorten-end|. + +It's possible to use |\line| in the |\CodeAfter| between two blocks (and not +only two cells). + +\subsection*{Changes between version 6.8 and 6.9} + +New keys |xdots/radius| and |xdots/inter| for customisation of the continuous +dotted lines. + +New command |\ShowCellNames| available in the |\CodeBefore| and in the |\CodeAfter|. + +\subsection*{Changes between version 6.7 and 6.8} + +In the notes of a tabular (with the command |\tabularnote|), the duplicates +are now detected: when several commands |\tabularnote| are used with the same +argument, only one note is created at the end of the tabular (but all the +labels are present, of course). + +\subsection*{Changes between version 6.6 and 6.7} + +Key |color| for |\OverBrace| and |\UnderBrace| in the |\CodeAfter| + +Key |tikz| in the key |borders| of a command |\Block| + +\subsection*{Changes between version 6.5 and 6.6} + +Keys |tikz| and |width| in |custom-line|. + +\subsection*{Changes between versions 6.4 and 6.5} + +Key |custom-line| in |\NiceMatrixOptions|. + +Key |respect-arraystretch|. + +\subsection*{Changes between versions 6.3 and 6.4} + +New commands |\UnderBrace| and |\OverBrace| in the |\CodeAfter|. + +Correction of a bug of the key |baseline| (cf. question 623258 on TeX StackExchange). + +Correction of a bug with the columns |V| of \pkg{varwidth}. + +Correction of a bug: the use of |\hdottedline| and |:| in the preamble of the +array (of another letter specified by |letter-for-dotted-lines|) was +incompatible with the key |xdots/line-style|. + +\subsection*{Changes between versions 6.2 and 6.3} + +Keys |nb-rows|, |rowcolor| and |bold| for the command |\RowStyle| + +Key |name| for the command |\Block|. + +Support for the columns |V| of \pkg{varwidth}. + +\subsection*{Changes between versions 6.1 and 6.2} + +Better compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}. + +Key |vlines-in-sub-matrix|. + +\subsection*{Changes between versions 6.0 and 6.1} + +Better computation of the widths of the |X| columns. + +Key |\color| for the command |\RowStyle|. + +\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 5.18 and 5.19} + +New key |tikz| for the command |\Block|. + +\subsection*{Changes between versions 5.17 and 5.18} + +New command |\RowStyle| + +\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.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.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.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.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.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.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.9 and 5.10} + +New command |\SubMatrix| available in the |\CodeAfter|. + +It's possible to provide options (between brackets) to the keyword |\CodeAfter|. + +\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.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.6 and 5.7} + +New key |delimiters-color| + +Keys |fill|, |draw| and |line-width| for the command |\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.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.3 and 5.4} + +Key |tabularnote|. + +Different behaviour for the mono-column blocks. + +\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.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.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 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 4.3 and 4.4} + +New key |hvlines-except-corners| (now deprecated). + +\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.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.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 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 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.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.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 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.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.10 and 3.11} + +Correction of a bug linked to |first-row| and |last-row|. + +\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 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.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.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.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.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.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.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. + +\subsection*{Changes between version 3.1 and 3.2 (and 3.2a)} + +Option |small|. + +\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|. + +The vertical rules in the matrices (drawn by ``\verb+|+'') 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 2.3 and 3.0} + +Modification of |\Hdotsfor|. Now |\Hdotsfor| erases the |\vlines| (of ``\verb+|+'') +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 2.2.1 and 2.3} + +Compatibility with the column type |S| of \pkg{siunitx}. + +Option |hlines|. + +\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.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 +``\verb+|+'' and the specifier ``|:|'' of \pkg{arydshln}). + +\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.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.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 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.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 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 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.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 versions 1.1 and 1.2} + +New environment |{NiceArray}| with column types |L|, |C| and |R|. + +\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. + + + +\cleardoublepage + +\phantomsection +\addcontentsline{toc}{section}{Index} + +\printindex + + +\newpage +\tableofcontents + +\end{document} + +% \endinput +% Local Variables: +% TeX-fold-mode: t +% TeX-fold-preserve-comments: nil +% fill-column: 80 +% End: + + -- cgit v1.2.3