diff options
Diffstat (limited to 'macros/latex/contrib/nicematrix/nicematrix-code.dtx')
-rw-r--r-- | macros/latex/contrib/nicematrix/nicematrix-code.dtx | 34698 |
1 files changed, 17349 insertions, 17349 deletions
diff --git a/macros/latex/contrib/nicematrix/nicematrix-code.dtx b/macros/latex/contrib/nicematrix/nicematrix-code.dtx index 6503a47298..79d804eb1c 100644 --- a/macros/latex/contrib/nicematrix/nicematrix-code.dtx +++ b/macros/latex/contrib/nicematrix/nicematrix-code.dtx @@ -1,17349 +1,17349 @@ -% \iffalse meta-comment -% -% This file should be compiled with $xelatex$. -% -% Copyright (C) 2018-2024 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.27} -\def\myfiledate{2024/02/13} -% -% -%<*batchfile> -\begingroup -\input l3docstrip.tex -\keepsilent -\usedir{tex/latex/nicematrix} -\preamble - - -Copyright (C) 2018-2024 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 -%</batchfile> -% -%<*driver> -\documentclass[dvipsnames]{l3doc}% dvipsnames is for xcolor (loaded by Tikz) -\VerbatimFootnotes - -\usepackage[luatex]{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{formatcom=\color{gray}} - -\usepackage{upquote} - -\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} -%</driver> -% \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 e } -\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, by default, 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 \g_@@_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 generate usually an error but only a -% warning on Overleaf. The argument is given by curryfication. -% \begin{macrocode} -\cs_new_protected:Npn \@@_error_or_warning:n - { \bool_if:NTF \g_@@_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_new:N \g_@@_messages_for_Overleaf_bool -\bool_gset:Nn \g_@@_messages_for_Overleaf_bool - { - \str_if_eq_p:on \c_sys_jobname_str { _region_ } % for Emacs - || \str_if_eq_p:on \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 \g_@@_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{Collecting options} -% -% The following technic allows to create user commands with the ability to put -% an arbitrary number of |[|\textsl{list of (key=val)}|]| after the name of the -% command. -% -% \medskip -% \emph{Exemple} :\par\nobreak -% -% |\@@_collect_options:n { \F } [x=a,y=b] [z=c,t=d] { arg }| -% -% will be transformed in :\quad |\F{x=a,y=b,z=c,t=d}{arg}| -% -% \smallskip -% Therefore, by writing : |\def\G{\@@_collect_options:n{\F}}|, -% -% the command |\G| takes in an arbitrary number of optional arguments between -% square brackets. -% -% Be careful: that command is \emph{not} ``fully expandable'' (because of -% |\peek_meaning:NTF|). -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_collect_options:n #1 - { - \peek_meaning:NTF [ - { \@@_collect_options:nw { #1 } } - { #1 { } } - } -% \end{macrocode} -% -% \bigskip -% We use |\NewDocumentCommand| in order to be able to allow nested brackets -% within the argument between |[| and |]|. -% \begin{macrocode} -\NewDocumentCommand \@@_collect_options:nw { m r[] } - { \@@_collect_options:nn { #1 } { #2 } } - -\cs_new_protected:Npn \@@_collect_options:nn #1 #2 - { - \peek_meaning:NTF [ - { \@@_collect_options:nnw { #1 } { #2 } } - { #1 { #2 } } - } - -\cs_new_protected:Npn \@@_collect_options:nnw #1#2[#3] - { \@@_collect_options:nn { #1 } { #2 , #3 } } -% \end{macrocode} -% -% -% \bigskip -% \section{Technical definitions} -% -% -% The following constants are defined only for efficiency in the tests. -% \begin{macrocode} -\tl_const:Nn \c_@@_b_tl { b } -\tl_const:Nn \c_@@_c_tl { c } -\tl_const:Nn \c_@@_l_tl { l } -\tl_const:Nn \c_@@_r_tl { r } -\tl_const:Nn \c_@@_all_tl { all } -\tl_const:Nn \c_@@_dot_tl { . } -\tl_const:Nn \c_@@_default_tl { default } -\tl_const:Nn \c_@@_star_tl { * } -\str_const:Nn \c_@@_r_str { r } -\str_const:Nn \c_@@_c_str { c } -\str_const:Nn \c_@@_l_str { l } -\str_const:Nn \c_@@_R_str { R } -\str_const:Nn \c_@@_C_str { C } -\str_const:Nn \c_@@_L_str { L } -\str_const:Nn \c_@@_j_str { j } -\str_const:Nn \c_@@_si_str { si } -% \end{macrocode} -% -% The following token list will be used for definitions of user commands (with -% |\NewDocumentCommand|) with an embellishment using an \emph{underscore} (there -% may be problems because of the catcode of the underscore). -% \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 \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 May 2023, the current -% version \cls{revtex4-2} is 4.2f (compatible with \pkg{booktabs}). -% -% \begin{macrocode} -\IfClassLoadedTF { revtex4-1 } - { \bool_const:Nn \c_@@_revtex_bool \c_true_bool } - { - \IfClassLoadedTF { 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 -% 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 { . } } - \tex_mkern:D 2 mu - \box_move_up:nn { 4 pt } { \hbox { . } } - \tex_mkern:D 2 mu - \box_move_up:nn { 7 pt } - { \vbox:n { \kern 7 pt \hbox { . } } } - \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_nopar: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_if_zero:nT \l_@@_first_col_int { \omit & } - \int_compare:nNnT { #1 } > \c_one_int - { \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 will be nullified in the environment |{NiceTabular}|, -% |{NiceTabular*}| and |{NiceTabularX}|. -% \begin{macrocode} -\cs_set_eq:NN \@@_math_toggle: \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 { o } -% \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 { o } -% \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 o } -% \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 { o } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_set_eq:NN \@@_old_pgfpointanchor \pgfpointanchor -% \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 -% If the user uses |{NiceTabular}|, |{NiceTabular*}| or |{NiceTabularX}|, we -% will raise the following flag. -% \begin{macrocode} -\bool_new:N \l_@@_tabular_bool -% \end{macrocode} -% -% \bigskip -% |\g_@@_delims_bool| will be true for the environments with delimiters (ex. : -% |{pNiceMatrix}|, |{pNiceArray}|, |\pAutoNiceMatrix|, etc.). -% \begin{macrocode} -\bool_new:N \g_@@_delims_bool -\bool_gset_true:N \g_@@_delims_bool -% \end{macrocode} -% In fact, if there is delimiters in the preamble of |{NiceArray}| (eg: -% |[cccc]|), this boolean will be set to false. -% -% \medskip -% The following boolean will be equal to |true| in the environments which have -% a preamble (provided by the final user): |{NiceTabular}|, |{NiceArray}|, -% |{pNiceArray}|, etc. -% \begin{macrocode} -\bool_new:N \l_@@_preamble_bool -\bool_set_true:N \l_@@_preamble_bool -% \end{macrocode} -% -% \medskip -% We need a special treatment for |{NiceMatrix}| when |vlines| is not used, in -% order to retrieve |\arraycolsep| on both sides. -% \begin{macrocode} -\bool_new:N \l_@@_NiceMatrix_without_vlines_bool -% \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| and |j|. For example, a column |p[l]{3cm}| will provide the -% value |l| for all the cells of the column. -% \begin{macrocode} -\tl_new:N \l_@@_hpos_cell_tl -\tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_c_tl -% \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 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 |{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 -% The key |color| in a command of rule such as |\Hline| (or the specifier -% ``\verb+|+'' in the preamble of an environment). -% \begin{macrocode} -\tl_new:N \l_@@_rule_color_tl -% \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 -% The following boolean will be raise then the command |\rotate| is used with -% the key |c|. -% \begin{macrocode} -\bool_new:N \g_@@_rotate_c_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_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} -% -% During the second run, if informations concerning the current environment has -% been found in the |aux| file, the following flag will be raised. -% \begin{macrocode} -\bool_new:N \g_@@_aux_found_bool -% \end{macrocode} -% -% \bigskip -% In particuler, in that |aux| file, there will be, for each environment of -% \pkg{nicematrix}, an affectation for the the following sequence that will -% contain informations about the size of the array. -% \begin{macrocode} -\seq_new:N \g_@@_size_seq -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\tl_new:N \g_@@_left_delim_tl -\tl_new:N \g_@@_right_delim_tl -% \end{macrocode} -% -% \bigskip -% The token list |\g_@@_user_preamble_tl| will contain the preamble provided by -% the the final user of \pkg{nicematrix} (eg the preamble of an environment -% |{NiceTabular}|). -% \begin{macrocode} -\tl_new:N \g_@@_user_preamble_tl -% \end{macrocode} -% The token list |\g_@@_array_preamble_tl| will contain the preamble constructed -% by \pkg{nicematrix} for the environment |{array}| (of \pkg{array}). -% \begin{macrocode} -\tl_new:N \g_@@_array_preamble_tl -% \end{macrocode} -% For |\multicolumn|. -% \begin{macrocode} -\tl_new:N \g_@@_preamble_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|. -% \begin{macrocode} -\tl_new:N \l_@@_columns_type_tl -\str_set:Nn \l_@@_columns_type_tl { c } -% \end{macrocode} -% -% \bigskip -% The following parameters correspond to the keys |down|, |up| and |middle| of a -% command such as |\Cdots|. Usually, the final user doesn't use that keys -% directly because he uses the syntax with the embellishments |_|, |^| and |:|. -% \begin{macrocode} -\tl_new:N \l_@@_xdots_down_tl -\tl_new:N \l_@@_xdots_up_tl -\tl_new:N \l_@@_xdots_middle_tl -% \end{macrocode} -% -% \bigskip -% We will store in the following sequence informations provided by the -% instructions |\rowlistcolors| in the main array (not in the |\CodeBefore|). -% \begin{macrocode} -\seq_new:N \g_@@_rowlistcolors_seq -% \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} -% -% -% 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 -% \begin{macrocode} -\bool_new:N \l_@@_bold_row_style_bool -% \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 -% 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 so-called |\CodeBefore| is splitted in two parts because we want to control -% the order of execution of some instructions. -% \begin{macrocode} -\tl_new:N \g_@@_pre_code_before_tl -\tl_new:N \g_nicematrix_code_before_tl -% \end{macrocode} -% 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|. -% -% \bigskip -% The so-called |\CodeAfter| is splitted in two parts because we want to control -% the order of execution of some instructions. -% \begin{macrocode} -\tl_new:N \g_@@_pre_code_after_tl -\tl_new:N \g_nicematrix_code_after_tl -% \end{macrocode} -% The |\CodeAfter| provided by the final user (with the key |code-after| or the -% keyword |\CodeAfter|) will be stored in the second token list. -% -% \bigskip -% \begin{macrocode} -\bool_new:N \l_@@_in_code_after_bool -% \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 counters will be used when drawing the rules. -% \begin{macrocode} -\int_new:N \l_@@_start_int -\int_set_eq:NN \l_@@_start_int \c_one_int -\int_new:N \l_@@_end_int -\int_new:N \l_@@_local_start_int -\int_new:N \l_@@_local_end_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|, |opacity|, |draw|, -% |tikz|, |borders|, and |rounded-corners| of the command |\Block|. -% \begin{macrocode} -\tl_new:N \l_@@_fill_tl -\tl_new:N \l_@@_opacity_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 -% In the key |tikz| of a command |\Block| or in the argument of a command -% |\TikzEveryCell|, the final user puts a list of tikz keys. But, you have added -% another key, named |offset| (which means that an offset will be used for the -% frame of the block or the cell). The following parameter corresponds to that key. -% \begin{macrocode} -\dim_new:N \l_@@_offset_dim -% \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 -% If the final user has used the special color ``|nocolor|'', the following flag -% will be raised. -% \begin{macrocode} -\bool_new:N \@@_nocolor_used_bool -% \end{macrocode} -% -% \medskip -% For the vertical position, the possible values are |c|, |t| and |b|. -% \begin{macrocode} -\str_new:N \l_@@_vpos_block_str -\str_set:Nn \l_@@_vpos_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_eq:NN \l_@@_first_col_int \c_one_int -% \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. The command |\NiceMatrixOptions| also sets -% |\l_@@_last_col_int| to~$0$. -% \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:|. -% -% \medskip -% In the last column, we will raise the following flag (it will be used by -% |\OnlyMainNiceMatrix|). -% \begin{macrocode} -\bool_new:N \l_@@_in_last_col_bool -% \end{macrocode} -% \end{itemize} -% -% \bigskip -% \textbf{Some utilities} -% -% \medskip -% \begin{macrocode} -\cs_set_protected:Npn \@@_cut_on_hyphen:w #1-#2\q_stop - { - \cs_set_nopar:Npn \l_tmpa_tl { #1 } - \cs_set_nopar:Npn \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:NVF #1 \c_@@_all_tl - { - \clist_clear:N \l_tmpa_clist - \clist_map_inline:Nn #1 - { - \tl_if_in:nnTF { ##1 } { - } - { \@@_cut_on_hyphen:w ##1 \q_stop } - { - \cs_set_nopar:Npn \l_tmpa_tl { ##1 } - \cs_set_nopar:Npn \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 -% The following internal parameters are for: -% \begin{itemize} -% \item |\Ldots| \emph{with both extremities open} (and hence also |\Hdotsfor| in an -% exterior row; -% \item |\Vdots| \emph{with both extremities open} (and hence also |\Vdotsfor| in an -% exterior column; -% \item when the special character ``|:|'' is used in order to put the label of -% a so-called ``dotted line'' \emph{on the line}, a margin of -% |\c_@@_innersep_middle_dim| will be added around the label. -% \end{itemize} -% -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \dim_const:Nn \c_@@_shift_Ldots_last_row_dim { 0.5 em } - \dim_const:Nn \c_@@_shift_exterior_Vdots_dim { 0.6 em } - \dim_const:Nn \c_@@_innersep_middle_dim { 0.17 em } - } -% \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 component of |\g_@@_notes_seq| will be a kind of -% couple of the form : \texttt{\{\textsl{label}\}\{\textsl{text of the -% tabularnote}\}}. The first component 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 expressed by |\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 components 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_lazy_or:nnT { \cs_if_exist_p:N \@captype } \l_@@_in_env_bool - { - \bool_lazy_and:nnTF { ! \l_@@_tabular_bool } \l_@@_in_env_bool - { \@@_error:n { tabularnote~forbidden } } - { - \bool_if:NTF \l_@@_in_caption_bool - \@@_tabularnote_caption:nn - \@@_tabularnote:nn - { #1 } { #2 } - } - } - } - } - { - \NewDocumentCommand \tabularnote { o m } - { - \@@_error_or_warning:n { enumitem~not~loaded } - \@@_gredirect_none:n { enumitem~not~loaded } - } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_first_novalue:nnn #1 #2 #3 - { \tl_if_novalue:nT { #1 } { #3 } } -% \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 expressed by |\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 expressed by |\c_novalue_tl|. -% -% When we will go through the sequence |\g_@@_notes_seq|, we will count in -% |\l_tmpb_int| the notes without explicit label in order to have the -% ``current'' value of the counter |\c@tabularnote|. -% \begin{macrocode} - \int_zero:N \l_tmpb_int - \seq_map_indexed_inline:Nn \g_@@_notes_seq - { - \@@_test_first_novalue:nnn ##2 { \int_incr:N \l_tmpb_int } - \tl_if_eq:nnT { { #1 } { #2 } } { ##2 } - { - \tl_if_novalue:nTF { #1 } - { \int_set_eq:NN \l_tmpa_int \l_tmpb_int } - { \int_set:Nn \l_tmpa_int { ##1 } } - \seq_map_break: - } - } - \int_if_zero:nF \l_tmpa_int - { \int_add:Nn \l_tmpa_int \g_@@_notes_caption_int } - } - \int_if_zero:nT \l_tmpa_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_if_zero:nTF \l_tmpa_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 when -% |\l_@@_hpos_cell_tl| is equal to |c| or |r|. -% \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_gdecr:N \c@tabularnote - \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 - \bool_lazy_or:nnTF - { \tl_if_eq_p:NN \l_@@_hpos_cell_tl \c_@@_c_tl } - { \tl_if_eq_p:NN \l_@@_hpos_cell_tl \c_@@_r_tl } - { - \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 } - } - { \box_use: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. -% Be careful! We must put |\tl_if_in:NnF| and not |\tl_if_in:NnT|! -% \begin{macrocode} - \seq_if_in:NnF \g_@@_notes_in_caption_seq { { #1 } { #2 } } - { \@@_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. -% \begin{macrocode} - \seq_if_in:NnTF \g_@@_notes_in_caption_seq { { #1 } { #2 } } - { -% \end{macrocode} -% Now, we know 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 \@@_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 - { - 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 - { - 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 |color-inside| is used, these -% commands are available. -% \begin{macrocode} -\bool_new:N \l_@@_color_inside_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 parameter corresponds to the key |xdots/horizontal_labels|. -% \begin{macrocode} -\bool_new:N \l_@@_xdots_h_labels_bool -% \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} -% The unit is |em| and that's why we fix the dimension after the preamble. -% -% \bigskip -% The following dimension is the distance between a node (in fact an -% anchor of that node) and a dotted line (for real dotted lines, the actual -% distance may, of course, be a bit larger, depending of the exact position of -% the dots). -% \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} -% The unit is |em| and that's why we fix the dimension after the preamble. -% -% \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} -% The unit is |em| and that's why we fix the dimension after the preamble. -% -% -% \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| -% and the boolean |\l_@@_light_syntax_expanded_bool| correspond to the the -% option |light-syntax-expanded|. -% \begin{macrocode} -\bool_new:N \l_@@_light_syntax_bool -\bool_new:N \l_@@_light_syntax_expanded_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 within |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 -% When the key |respect-arraystretch| is used, the following command will be nullified. -% \begin{macrocode} -\cs_new_protected:Npn \@@_reset_arraystretch: - { \cs_set_nopar:Npn \arraystretch { 1 } } -% \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 } - { - 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 } } , - shorten-start .value_required:n = true , - shorten-end .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 .value_required:n = true , - horizontal-labels .bool_set:N = \l_@@_xdots_h_labels_bool , - horizontal-labels .default:n = true , - 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 , - 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|, |up| and |middle| are not documented for the final user -% because he should use the syntax with |^|, |_| and |:|. We use -% |\tl_put_right:Nn| and not |\tl_set:Nn| (or |.tl_set:N|) because we don't want -% a direct use of |up=...| erased by a absent |^{...}|. -% \begin{macrocode} - down .code:n = \tl_put_right:Nn \l_@@_xdots_down_tl { #1 } , - up .code:n = \tl_put_right:Nn \l_@@_xdots_up_tl { #1 } , - middle .code:n = \tl_put_right:Nn \l_@@_xdots_middle_tl { #1 } , -% \end{macrocode} -% The key |draw-first|, which is meant to be used only with |\Ddots| and -% |\Iddots|, will 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 } - { - no-cell-nodes .code:n = - \cs_set_protected:Npn \@@_node_for_cell: - { \box_use_drop:N \l_@@_cell_box } , - no-cell-nodes .value_forbidden:n = true , - rounded-corners .dim_set:N = \l_@@_tab_rounded_corners_dim , - rounded-corners .default:n = 4 pt , - 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 .code:n = - \bool_set_true:N \l_@@_light_syntax_bool - \bool_set_false:N \l_@@_light_syntax_expanded_bool , - light-syntax .value_forbidden:n = true , - light-syntax-expanded .code:n = - \bool_set_true:N \l_@@_light_syntax_bool - \bool_set_true:N \l_@@_light_syntax_expanded_bool , - light-syntax-expanded .value_forbidden: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_if_in:NnTF \c_@@_forbidden_letters_tl { #1 } - { \@@_error:nn { Forbidden~letter } { #1 } } -% \end{macrocode} -% We write directly a command for the automata which reads the preamble provided -% by the final user. -% \begin{macrocode} - { \cs_set_eq:cN { @@ _ #1 } \@@_make_preamble_vlism:n } - } - { \@@_error:n { One~letter~allowed } } - } , - vlines-in-sub-matrix .value_required:n = true , - hvlines .code:n = - { - \bool_set_true:N \l_@@_hvlines_bool - \tl_set_eq:NN \l_@@_vlines_clist \c_@@_all_tl - \tl_set_eq:NN \l_@@_hlines_clist \c_@@_all_tl - } , - hvlines-except-borders .code:n = - { - \tl_set_eq:NN \l_@@_vlines_clist \c_@@_all_tl - \tl_set_eq:NN \l_@@_hlines_clist \c_@@_all_tl - \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 .code:n = - \cs_set_eq:NN \@@_reset_arraystretch: \prg_do_nothing: , - respect-arraystretch .value_forbidden: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:Nx \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 , - color-inside .code:n = - \bool_set_true:N \l_@@_color_inside_bool - \bool_set_true:N \l_@@_code_before_bool , - color-inside .value_forbidden:n = true , - colortbl-like .meta:n = color-inside - } -% \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 .cs_set:Np = \@@_notes_style:n #1 , - style .value_required:n = true , - label-in-tabular .cs_set:Np = \@@_notes_label_in_tabular:n #1 , - label-in-tabular .value_required:n = true , - label-in-list .cs_set:Np = \@@_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 , - CodeAfter / 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 .dim_set:N = \l_@@_width_dim , - 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 .tl_set:N = \l_@@_columns_type_tl , - 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 .tl_set:N = \l_@@_columns_type_tl , - 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 , - 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 -% 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. -% -% We \emph{must} put the following instructions \emph{after} the : -% -% \begin{verbatim} -% CodeAfter / sub-matrix .inherit:n = NiceMatrix / sub-matrix -% \end{verbatim} -% -% \begin{macrocode} -\keys_define:nn { NiceMatrix / CodeAfter } - { - 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 , - xdots .code:n = \keys_set:nn { NiceMatrix / xdots } { #1 } , - sub-matrix .code:n = \keys_set:nn { NiceMatrix / sub-matrix } { #1 } , - sub-matrix .value_required:n = true , - unknown .code:n = \@@_error:n { Unknown~key~for~CodeAfter } - } -% \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 the LaTeX counter |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 = \c_one_int - { \int_compare:nNnT \l_@@_first_col_int = \c_one_int \@@_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| is in the -% |\@@_cell_end:|. -% \begin{macrocode} - \hbox_set:Nw \l_@@_cell_box -% \end{macrocode} -% The following command is nullified in the tabulars. -% \begin{macrocode} - \@@_tuning_not_tabular_begin: -% \end{macrocode} -% -% \begin{macrocode} - \@@_tuning_first_row: - \@@_tuning_last_row: - \g_@@_row_style_tl - } -% \end{macrocode} -% -% The following command will be nullified unless there is a first row. -% \begin{macrocode} -\cs_new_protected:Npn \@@_tuning_first_row: - { - \int_if_zero:nT \c@iRow - { - \int_compare:nNnT \c@jCol > \c_zero_int - { - \l_@@_code_for_first_row_tl - \xglobal \colorlet { nicematrix-first-row } { . } - } - } - } -% \end{macrocode} -% -% The following command will be nullified unless there is a last row and we -% know its value (\emph{ie}: |\l_@@_lat_row_int > 0|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_tuning_last_row: - { - \int_compare:nNnT \c@iRow = \l_@@_last_row_int - { - \l_@@_code_for_last_row_tl - \xglobal \colorlet { nicematrix-last-row } { . } - } - } -% \end{macrocode} -% -% A different value will be provided to the following command when the key -% |small| is in force. -% \begin{macrocode} -\cs_set_eq:NN \@@_tuning_key_small: \prg_do_nothing: -% \end{macrocode} -% -% The following commands are nullified in the tabulars. -% \begin{macrocode} -\cs_set_nopar:Npn \@@_tuning_not_tabular_begin: - { - \c_math_toggle_token -% \end{macrocode} -% A special value is provided by the following controls sequence when the key -% |small| is in force. -% \begin{macrocode} - \@@_tuning_key_small: - } -\cs_set_eq:NN \@@_tuning_not_tabular_end: \c_math_toggle_token -% \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_if_zero:nTF \c@iRow - { - \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 = \c_one_int - { - \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 } - \bool_if:NTF \g_@@_rotate_c_bool - { - \hbox_set:Nn \l_@@_cell_box - { - \c_math_toggle_token - \vcenter { \box_use:N \l_@@_cell_box } - \c_math_toggle_token - } - } - { - \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 - \bool_gset_false:N \g_@@_rotate_c_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: - { -% \end{macrocode} -% The following command is nullified in the tabulars. -% \begin{macrocode} - \@@_tuning_not_tabular_end: - \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} - \@@_update_max_cell_width: -% \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_if:NTF \g_@@_not_empty_cell_bool - \@@_node_for_cell: - { - \dim_compare:nNnTF { \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 command will be nullified in our redefinition of |\multicolumn|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_update_max_cell_width: - { - \dim_gset:Nn \g_@@_max_cell_width_dim - { \dim_max:nn \g_@@_max_cell_width_dim { \box_wd:N \l_@@_cell_box } } - } -% \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: - \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 -% \begin{macrocode} -\pgfset - { - nicematrix / cell-node /.style = - { - inner~sep = \c_zero_dim , - minimum~width = \c_zero_dim - } - } -% \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} -\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 (with -% consequences for the parallelisation of the diagonal lines). -% \begin{macrocode} -\cs_new_protected:Npn \@@_instruction_of_type:nnn #1 #2 #3 - { - \bool_if:nTF { #1 } \tl_gput_left:cx \tl_gput_right:cx - { g_@@_ #2 _ lines _ tl } - { - \use:c { @@ _ draw _ #2 : nnn } - { \int_use:N \c@iRow } - { \int_use:N \c@jCol } - { \exp_not:n { #3 } } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_array: - { -% \begin{macrocode} - \dim_set:Nn \col@sep - { \bool_if:NTF \l_@@_tabular_bool \tabcolsep \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 we need something fully expandable here. -% \begin{macrocode} - [ \str_if_eq:VnTF \l_@@_baseline_tl c c t ] - } -% \end{macrocode} -% -% \medskip -% We keep in memory the standard version of |\ialign| because we will redefine -% |\ialign| in the environment |{NiceArrayWithDelims}| but restore the standard -% version for use in the cells of the array. -% \begin{macrocode} -\cs_set_eq:NN \@@_old_ialign: \ialign -% \end{macrocode} -% -% -% The following command creates a |row| node (and not a row of nodes!). -% \begin{macrocode} -\cs_new_protected:Npn \@@_create_row_node: - { - \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 \c_@@_all_tl - { - \exp_args:NNe - \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 -% 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} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_color_inside: - { - \bool_if:NF \l_@@_color_inside_bool - { -% \end{macrocode} -% We will issue an error only during the first run. -% \begin{macrocode} - \bool_if:NF \g_@@_aux_found_bool - { \@@_error:n { without~color-inside } } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_redefine_everycr: { \everycr { \@@_everycr: } } -\hook_gput_code:nnn { begindocument } { . } - { - \IfPackageLoadedTF { colortbl } - { - \cs_set_protected:Npn \@@_redefine_everycr: - { - \CT@everycr - { - \noalign { \cs_gset_eq:NN \CT@row@color \prg_do_nothing: } - \@@_everycr: - } - } - } - { } - } -% \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} -\hook_gput_code:nnn { begindocument } { . } - { - \IfPackageLoadedTF { booktabs } - { - \cs_new_protected:Npn \@@_patch_booktabs: - { \tl_put_left:Nn \@BTnormal \@@_create_row_node_i: } - } - { \cs_new_protected:Npn \@@_patch_booktabs: { } } - } -% \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 - \@@_patch_booktabs: - \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} -% By default, |\@@_small_scripstyle:| is null. -% \begin{macrocode} - \cs_set_eq:NN \@@_tuning_key_small: \scriptstyle - } -% \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 - { - \@@_redefine_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 } } - \cs_set_eq:NN \cellcolor \@@_cellcolor_tabular - \cs_set_eq:NN \rowcolor \@@_rowcolor_tabular - \cs_set_eq:NN \rowcolors \@@_rowcolors_tabular - \cs_set_eq:NN \rowlistcolors \@@_rowlistcolors_tabular - \int_compare:nNnT \l_@@_first_row_int > \c_zero_int - { \cs_set_eq:NN \@@_tuning_first_row: \prg_do_nothing: } - \int_compare:nNnT \l_@@_last_row_int < \c_zero_int - { \cs_set_eq:NN \@@_tuning_last_row: \prg_do_nothing: } - \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 } - \@@_revert_colortbl: -% \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 counting the tabular notes in -% the main array at the right value (we 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} - \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: - { - \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_@@_delims_bool - { -% \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 } - } - { - \dim_gset:Nn \l_@@_left_delim_dim - { 2 \bool_if:NTF \l_@@_tabular_bool \tabcolsep \arraycolsep } - \dim_gset_eq:NN \l_@@_right_delim_dim \l_@@_left_delim_dim - } -% \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_set:Nn \l_tmpa_tl { #1 } - \int_compare:nNnT { \char_value_catcode:n { 60 } } = { 13 } - { \@@_rescan_for_spanish:N \l_tmpa_tl } - \tl_gput_left:NV \g_@@_pre_code_before_tl \l_tmpa_tl - \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 (that commmand will be used only once and is present only for legibility). -% \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 - \cs_set_eq:NN \TikzEveryCell \@@_TikzEveryCell - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_exec_code_before: - { - \seq_gclear_new:N \g_@@_colors_seq -% \end{macrocode} -% The sequence |\g_@@_colors_seq| will always contain as first element the -% special color |nocolor|: when that color is used, no color will be applied in -% the corresponding cells by the other coloring commands of \pkg{nicematrix}. -% \begin{macrocode} - \@@_add_to_colors_seq:nn { { nocolor } } { } - \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_@@_tabular_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 \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_@@_tabular_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 |\CodeBefore|, 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 -% 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 \g_@@_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_@@_user_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_@@_tabular_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| and the |\multicolumn|. -% -% \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} - \tl_if_exist:cTF { 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 } - } - { \bool_gset_false:N \g_@@_aux_found_bool } -% \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_@@_delims_bool - { \keys_set:nn { NiceMatrix / pNiceArray } } - { \keys_set:nn { NiceMatrix / NiceArray } } - { #3 , #5 } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \@@_set_CT@arc@:o \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_if_zero:nT \g_@@_total_X_weight_int - { \@@_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 > \c_zero_int - { - \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_if_zero:nT \l_@@_first_col_int - { \skip_horizontal:N \g_@@_width_first_col_dim } -% \end{macrocode} -% -% The construction of the real box is different whether we have delimiters to -% put. -% \begin{macrocode} - \bool_if:nTF { ! \g_@@_delims_bool } - { - \tl_if_eq:NNTF \l_@@_baseline_tl \c_@@_c_tl - \@@_use_arraybox_with_notes_c: - { - \tl_if_eq:NNTF \l_@@_baseline_tl \c_@@_b_tl - \@@_use_arraybox_with_notes_b: - \@@_use_arraybox_with_notes: - } - } -% \end{macrocode} -% -% Now, in the case of an environment with delimiters. 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_if_zero:nTF \l_@@_first_row_int - { - \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:o \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_@@_tabular_bool - { \skip_horizontal:N -\tabcolsep } - { \skip_horizontal:N -\arraycolsep } - \@@_use_arraybox_with_notes_c: - \bool_if:NTF \l_@@_tabular_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 - \skip_vertical:N \arrayrulewidth - } - \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 } - \bool_if:NT \l_@@_preamble_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:o \g_@@_aux_tl } - } - \iow_now:Nn \@mainaux { \ExplSyntaxOff } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \bool_if:NT \g_@@_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 final user provides a preamble, but we must convert that preamble into a -% preamble that will be given to |{array}| (of the package \pkg{array}). -% -% \bigskip -% The preamble given by the final user is stored in |\g_@@_user_preamble_tl|. -% The modified version will be stored in |\g_@@_array_preamble_tl| also. -% \begin{macrocode} -\cs_new_protected:Npn \@@_transform_preamble: - { - \@@_transform_preamble_i: - \@@_transform_preamble_ii: - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_transform_preamble_i: - { - \int_gzero:N \c@jCol -% \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_gclear:N \g_@@_cols_vlism_seq -% \end{macrocode} -% |\g_tmpb_bool| will be raised if you have a \verb+|+ at the end of the -% preamble provided by the final user. -% \begin{macrocode} - \bool_gset_false:N \g_tmpb_bool -% \end{macrocode} -% -% 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 - \tl_gclear:N \g_@@_array_preamble_tl - \tl_if_eq:NNTF \l_@@_vlines_clist \c_@@_all_tl - { - \tl_gset:Nn \g_@@_array_preamble_tl - { ! { \skip_horizontal:N \arrayrulewidth } } - } - { - \clist_if_in:NnT \l_@@_vlines_clist 1 - { - \tl_gset:Nn \g_@@_array_preamble_tl - { ! { \skip_horizontal:N \arrayrulewidth } } - } - } -% \end{macrocode} -% -% \bigskip -% Now, we actually make the preamble (which will be given to |{array}|). It will -% be stored in |\g_@@_array_preamble_tl|. -% \begin{macrocode} - \exp_last_unbraced:NV \@@_rec_preamble:n \g_@@_user_preamble_tl \stop - \int_gset_eq:NN \g_@@_static_num_of_col_int \c@jCol -% \end{macrocode} -% -% \medskip -% \begin{macrocode} - \@@_replace_columncolor: - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \IfPackageLoadedTF { colortbl } - { - \regex_const:Nn \c_@@_columncolor_regex { \c { columncolor } } - \cs_new_protected:Npn \@@_replace_columncolor: - { - \regex_replace_all:NnN - \c_@@_columncolor_regex - { \c { @@_columncolor_preamble } } - \g_@@_array_preamble_tl - } - } - { - \cs_new_protected:Npn \@@_replace_columncolor: - { \cs_set_eq:NN \columncolor \@@_columncolor_preamble } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_transform_preamble_ii: - { -% \end{macrocode} -% -% \medskip -% If there were delimiters at the beginning or at the end of the preamble, the -% environment |{NiceArray}| is transformed into an environment |{xNiceMatrix}|. -% \begin{macrocode} - \tl_if_eq:NNTF \g_@@_left_delim_tl \c_@@_dot_tl - { - \tl_if_eq:NNF \g_@@_right_delim_tl \c_@@_dot_tl - { \bool_gset_true:N \g_@@_delims_bool } - } - { \bool_gset_true:N \g_@@_delims_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_if_zero:nTF \l_@@_first_col_int - { \tl_gput_left:No \g_@@_array_preamble_tl \c_@@_preamble_first_col_tl } - { - \bool_if:NF \g_@@_delims_bool - { - \bool_if:NF \l_@@_tabular_bool - { - \tl_if_empty:NT \l_@@_vlines_clist - { - \bool_if:NF \l_@@_exterior_arraycolsep_bool - { \tl_gput_left:Nn \g_@@_array_preamble_tl { @ { } } } - } - } - } - } - \int_compare:nNnTF \l_@@_last_col_int > { -1 } - { \tl_gput_right:No \g_@@_array_preamble_tl \c_@@_preamble_last_col_tl } - { - \bool_if:NF \g_@@_delims_bool - { - \bool_if:NF \l_@@_tabular_bool - { - \tl_if_empty:NT \l_@@_vlines_clist - { - \bool_if:NF \l_@@_exterior_arraycolsep_bool - { \tl_gput_right:Nn \g_@@_array_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_@@_array_preamble_tl - { > { \@@_error_too_much_cols: } l } - } - } -% \end{macrocode} -% -% \bigskip -% The preamble provided by the final user will be read by a finite -% automata. The following function |\@@_rec_preamble:n| will read that preamble -% (usually letter by letter) in a recursive way (hence the name of that function). -% in the preamble. -% \begin{macrocode} -\cs_new_protected:Npn \@@_rec_preamble:n #1 - { -% \end{macrocode} -% For the majority of the letters, we will trigger the corresponding action by -% calling directly a function in the main hashtable of TeX (thanks to the -% mechanism |\csname...\endcsname|. Be careful: all these functions take in as -% first argument the letter (or token) itself.\footnote{We do that because it's -% an easy way to insert the letter at some places in the code that we will add to -% |\g_@@_array_preamble_tl|.} -% \begin{macrocode} - \cs_if_exist:cTF { @@ _ \token_to_str:N #1 } - { \use:c { @@ _ \token_to_str:N #1 } { #1 } } - { -% \end{macrocode} -% Now, the columns defined by |\newcolumntype| of \pkg{array}. -% \begin{macrocode} - \cs_if_exist:cTF { NC @ find @ #1 } - { - \tl_set_eq:Nc \l_tmpb_tl { NC @ rewrite @ #1 } - \exp_last_unbraced:NV \@@_rec_preamble:n \l_tmpb_tl - } - { - \tl_if_eq:nnT { #1 } { S } - { \@@_fatal:n { unknown~column~type~S } } - { \@@_fatal:nn { unknown~column~type } { #1 } } - } - } - } -% \end{macrocode} -% -% -% -% \bigskip -% For |c|, |l| and |r| -% \begin{macrocode} -\cs_new:Npn \@@_c #1 - { - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_preamble_tl - { > \@@_cell_begin:w c < \@@_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 - \@@_rec_preamble_after_col:n - } -% \end{macrocode} -% \begin{macrocode} -\cs_new:Npn \@@_l #1 - { - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_preamble_tl - { - > { \@@_cell_begin:w \tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_l_tl } - l - < \@@_cell_end: - } - \int_gincr:N \c@jCol - \@@_rec_preamble_after_col:n - } -% \end{macrocode} -% \begin{macrocode} -\cs_new:Npn \@@_r #1 - { - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_preamble_tl - { - > { \@@_cell_begin:w \tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_r_tl } - r - < \@@_cell_end: - } - \int_gincr:N \c@jCol - \@@_rec_preamble_after_col:n - } -% \end{macrocode} -% -% \medskip -% For |!| and |@| -% \begin{macrocode} -\cs_new:cpn { @@ _ \token_to_str:N ! } #1 #2 - { - \tl_gput_right:Nn \g_@@_array_preamble_tl { #1 { #2 } } - \@@_rec_preamble:n - } -\cs_set_eq:cc { @@ _ \token_to_str:N @ } { @@ _ \token_to_str:N ! } -% \end{macrocode} -% -% -% \medskip -% For \verb+|+ -% \begin{macrocode} -\cs_new:cpn { @@ _ | } #1 - { -% \end{macrocode} -% |\l_tmpa_int| is the number of successive occurrences of \verb+|+ -% \begin{macrocode} - \int_incr:N \l_tmpa_int - \@@_make_preamble_i_i:n - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_i_i:n #1 - { - \str_if_eq:nnTF { #1 } | - { \use:c { @@ _ | } | } - { \@@_make_preamble_i_ii:nn { } #1 } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_i_ii:nn #1 #2 - { - \str_if_eq:nnTF { #2 } [ - { \@@_make_preamble_i_ii:nw { #1 } [ } - { \@@_make_preamble_i_iii:nn { #2 } { #1 } } - } -\cs_new_protected:Npn \@@_make_preamble_i_ii:nw #1 [ #2 ] - { \@@_make_preamble_i_ii:nn { #1 , #2 } } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_i_iii:nn #1 #2 - { - \@@_compute_rule_width:n { multiplicity = \l_tmpa_int , #2 } - \tl_gput_right:Nx \g_@@_array_preamble_tl - { -% \end{macrocode} -% Here, the command |\dim_eval:n| is mandatory. -% \begin{macrocode} - \exp_not:N ! { \skip_horizontal:n { \dim_eval:n { \l_@@_rule_width_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_@@_rule_width_dim , - #2 - } -% \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 } { \stop } { \bool_gset_true:N \g_tmpb_bool } - \@@_rec_preamble:n #1 - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new:cpn { @@ _ > } #1 #2 - { - \tl_gput_right:Nn \g_@@_pre_cell_tl { > { #2 } } - \@@_rec_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_eq:NN \l_@@_hpos_col_str \c_@@_r_str , - r .value_forbidden:n = true , - c .code:n = \str_set_eq:NN \l_@@_hpos_col_str \c_@@_c_str , - c .value_forbidden:n = true , - l .code:n = \str_set_eq:NN \l_@@_hpos_col_str \c_@@_l_str , - l .value_forbidden:n = true , - R .code:n = - \IfPackageLoadedTF { ragged2e } - { \str_set_eq:NN \l_@@_hpos_col_str \c_@@_R_str } - { - \@@_error_or_warning:n { ragged2e~not~loaded } - \str_set_eq:NN \l_@@_hpos_col_str \c_@@_r_str - } , - R .value_forbidden:n = true , - L .code:n = - \IfPackageLoadedTF { ragged2e } - { \str_set_eq:NN \l_@@_hpos_col_str \c_@@_L_stsr } - { - \@@_error_or_warning:n { ragged2e~not~loaded } - \str_set_eq:NN \l_@@_hpos_col_str \c_@@_l_str - } , - L .value_forbidden:n = true , - C .code:n = - \IfPackageLoadedTF { ragged2e } - { \str_set_eq:NN \l_@@_hpos_col_str \c_@@_C_str } - { - \@@_error_or_warning:n { ragged2e~not~loaded } - \str_set_eq:NN \l_@@_hpos_col_str \c_@@_c_str - } , - C .value_forbidden:n = true , - S .code:n = \str_set_eq:NN \l_@@_hpos_col_str \c_@@_si_str , - 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|. -% \begin{macrocode} -\cs_new:Npn \@@_p #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} - \@@_make_preamble_ii_i:n - } -\cs_set_eq:NN \@@_b \@@_p -\cs_set_eq:NN \@@_m \@@_p -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_ii_i:n #1 - { - \str_if_eq:nnTF { #1 } { [ } - { \@@_make_preamble_ii_ii:w [ } - { \@@_make_preamble_ii_ii:w [ ] { #1 } } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_ii_ii:w [ #1 ] - { \@@_make_preamble_ii_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 \@@_make_preamble_ii_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_eq:NN \l_@@_hpos_col_str \c_@@_j_str - \@@_keys_p_column:n { #1 } - \@@_make_preamble_ii_iv:nnn { #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 } -% \end{macrocode} -% -% \medskip -% The first argument is the width of the column. The second is the type of -% environment: |minipage| or |varwidth|. The third is some code added at the -% beginning of the cell. -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_ii_iv:nnn #1 #2 #3 - { - \use:e - { - \@@_make_preamble_ii_v:nnnnnnnn - { \str_if_eq:onTF \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_tl| which -% will provide the horizontal alignment of the column to which belongs the cell. -% \begin{macrocode} - \str_if_eq:NNTF \l_@@_hpos_col_str \c_@@_j_str - { \tl_clear:N \exp_not:N \l_@@_hpos_cell_tl } - { - \cs_set_nopar:Npn \exp_not:N \l_@@_hpos_cell_tl - { \str_lowercase:V \l_@@_hpos_col_str } - } - \str_case:on \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 } - } - #3 - } - { \str_if_eq:onT \l_@@_vpos_col_str { m } \@@_center_cell_box: } - { \str_if_eq:onT \l_@@_hpos_col_str { si } \siunitx_cell_begin:w } - { \str_if_eq:onT \l_@@_hpos_col_str { si } \siunitx_cell_end: } - { #2 } - { - \str_case:onF \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 - \@@_rec_preamble_after_col:n - } -% \end{macrocode} -% -% \medskip -% |#1| is the optional argument of |{minipage}| (or |{varwidth}|): |t| or |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_tl| 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 \@@_make_preamble_ii_v:nnnnnnnn #1 #2 #3 #4 #5 #6 #7 #8 - { - \tl_if_eq:NNTF \l_@@_hpos_col_str \c_@@_si_str - { \tl_gput_right:Nn \g_@@_array_preamble_tl { > { \@@_test_if_empty_for_S: } } } - { \tl_gput_right:Nn \g_@@_array_preamble_tl { > { \@@_test_if_empty: } } } - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_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 -% \end{macrocode} -% We use the form |\minipage|--|\endminipage| (|\varwidth|--|\endvarwidth|) for -% compatibility with \pkg{collcell} (2023-10-31). -% \begin{macrocode} - \use:c { #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 - \use:c { 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} -\str_new:N \c_@@_ignorespaces_str -\str_set:Nx \c_@@_ignorespaces_str { \ignorespaces } -\str_remove_all:Nn \c_@@_ignorespaces_str { ~ } -% \end{macrocode} -% -% \bigskip -% In order to test whether a cell is empty, we test whether it begins by -% |\ignorespaces\unskip|. However, in some circunstancies, for example when -% |\collectcell| of \pkg{collcell} is used, the cell does not begin with -% |\ignorespaces|. In that case, we consider as not empty... -% -% First, we test if the next token is |\ignorespaces| and it's not very easy... -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_if_empty: { \peek_after:Nw \@@_test_if_empty_i: } -\cs_new_protected:Npn \@@_test_if_empty_i: - { - \str_set:Nx \l_tmpa_str { \token_to_meaning:N \l_peek_token } - \str_if_eq:NNT \l_tmpa_str \c_@@_ignorespaces_str - { \@@_test_if_empty:w } - } -\cs_new_protected:Npn \@@_test_if_empty:w \ignorespaces - { - \peek_meaning:NT \unskip - { - \tl_gput_right:Nn \g_@@_cell_after_hook_tl - { - \box_set_wd:Nn \l_@@_cell_box \c_zero_dim - \skip_horizontal:N \l_@@_col_width_dim - } - } - } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_test_if_empty_for_S: - { - \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 } - } - } -% \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:Npn \@@_V #1 #2 - { - \str_if_eq:nnTF { #2 } { [ } - { \@@_make_preamble_V_i:w [ } - { \@@_make_preamble_V_i:w [ ] { #2 } } - } -\cs_new_protected:Npn \@@_make_preamble_V_i:w [ #1 ] - { \@@_make_preamble_V_ii:nn { #1 } } -\cs_new_protected:Npn \@@_make_preamble_V_ii:nn #1 #2 - { - \str_set:Nn \l_@@_vpos_col_str { p } - \str_set_eq:NN \l_@@_hpos_col_str \c_@@_j_str - \@@_keys_p_column:n { #1 } - \IfPackageLoadedTF { varwidth } - { \@@_make_preamble_ii_iv:nnn { #2 } { varwidth } { } } - { - \@@_error_or_warning:n { varwidth~not~loaded } - \@@_make_preamble_ii_iv:nnn { #2 } { minipage } { } - } - } -% \end{macrocode} -% -% \medskip -% For |w| and |W| -% \begin{macrocode} -\cs_new:Npn \@@_w { \@@_make_preamble_w:nnnn { } } -\cs_new:Npn \@@_W { \@@_make_preamble_w:nnnn { \@@_special_W: } } -% \end{macrocode} -% -% |#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 \@@_make_preamble_w:nnnn #1 #2 #3 #4 - { - \str_if_eq:nnTF { #3 } { s } - { \@@_make_preamble_w_i:nnnn { #1 } { #4 } } - { \@@_make_preamble_w_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 \@@_make_preamble_w_i:nnnn #1 #2 - { - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_preamble_tl - { - > { - \dim_set:Nn \l_@@_col_width_dim { #2 } - \@@_cell_begin:w - \tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_c_tl - } - c - < { - \@@_cell_end_for_w_s: - #1 - \@@_adjust_size_box: - \box_use_drop:N \l_@@_cell_box - } - } - \int_gincr:N \c@jCol - \@@_rec_preamble_after_col: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 \@@_make_preamble_w_ii:nnnn #1 #2 #3 #4 - { - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_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 - \cs_set_nopar:Npn \l_@@_hpos_cell_tl { #3 } - } - c - < { - \@@_cell_end: - \hbox_set_end: - #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 - \@@_rec_preamble_after_col: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| (of \pkg{siunitx}). -% \begin{macrocode} -\cs_new:Npn \@@_S #1 #2 - { - \str_if_eq:nnTF { #2 } { [ } - { \@@_make_preamble_S:w [ } - { \@@_make_preamble_S:w [ ] { #2 } } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_S:w [ #1 ] - { \@@_make_preamble_S_i:n { #1 } } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_S_i:n #1 - { - \IfPackageLoadedTF { siunitx } - { - \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl - \tl_gclear:N \g_@@_pre_cell_tl - \tl_gput_right:Nn \g_@@_array_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 - \@@_rec_preamble_after_col:n - } - { \@@_fatal:n { siunitx~not~loaded } } - } -% \end{macrocode} -% -% -% \medskip -% For |(|, |[| and |\{|. -% \begin{macrocode} -\cs_new:cpn { @@ _ \token_to_str:N ( } #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_if_zero:nTF \c@jCol - { - \tl_if_eq:NNTF \g_@@_left_delim_tl \c_@@_dot_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_eq:NN \g_@@_right_delim_tl \c_@@_dot_tl - \@@_rec_preamble:n #2 - } - { - \tl_gput_right:Nn \g_@@_array_preamble_tl { ! { \enskip } } - \@@_make_preamble_iv:nn { #1 } { #2 } - } - } - { \@@_make_preamble_iv:nn { #1 } { #2 } } - } -\cs_set_eq:cc { @@ _ \token_to_str:N [ } { @@ _ \token_to_str:N ( } -\cs_set_eq:cc { @@ _ \token_to_str:N \{ } { @@ _ \token_to_str:N ( } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_iv: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 } - \@@_rec_preamble:n - } - { \@@_rec_preamble:n #2 } - } -% \end{macrocode} -% -% In fact, if would be possible to define |\left| and |\right| as no-op. -% \begin{macrocode} -\cs_new:cpn { @@ _ \token_to_str:N \left } #1 { \use:c { @@ _ \token_to_str:N ( } } -% \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:cpn { @@ _ \token_to_str:N ) } #1 #2 - { - \bool_if:NT \l_@@_small_bool { \@@_fatal:n { Delimiter~with~small } } - \tl_if_in:nnTF { ) ] \} } { #2 } - { \@@_make_preamble_v:nnn #1 #2 } - { - \tl_if_eq:nnTF { \stop } { #2 } - { - \tl_if_eq:NNTF \g_@@_right_delim_tl \c_@@_dot_tl - { \tl_gset:Nn \g_@@_right_delim_tl { #1 } } - { - \tl_gput_right:Nn \g_@@_array_preamble_tl { ! { \enskip } } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } - \@@_rec_preamble:n #2 - } - } - { - \tl_if_in:nnT { ( [ \{ \left } { #2 } - { \tl_gput_right:Nn \g_@@_array_preamble_tl { ! { \enskip } } } - \tl_gput_right:Nx \g_@@_pre_code_after_tl - { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool } - \@@_rec_preamble:n #2 - } - } - } -\cs_set_eq:cc { @@ _ \token_to_str:N ] } { @@ _ \token_to_str:N ] } -\cs_set_eq:cc { @@ _ \token_to_str:N \} } { @@ _ \token_to_str:N \} } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_v:nnn #1 #2 #3 - { - \tl_if_eq:nnTF { \stop } { #3 } - { - \tl_if_eq:NNTF \g_@@_right_delim_tl \c_@@_dot_tl - { - \tl_gput_right:Nn \g_@@_array_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_@@_array_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 } - \@@_rec_preamble:n #3 - } - } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\cs_new:cpn { @@ _ \token_to_str:N \right } #1 - { \use:c { @@ _ \token_to_str: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 \@@_rec_preamble_after_col:n #1 - { - \str_if_eq:nnTF { #1 } { < } - \@@_rec_preamble_after_col_i:n - { - \str_if_eq:nnTF { #1 } { @ } - \@@_rec_preamble_after_col_ii:n - { - \tl_if_eq:NNTF \l_@@_vlines_clist \c_@@_all_tl - { - \tl_gput_right:Nn \g_@@_array_preamble_tl - { ! { \skip_horizontal:N \arrayrulewidth } } - } - { - \exp_args:NNe - \clist_if_in:NnT \l_@@_vlines_clist { \int_eval:n { \c@jCol + 1 } } - { - \tl_gput_right:Nn \g_@@_array_preamble_tl - { ! { \skip_horizontal:N \arrayrulewidth } } - } - } - \@@_rec_preamble:n { #1 } - } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_rec_preamble_after_col_i:n #1 - { - \tl_gput_right:Nn \g_@@_array_preamble_tl { < { #1 } } - \@@_rec_preamble_after_col: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 \@@_rec_preamble_after_col_ii:n #1 - { - \tl_if_eq:NNTF \l_@@_vlines_clist \c_@@_all_tl - { - \tl_gput_right:Nn \g_@@_array_preamble_tl - { @ { #1 \skip_horizontal:N \arrayrulewidth } } - } - { - \exp_args:NNe - \clist_if_in:NnTF \l_@@_vlines_clist { \int_eval:n { \c@jCol + 1 } } - { - \tl_gput_right:Nn \g_@@_array_preamble_tl - { @ { #1 \skip_horizontal:N \arrayrulewidth } } - } - { \tl_gput_right:Nn \g_@@_array_preamble_tl { @ { #1 } } } - } - \@@_rec_preamble:n - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new:cpn { @@ _ * } #1 #2 #3 - { - \tl_clear:N \l_tmpa_tl - \int_step_inline:nn { #2 } { \tl_put_right:Nn \l_tmpa_tl { #3 } } - \exp_last_unbraced:No \@@_rec_preamble:n \l_tmpa_tl - } -% \end{macrocode} -% -% \bigskip -% The token |\NC@find| is at the head of the definition of the columns type done -% by |\newcolumntype|. We wan't that token to be no-op here. -% \begin{macrocode} -\cs_new:cpn { @@ _ \token_to_str:N \NC@find } #1 { \@@_rec_preamble:n } -% \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:Npn \@@_X #1 #2 - { - \str_if_eq:nnTF { #2 } { [ } - { \@@_make_preamble_X:w [ } - { \@@_make_preamble_X:w [ ] #2 } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_X:w [ #1 ] - { \@@_make_preamble_X_i: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 \@@_make_preamble_X_i: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} - \str_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_eq:NN \l_@@_weight_int \c_one_int - \@@_keys_p_column:n { #1 } -% \end{macrocode} -% The unknown keys are put in |\l_tmpa_tl| -% \begin{macrocode} - \keys_set:no { WithArrows / X-column } \l_tmpa_tl - \int_compare:nNnT \l_@@_weight_int < \c_zero_int - { - \@@_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:Nne - \@@_make_preamble_ii_iv:nnn - { \l_@@_weight_int \l_@@_X_columns_dim } - { minipage } - { \@@_no_update_width: } - } - { - \tl_gput_right:Nn \g_@@_array_preamble_tl - { - > { - \@@_cell_begin:w - \bool_set_true:N \l_@@_X_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 - \@@_rec_preamble_after_col:n - } - } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_no_update_width: - { - \tl_gput_right:Nn \g_@@_cell_after_hook_tl - { \cs_set_eq:NN \@@_update_max_cell_width: \prg_do_nothing: } - } -% \end{macrocode} -% -% \medskip -% For the letter set by the user with |vlines-in-sub-matrix| (vlism). -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_preamble_vlism:n #1 - { - \seq_gput_right:Nx \g_@@_cols_vlism_seq - { \int_eval:n { \c@jCol + 1 } } - \tl_gput_right:Nx \g_@@_array_preamble_tl - { \exp_not:N ! { \skip_horizontal:N \arrayrulewidth } } - \@@_rec_preamble:n - } -% \end{macrocode} -% -% \medskip -% The token |\stop| is a marker that we have inserted to mark the end of the -% preamble (as provided by the final user) that we have inserted in the TeX flow. -% \begin{macrocode} -\cs_set_eq:cN { @@ _ \token_to_str:N \stop } \use_none:n -% \end{macrocode} -% -% \medskip -% The following lines try to catch some errors (when the final user has -% forgotten the preamble of its environment). -% \begin{macrocode} -\cs_new_protected:cpn { @@ _ \token_to_str:N \hline } - { \@@_fatal:n { Preamble~forgotten } } -\cs_set_eq:cc { @@ _ \token_to_str:N \Hline } { @@ _ \token_to_str:N \hline } -\cs_set_eq:cc { @@ _ \token_to_str:N \toprule } { @@ _ \token_to_str:N \hline } -\cs_set_eq:cc { @@ _ \token_to_str:N \CodeBefore } { @@ _ \token_to_str:N \hline } -% \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 } - \cs_set_eq:NN \@@_update_max_cell_width: \prg_do_nothing: % added 2023-10-04 - \begingroup - \cs_set:Npn \@addamp - { \legacy_if:nTF { @firstamp } { \@firstampfalse } { \@preamerr 5 } } -% \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 - \@@_make_m_preamble:n #2 \q_stop -% \end{macrocode} -% -% \medskip -% The following lines are an adaptation of the definition of |\multicolumn| in -% \pkg{array}. -% \begin{macrocode} - \exp_args:No \@mkpream \g_@@_preamble_tl - \@addtopreamble \@empty - \endgroup -% \end{macrocode} -% -% \medskip -% Now, we do a treatment specific to \pkg{nicematrix} which has no equivalent -% in the original definition of |\multicolumn|. -% \begin{macrocode} - \int_compare:nNnT { #1 } > \c_one_int - { - \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_if_zero:nTF \c@jCol - { \int_eval:n { \c@iRow + 1 } } - { \int_use:N \c@iRow } - } - { \int_eval:n { \c@jCol + 1 } } - { - \int_if_zero:nTF \c@jCol - { \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 \@@_make_m_preamble:n #1 - { - \str_case:nnF { #1 } - { - c { \@@_make_m_preamble_i:n #1 } - l { \@@_make_m_preamble_i:n #1 } - r { \@@_make_m_preamble_i:n #1 } - > { \@@_make_m_preamble_ii:nn #1 } - ! { \@@_make_m_preamble_ii:nn #1 } - @ { \@@_make_m_preamble_ii:nn #1 } - | { \@@_make_m_preamble_iii:n #1 } - p { \@@_make_m_preamble_iv:nnn t #1 } - m { \@@_make_m_preamble_iv:nnn c #1 } - b { \@@_make_m_preamble_iv:nnn b #1 } - w { \@@_make_m_preamble_v:nnnn { } #1 } - W { \@@_make_m_preamble_v:nnnn { \@@_special_W: } #1 } - \q_stop { } - } - { - \cs_if_exist:cTF { NC @ find @ #1 } - { - \tl_set_eq:Nc \l_tmpa_tl { NC @ rewrite @ #1 } - \exp_last_unbraced:No \@@_make_m_preamble:n \l_tmpa_tl - } - { - \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 \@@_make_m_preamble_i:n #1 - { - \tl_gput_right:Nn \g_@@_preamble_tl - { - > { \@@_cell_begin:w \cs_set_nopar:Npn \l_@@_hpos_cell_tl { #1 } } - #1 - < \@@_cell_end: - } -% \end{macrocode} -% -% We test for the presence of a |<|. -% \begin{macrocode} - \@@_make_m_preamble_x:n - } -% \end{macrocode} -% -% \medskip -% For |>|, |!| and |@| -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_m_preamble_ii:nn #1 #2 - { - \tl_gput_right:Nn \g_@@_preamble_tl { #1 { #2 } } - \@@_make_m_preamble:n - } -% \end{macrocode} -% -% -% \medskip -% For \verb+|+ -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_m_preamble_iii:n #1 - { - \tl_gput_right:Nn \g_@@_preamble_tl { #1 } - \@@_make_m_preamble:n - } -% \end{macrocode} -% -% \medskip -% For |p|, |m| and |b| -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_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} - \@@_make_m_preamble_x:n - } -% \end{macrocode} -% -% \medskip -% For |w| and |W| -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_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 - \cs_set_nopar:Npn \l_@@_hpos_cell_tl { #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} - \@@_make_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 \@@_make_m_preamble_x:n #1 - { - \str_if_eq:nnTF { #1 } { < } - \@@_make_m_preamble_ix:n - { \@@_make_m_preamble:n { #1 } } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_make_m_preamble_ix:n #1 - { - \tl_gput_right:Nn \g_@@_preamble_tl { < { #1 } } - \@@_make_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_@@_c_tl - { \box_use_drop:N \l_tmpa_box } - \@@_put_box_in_flow_i: - } -% \end{macrocode} -% -% \bigskip -% -% \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} - \tl_if_in:NnTF \l_@@_baseline_tl { line- } - { - \int_set:Nn \l_tmpa_int - { - \str_range:Nnn - \l_@@_baseline_tl - 6 - { \tl_count:o \l_@@_baseline_tl } - } - \@@_qpoint:n { row - \int_use:N \l_tmpa_int } - } - { - \tl_if_eq:NnTF \l_@@_baseline_tl { t } - { \int_set_eq:NN \l_tmpa_int \c_one_int } - { - \tl_if_eq:NnTF \l_@@_baseline_tl { 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_eq:NN \l_tmpa_int \c_one_int - } - \@@_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_if:NT \l_@@_NiceMatrix_without_vlines_bool - { - \int_compare:nNnT \c@jCol > \c_one_int - { - \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 > \c_zero_int - { - \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:o \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 } -% \end{macrocode} -% In some circonstancies (in particular when the package \pkg{caption} is -% loaded), the caption is composed several times. That's why, when the same -% tabular note is encountered (in the caption!), we consider that you are in the -% second compilation and you can give to |\g_@@_notes_caption_int| its final -% value, which is the number of tabular notes in the caption. But sometimes, the -% caption is composed only once. In that case, we fix the value of -% |\g_@@_caption_finished_bool| now. -% \begin{macrocode} - \bool_if:NF \g_@@_caption_finished_bool - { - \bool_gset_true:N \g_@@_caption_finished_bool - \int_gset_eq:NN \g_@@_notes_caption_int \c@tabularnote - \int_gzero:N \c@tabularnote - } - \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 > \c_zero_int - { - \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 -% curryfication. -% \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_if_zero:nT \l_@@_first_row_int - { - \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 } - { \cs_set_nopar:Npn \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:o \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_if_zero:nT \l_@@_first_row_int - { - \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:| because -% of compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}). -% \begin{macrocode} - \exp_args:No \@@_array: \g_@@_array_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 - \bool_if:NTF \l_@@_light_syntax_expanded_bool - \seq_set_split:Nee - \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:No \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| in order to allow the use of commands such as -% |\hline| or |\hdottedline| with the key |light-syntax|). -% \begin{macrocode} - \tl_build_begin: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:o \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_build_put_right:Nn \l_@@_new_body_tl { \\ } - \@@_line_with_light_syntax:n { ##1 } - } - \tl_build_end:N \l_@@_new_body_tl -% \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} -% \bigskip -% -% The call to |\array| is in the following command (we have a dedicated macro -% |\@@_array:| because of compatibility with the classes \cls{revtex4-1} and -% \cls{revtex4-2}). -% \begin{macrocode} - \exp_args:No \@@_array: \g_@@_array_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 - \exp_args:NNo \tl_build_put_right:Nn \l_@@_new_body_tl \l_tmpa_tl - \seq_map_inline:Nn \l_@@_cells_seq - { \tl_build_put_right:Nn \l_@@_new_body_tl { & ##1 } } - } -\cs_generate_variant:Nn \@@_line_with_light_syntax:n { o } -% \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:onT \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_if_zero:nT \l_@@_first_col_int - { - \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_if_zero:nTF \l_@@_first_col_int - { - \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 that 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 we will -% add some dimensions to it. -% \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_gadd:Nn \g_tmpa_skip \g_@@_max_cell_width_dim } - { \skip_gadd: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_eq:NN \g_tmpa_int \c_one_int - \bool_if:NTF \g_@@_last_col_found_bool - { \prg_replicate:nn { \int_max:nn { \g_@@_col_total_int - 3 } \c_zero_int } } - { \prg_replicate:nn { \int_max:nn { \g_@@_col_total_int - 2 } \c_zero_int } } - { - & - \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_if_zero:nT \g_@@_col_total_int - { \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_any:nF % modified 2023/12/13 - { - \g_@@_delims_bool - \l_@@_tabular_bool - { ! \clist_if_empty_p:N \l_@@_vlines_clist } - \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_if:NT \l_@@_NiceMatrix_without_vlines_bool - { \skip_horizontal:N -\arraycolsep } - \pgfsys@markposition - { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } - \skip_horizontal:N 0.5\arrayrulewidth - \bool_if:NT \l_@@_NiceMatrix_without_vlines_bool - { \skip_horizontal:N \arraycolsep } - } - } - \pgfpicture - \pgfrememberpicturepositiononpagetrue - \pgfcoordinate { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } } - { - \bool_if:NT \l_@@_NiceMatrix_without_vlines_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 - \skip_horizontal:N \col@sep % added 2023-11-05 - \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: - \@@_tuning_key_small: -% \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} - \int_compare:nNnT \c@iRow > \c_zero_int - { - \bool_lazy_or:nnT - { \int_compare_p:nNn \l_@@_last_row_int < \c_zero_int } - { \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: - \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 - { - > - { - \bool_set_true:N \l_@@_in_last_col_bool -% \end{macrocode} -% At the beginning of the cell, we link |\CodeAfter| to a command which -% 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: - \@@_tuning_key_small: -% \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 > \c_zero_int - { - \bool_lazy_or:nnT - { \int_compare_p:nNn \l_@@_last_row_int < \c_zero_int } - { \int_compare_p:nNn \c@iRow < \l_@@_last_row_int } - { - \l_@@_code_for_last_col_tl - \xglobal \colorlet { nicematrix-last-col } { . } - } - } - } - l - < - { - \@@_math_toggle: - \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}|. -% \begin{macrocode} -\NewDocumentEnvironment { NiceArray } { } - { - \bool_gset_false:N \g_@@_delims_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_@@_delims_bool| is set to false). -% \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_true:N \g_@@_delims_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_false:N \l_@@_preamble_bool - \tl_clear:N \l_tmpa_tl - \bool_if:NT \l_@@_NiceMatrix_without_vlines_bool - { \tl_set:Nn \l_tmpa_tl { @ { } } } - \tl_put_right:Nn \l_tmpa_tl - { - * - { - \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 } - } - \tl_set:Nn \l_tmpb_tl { \use:c { #1 NiceArray } } - \exp_args:No \l_tmpb_tl \l_tmpa_tl - } -% \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_true:N \g_@@_delims_bool - \str_gset:Nn \g_@@_name_env_str { #1 NiceMatrix } - % added 2023/10/01 - \int_if_zero:nT \l_@@_last_col_int - { - \bool_set_true:N \l_@@_last_col_without_value_bool - \int_set:Nn \l_@@_last_col_int { -1 } - } - \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 { } } - { - \str_gset:Nn \g_@@_name_env_str { NiceMatrix } - % added 2023/10/01 - \int_if_zero:nT \l_@@_last_col_int - { - \bool_set_true:N \l_@@_last_col_without_value_bool - \int_set:Nn \l_@@_last_col_int { -1 } - } - \keys_set:nn { NiceMatrix / NiceMatrix } { #1 } - \bool_lazy_or:nnT - { \clist_if_empty_p:N \l_@@_vlines_clist } - { \l_@@_except_borders_bool } - { \bool_set_true:N \l_@@_NiceMatrix_without_vlines_bool } - \@@_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 } - \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 } - } - } - { } - \@@_settings_for_tabular: - \NiceArray { #2 } - } - { \endNiceArray } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_settings_for_tabular: - { - \bool_set_true:N \l_@@_tabular_bool - \cs_set_eq:NN \@@_math_toggle: \prg_do_nothing: - \cs_set_eq:NN \@@_tuning_not_tabular_begin: \prg_do_nothing: - \cs_set_eq:NN \@@_tuning_not_tabular_end: \prg_do_nothing: - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\NewDocumentEnvironment { NiceTabularX } { m O { } m ! O { } } - { - \str_gset:Nn \g_@@_name_env_str { NiceTabularX } - \dim_zero_new:N \l_@@_width_dim - \dim_set:Nn \l_@@_width_dim { #1 } - \keys_set:nn { NiceMatrix / NiceTabular } { #2 , #4 } - \@@_settings_for_tabular: - \NiceArray { #3 } - } - { - \endNiceArray - \int_if_zero:nT \g_@@_total_X_weight_int - { \@@_error:n { NiceTabularX~without~X } } - } -% \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 } - \@@_settings_for_tabular: - \NiceArray { #3 } - } - { \endNiceArray } -% \end{macrocode} -% -% -% \bigskip -% \section{After the construction of the array} -% -% \bigskip -% The following command will be used when the key |rounded-corners| is in force -% (this is the key |rounded-corners| for the whole environment and \emph{not} -% the key |rounded-corners| of a command |\Block|). -% \begin{macrocode} -\cs_new_protected:Npn \@@_deal_with_rounded_corners: - { - \bool_lazy_all:nT - { - { \int_compare_p:nNn \l_@@_tab_rounded_corners_dim > \c_zero_dim } - \l_@@_hvlines_bool - { ! \g_@@_delims_bool } - { ! \l_@@_except_borders_bool } - } - { - \bool_set_true:N \l_@@_except_borders_bool - \clist_if_empty:NF \l_@@_corners_clist - { \@@_error:n { hvlines,~rounded-corners~and~corners } } - \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 } - } - } - } -% \end{macrocode} -% -% -% \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} - \@@_deal_with_rounded_corners: - \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 \TikzEveryCell \@@_TikzEveryCell - \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:No \@@_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 |color-inside| 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} - \seq_if_empty:NF \g_@@_rowlistcolors_seq { \@@_clear_rowlistcolors_seq: } - \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:o \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:o \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 } = \c_one_int - { \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 } = \c_one_int - { \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 } = \c_one_int - { \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 } = \c_one_int - { \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 -% If the final user uses the key |xdots/shorten| in |\NiceMatrixOptions| or at the -% level of an environment (such as |{pNiceMatrix}|, etc.), only the so called -% ``closed extremities'' will be shortened by that key. The following command -% will be used \emph{after} the detection of the extremities of a dotted line -% (hence at a time when we known wheter the extremities are closed or open) but -% before the analyse of the keys of the individual command |\Cdots|, |\Vdots|. -% Hence, the keys |shorten|, |shorten-start| and |shorten-end| of that -% individual command will be applied. -% \begin{macrocode} -\cs_new_protected:Npn \@@_open_shorten: - { - \bool_if:NT \l_@@_initial_open_bool - { \dim_zero:N \l_@@_xdots_shorten_start_dim } - \bool_if:NT \l_@@_final_open_bool - { \dim_zero:N \l_@@_xdots_shorten_end_dim } - } -% \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 - { - \int_compare:nNnF { #3 } > { #1 } - { - \int_compare:nNnF { #1 } > { #5 } - { - \int_compare:nNnF { #4 } > { #2 } - { - \int_compare:nNnF { #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 column 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: - \@@_open_shorten: - \int_if_zero:nTF { #1 } - { \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:oF \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} -% Now the case of a |\Hdotsfor| (or when there is only a |\Ldots|) in the ``last -% row'' (that case will probably arise when the final user draws an arrow to -% indicate the number of columns of the matrix). In the ``first row'', we don't -% need any adjustment. -% \begin{macrocode} - \bool_lazy_all:nTF - { - \l_@@_initial_open_bool - \l_@@_final_open_bool - { \int_compare_p:nNn \l_@@_initial_i_int = \l_@@_last_row_int } - } - { - \dim_add:Nn \l_@@_y_initial_dim \c_@@_shift_Ldots_last_row_dim - \dim_add:Nn \l_@@_y_final_dim \c_@@_shift_Ldots_last_row_dim - } -% \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: - \@@_open_shorten: - \int_if_zero:nTF { #1 } - { \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:oF \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: - { - \dim_set:Nn \l_@@_y_initial_dim { - \c_max_dim } - \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 } - } - } - \dim_compare:nNnT \l_@@_y_initial_dim = { - \c_max_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 - } - } - } - } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_open_y_final_dim: - { - \dim_set_eq:NN \l_@@_y_final_dim \c_max_dim - \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 } - } - } - \dim_compare:nNnT \l_@@_y_final_dim = \c_max_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 } } - } - } -% \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: - \@@_open_shorten: - \int_if_zero:nTF { #2 } - { \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:oF \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} -% -% First, the case of a dotted line open on both sides. -% \begin{macrocode} - \bool_lazy_and:nnTF \l_@@_initial_open_bool \l_@@_final_open_bool -% \end{macrocode} -% -% We have to determine the $x$-value of the vertical rule that we will have -% to draw. -% \begin{macrocode} - { - \@@_open_y_initial_dim: - \@@_open_y_final_dim: - \int_if_zero:nTF \l_@@_initial_j_int -% \end{macrocode} -% We have a dotted line open on both sides in the ``first column''. -% \begin{macrocode} - { - \@@_qpoint:n { col - 1 } - \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x - \dim_sub:Nn \l_@@_x_initial_dim \l_@@_left_margin_dim - \dim_sub:Nn \l_@@_x_initial_dim \l_@@_extra_left_margin_dim - \dim_sub:Nn \l_@@_x_initial_dim \c_@@_shift_exterior_Vdots_dim - } - { - \bool_lazy_and:nnTF - { \int_compare_p:nNn \l_@@_last_col_int > { -2 } } - { \int_compare_p:nNn \l_@@_initial_j_int = \g_@@_col_total_int } -% \end{macrocode} -% We have a dotted line open on both sides in the ``last column''. -% \begin{macrocode} - { - \@@_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 \l_@@_right_margin_dim - \dim_add:Nn \l_@@_x_initial_dim \l_@@_extra_right_margin_dim - \dim_add:Nn \l_@@_x_initial_dim \c_@@_shift_exterior_Vdots_dim - } -% \end{macrocode} -% We have a dotted line open on both sides which is \emph{not} in an exterior column. -% \begin{macrocode} - { - \@@_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 } - } - } - } -% \end{macrocode} -% -% Now, the dotted line is \emph{not} open on both sides (maybe open on only one side). -% -% The boolean |\l_tmpa_bool| will indicate whether the column is of type |l| or -% may be considered as if. -% \begin{macrocode} - { - \bool_set_false:N \l_tmpa_bool - \bool_if:NF \l_@@_initial_open_bool - { - \bool_if:NF \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_final_coords_from_anchor:n { north } - \dim_set_eq:NN \l_@@_x_initial_dim \l_@@_x_final_dim - } - { - \@@_set_initial_coords_from_anchor:n { south } - \bool_if:NTF \l_@@_final_open_bool - \@@_open_y_final_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} - { - \@@_set_final_coords_from_anchor:n { north } - \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: - \@@_open_shorten: - \keys_set:nn { NiceMatrix / xdots } { #3 } - \tl_if_empty:oF \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 = \c_one_int -% \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: - \@@_open_shorten: - \keys_set:nn { NiceMatrix / xdots } { #3 } - \tl_if_empty:oF \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 = \c_one_int - { - \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:No| 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:nooo - { #1 } - \l_@@_xdots_up_tl - \l_@@_xdots_down_tl - \l_@@_xdots_middle_tl - } -\cs_generate_variant:Nn \@@_draw_unstandard_dotted_line:n { o } -% \end{macrocode} -% -% -% \bigskip -% The following Tikz styles are for the three labels (set by the symbols |_|, -% |^| and |=|) of a continous line with a non-standard style. -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \IfPackageLoadedTF { tikz } - { - \tikzset - { - @@_node_above / .style = { sloped , above } , - @@_node_below / .style = { sloped , below } , - @@_node_middle / .style = - { - sloped , - inner~sep = \c_@@_innersep_middle_dim - } - } - } - { } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_draw_unstandard_dotted_line:nnnn #1 #2 #3 #4 - { -% \end{macrocode} -% We take into account the parameters |xdots/shorten-start| and -% |xdots/shorten-end| ``by hand'' because, when we use the key |shorten >| and -% |shorten <| of TikZ in the command |\draw|, we don't have the expected output -% with |{decorate,decoration=brace}| is used. -% -% \medskip -% 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} - \dim_compare:nNnT \l_@@_l_dim < \c_@@_max_l_dim - { - \dim_compare:nNnT \l_@@_l_dim > { 1 pt } - \@@_draw_unstandard_dotted_line_i: - } -% \end{macrocode} -% -% If the key |xdots/horizontal-labels| has been used. -% \begin{macrocode} - \bool_if:NT \l_@@_xdots_h_labels_bool - { - \tikzset - { - @@_node_above / .style = { auto = left } , - @@_node_below / .style = { auto = right } , - @@_node_middle / .style = { inner~sep = \c_@@_innersep_middle_dim } - } - } - \tl_if_empty:nF { #4 } - { \tikzset { @@_node_middle / .append~style = { fill = white } } } - \draw - [ #1 ] - ( \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 [ @@_node_middle] { $ \scriptstyle #4 $ } - node [ @@_node_below ] { $ \scriptstyle #3 $ } - node [ @@_node_above ] { $ \scriptstyle #2 $ } - ( \l_@@_x_final_dim , \l_@@_y_final_dim ) ; - \end { scope } - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_draw_unstandard_dotted_line_i: - { - \dim_set:Nn \l_tmpa_dim - { - \l_@@_x_initial_dim - + ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) - * \dim_ratio:nn \l_@@_xdots_shorten_start_dim \l_@@_l_dim - } - \dim_set:Nn \l_tmpb_dim - { - \l_@@_y_initial_dim - + ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) - * \dim_ratio:nn \l_@@_xdots_shorten_start_dim \l_@@_l_dim - } - \dim_set:Nn \l_@@_tmpc_dim - { - \l_@@_x_final_dim - - ( \l_@@_x_final_dim - \l_@@_x_initial_dim ) - * \dim_ratio:nn \l_@@_xdots_shorten_end_dim \l_@@_l_dim - } - \dim_set:Nn \l_@@_tmpd_dim - { - \l_@@_y_final_dim - - ( \l_@@_y_final_dim - \l_@@_y_initial_dim ) - * \dim_ratio:nn \l_@@_xdots_shorten_end_dim \l_@@_l_dim - } - \dim_set_eq:NN \l_@@_x_initial_dim \l_tmpa_dim - \dim_set_eq:NN \l_@@_y_initial_dim \l_tmpb_dim - \dim_set_eq:NN \l_@@_x_final_dim \l_@@_tmpc_dim - \dim_set_eq:NN \l_@@_y_final_dim \l_@@_tmpd_dim - } -% \end{macrocode} -% -% \begin{macrocode} -\cs_generate_variant:Nn \@@_draw_unstandard_dotted_line:nnnn { n o o o } -% \end{macrocode} -% -% \bigskip -% The command |\@@_draw_standard_dotted_line:| draws the line with our system of dots -% (which gives a dotted line with real rounded dots). -% \begin{macrocode} -\cs_new_protected:Npn \@@_draw_standard_dotted_line: - { - \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} - \dim_compare:nNnT \l_@@_l_dim < \c_@@_max_l_dim - { - \dim_compare:nNnT \l_@@_l_dim > { 1 pt } - \@@_draw_standard_dotted_line_i: - } - \group_end: -% \end{macrocode} -% \begin{macrocode} - \bool_lazy_all:nF - { - { \tl_if_empty_p:N \l_@@_xdots_up_tl } - { \tl_if_empty_p:N \l_@@_xdots_down_tl } - { \tl_if_empty_p:N \l_@@_xdots_middle_tl } - } - \l_@@_labels_standard_dotted_line: - } -% \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} - \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 \c_zero_int \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 -% \begin{macrocode} -\cs_new_protected:Npn \l_@@_labels_standard_dotted_line: - { - \pgfscope - \pgftransformshift - { - \pgfpointlineattime { 0.5 } - { \pgfpoint \l_@@_x_initial_dim \l_@@_y_initial_dim } - { \pgfpoint \l_@@_x_final_dim \l_@@_y_final_dim } - } - \fp_set:Nn \l_tmpa_fp - { - atand - ( - \l_@@_y_final_dim - \l_@@_y_initial_dim , - \l_@@_x_final_dim - \l_@@_x_initial_dim - ) - } - \pgftransformrotate { \fp_use:N \l_tmpa_fp } - \bool_if:NF \l_@@_xdots_h_labels_bool { \fp_zero:N \l_tmpa_fp } - \tl_if_empty:NF \l_@@_xdots_middle_tl - { - \begin { pgfscope } - \pgfset { inner~sep = \c_@@_innersep_middle_dim } - \pgfnode - { rectangle } - { center } - { - \rotatebox { \fp_eval:n { - \l_tmpa_fp } } - { - \c_math_toggle_token - \scriptstyle \l_@@_xdots_middle_tl - \c_math_toggle_token - } - } - { } - { - \pgfsetfillcolor { white } - \pgfusepath { fill } - } - \end { pgfscope } - } - \tl_if_empty:NF \l_@@_xdots_up_tl - { - \pgfnode - { rectangle } - { south } - { - \rotatebox { \fp_eval:n { - \l_tmpa_fp } } - { - \c_math_toggle_token - \scriptstyle \l_@@_xdots_up_tl - \c_math_toggle_token - } - } - { } - { \pgfusepath { } } - } - \tl_if_empty:NF \l_@@_xdots_down_tl - { - \pgfnode - { rectangle } - { north } - { - \rotatebox { \fp_eval:n { - \l_tmpa_fp } } - { - \c_math_toggle_token - \scriptstyle \l_@@_xdots_down_tl - \c_math_toggle_token - } - } - { } - { \pgfusepath { } } - } - \endpgfscope - } -% \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 } { . } - { - \cs_set_nopar:Npn \l_@@_argspec_tl { m E { _ ^ : } { { } { } { } } } - \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl - \cs_new_protected:Npn \@@_Ldots - { \@@_collect_options:n { \@@_Ldots_i } } - \exp_args:NNo \NewDocumentCommand \@@_Ldots_i \l_@@_argspec_tl - { - \int_if_zero:nTF \c@jCol - { \@@_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 , middle = #4 } - } - } - \bool_if:NF \l_@@_nullify_dots_bool - { \phantom { \ensuremath { \@@_old_ldots } } } - \bool_gset_true:N \g_@@_empty_cell_bool - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \cs_new_protected:Npn \@@_Cdots - { \@@_collect_options:n { \@@_Cdots_i } } - \exp_args:NNo \NewDocumentCommand \@@_Cdots_i \l_@@_argspec_tl - { - \int_if_zero:nTF \c@jCol - { \@@_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 , middle = #4 } - } - } - \bool_if:NF \l_@@_nullify_dots_bool - { \phantom { \ensuremath { \@@_old_cdots } } } - \bool_gset_true:N \g_@@_empty_cell_bool - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \cs_new_protected:Npn \@@_Vdots - { \@@_collect_options:n { \@@_Vdots_i } } - \exp_args:NNo \NewDocumentCommand \@@_Vdots_i \l_@@_argspec_tl - { - \int_if_zero:nTF \c@iRow - { \@@_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 , middle = #4 } - } - } - \bool_if:NF \l_@@_nullify_dots_bool - { \phantom { \ensuremath { \@@_old_vdots } } } - \bool_gset_true:N \g_@@_empty_cell_bool - } -% \end{macrocode} -% -% -% \bigskip -% \begin{macrocode} - \cs_new_protected:Npn \@@_Ddots - { \@@_collect_options:n { \@@_Ddots_i } } - \exp_args:NNo \NewDocumentCommand \@@_Ddots_i \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 , middle = #4 } - } - - } - \bool_if:NF \l_@@_nullify_dots_bool - { \phantom { \ensuremath { \@@_old_ddots } } } - \bool_gset_true:N \g_@@_empty_cell_bool - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} - \cs_new_protected:Npn \@@_Iddots - { \@@_collect_options:n { \@@_Iddots_i } } - \exp_args:NNo \NewDocumentCommand \@@_Iddots_i \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 , middle = #4 } - } - } - \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_if_zero_p:n \c@jCol } - { \int_if_zero_p:n \l_@@_first_col_int } - { - \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 } { . } - { - \cs_set_nopar:Npn \l_@@_argspec_tl { m 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} - \cs_new_protected:Npn \@@_Hdotsfor_i - { \@@_collect_options:n { \@@_Hdotsfor_ii } } - \exp_args:NNo \NewDocumentCommand \@@_Hdotsfor_ii \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 } , - middle = \exp_not:n { #6 } - } - } - \prg_replicate:nn { #2 - 1 } - { - & - \multicolumn { 1 } { c } { } - \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i: - } - } - } -% \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 } = \c_one_int - { - \int_set_eq:NN \l_@@_initial_j_int \c_one_int - \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: - \@@_open_shorten: - \int_if_zero:nTF { #1 } - { \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:oF \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 } { . } - { - \cs_set_nopar:Npn \l_@@_argspec_tl { m m O { } E { _ ^ : } { { } { } { } } } - \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl - \cs_new_protected:Npn \@@_Vdotsfor: - { \@@_collect_options:n { \@@_Vdotsfor_i } } - \exp_args:NNo \NewDocumentCommand \@@_Vdotsfor_i \l_@@_argspec_tl - { - \bool_gset_true:N \g_@@_empty_cell_bool - \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 } , - middle = \exp_not:n { #6 } - } - } - } - } -% \end{macrocode} -% -% \bigskip -% \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 } = \c_one_int - { - \int_set_eq:NN \l_@@_initial_i_int \c_one_int - \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: - \@@_open_shorten: - \int_if_zero:nTF { #2 } - { \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:oF \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} -\NewDocumentCommand \@@_rotate: { O { } } - { - \peek_remove_spaces:n - { - \bool_gset_true:N \g_@@_rotate_bool - \keys_set:nn { NiceMatrix / rotate } { #1 } - } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\keys_define:nn { NiceMatrix / rotate } - { - c .code:n = \bool_gset_true:N \g_@@_rotate_c_bool , - c .value_forbidden:n = true , - unknown .code:n = \@@_error:n { Unknown~key~for~rotate } - } -% \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. In -% fact, if also works with names of blocks. -% -% \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 } { . } - { - \cs_set_nopar:Npn \l_@@_argspec_tl - { O { } m m ! O { } E { _ ^ : } { { } { } { } } } - \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl - \exp_args:NNo \NewDocumentCommand \@@_line \l_@@_argspec_tl - { - \group_begin: - \keys_set:nn { NiceMatrix / xdots } { #1 , #4 , down = #5 , up = #6 } - \tl_if_empty:oF \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_lazy_or:nnTF - { \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 } } -% \end{macrocode} -% The test of |measuring@| is a security (cf. question 686649 on TeX StackExchange). -% \begin{macrocode} - { \legacy_if:nF { measuring@ } { \@@_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} -% -% -% |\g_@@_row_style_tl| may contain several instructions of the form: -% -% \qquad |\@@_if_row_less_than:nn { number } { instructions }| -% -% \smallskip -% Then, |\g_@@_row_style_tl| will be inserted in all the cells of the array (and -% also in both components of a |\diagbox| in a cell of in a mono-row block). -% -% The test |\@@_if_row_less_then:nn| ensures that the instructions are inserted -% only if you are in a row which is (still) in the scope of that instructions -% (which depends on the value of the key |nb-rows| of |\RowStyle|). -% -% That test will be active even in an expandable context because -% |\@@_if_row_less_then:nn| is \emph{not} protected. -% -% |#1| is the first row \emph{after} the scope of the instructions in |#2| -% \begin{macrocode} -\cs_new:Npn \@@_if_row_less_than:nn #1 #2 - { \int_compare:nNnT { \c@iRow } < { #1 } { #2 } } -% \end{macrocode} -% -% \bigskip -% |\@@_put_in_row_style| will be used several times by |\RowStyle|. -% \begin{macrocode} -\cs_set_protected:Npn \@@_put_in_row_style:n #1 - { - \tl_gput_right:Nx \g_@@_row_style_tl - { -% \end{macrocode} -% Be careful, |\exp_not:N \@@_if_row_less_than:nn| can't be replaced by a -% protected version of |\@@_if_row_less_than:nn|. -% \begin{macrocode} - \exp_not:N - \@@_if_row_less_than:nn - { \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int } } -% \end{macrocode} -% The |\scan_stop:| is mandatory (for ex. for the case where |\rotate| is used -% in the argument of |\RowStyle|). -% \begin{macrocode} - { \exp_not:n { #1 } \scan_stop: } - } - } -\cs_generate_variant:Nn \@@_put_in_row_style:n { e } -% \end{macrocode} -% \medskip -% \begin{macrocode} -\keys_define:nn { NiceMatrix / RowStyle } - { - cell-space-top-limit .dim_set:N = \l_tmpa_dim , - cell-space-top-limit .value_required:n = true , - cell-space-bottom-limit .dim_set:N = \l_tmpb_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_@@_bold_row_style_bool , - bold .default:n = true , - 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 , - 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 - \tl_clear:N \l_@@_color_tl - \int_set_eq:NN \l_@@_key_nb_rows_int \c_one_int - \dim_zero:N \l_tmpa_dim - \dim_zero:N \l_tmpb_dim - \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:No| is \emph{fully expandable}. -% \begin{macrocode} - \@@_exp_color_arg:No \@@_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 > \c_one_int - { - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { - \@@_exp_color_arg:No \@@_rowcolor \l_tmpa_tl - { - \int_eval:n { \c@iRow + 1 } - - \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int - 1 } - } - } - } - } - \@@_put_in_row_style:n { \exp_not:n { #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 - { - \exp_args:Nx \@@_put_in_row_style:n - { - \tl_gput_right:Nn \exp_not:N \g_@@_cell_after_hook_tl - { -% \end{macrocode} -% It's not possible to chanage the following code by using |\dim_set_eq:NN| -% (because of expansion). -% \begin{macrocode} - \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 - { - \exp_args:Nx \@@_put_in_row_style:n - { - \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 - { - \@@_put_in_row_style:e - { - \mode_leave_vertical: - \@@_color:n { \l_@@_color_tl } - } - } -% \end{macrocode} -% |\l_@@_bold_row_style_bool| is the value of the key |bold|. -% \begin{macrocode} - \bool_if:NT \l_@@_bold_row_style_bool - { - \@@_put_in_row_style:n - { - \exp_not:n - { - \if_mode_math: - \c_math_toggle_token - \bfseries \boldmath - \c_math_toggle_token - \else: - \bfseries \boldmath - \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_if_zero:nTF \l_tmpa_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 { e n } -\cs_generate_variant:Nn \@@_add_to_colors_seq:nn { e e } -% \end{macrocode} -% -% \bigskip -% The following command must be used within a |\pgfpicture|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_clip_with_rounded_corners: - { - \dim_compare:nNnT \l_@@_tab_rounded_corners_dim > \c_zero_dim - { -% \end{macrocode} -% The TeX group is for |\pgfsetcornersarced| (whose scope is the TeX scope). -% \begin{macrocode} - \group_begin: - \pgfsetcornersarced - { - \pgfpoint - { \l_@@_tab_rounded_corners_dim } - { \l_@@_tab_rounded_corners_dim } - } -% \end{macrocode} -% 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 } - \group_end: -% \end{macrocode} -% The TeX group was for |\pgfsetcornersarced|. -% \begin{macrocode} - } - } -% \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} - \@@_clip_with_rounded_corners: - \seq_map_indexed_inline:Nn \g_@@_colors_seq - { - \int_compare:nNnTF { ##1 } = \c_one_int - { - \cs_set_eq:NN \@@_cartesian_path:n \@@_cartesian_path_nocolor:n - \use:c { g_@@_color _ 1 _tl } - \cs_set_eq:NN \@@_cartesian_path:n \@@_cartesian_path_normal:n - } - { - \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 curryfication. -% \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:No \pgfsetfillopacity \l_tmpa_tl } - \tl_if_empty:NTF \l_tmpb_tl - { \@declaredcolor } - { \use:e { \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 - { - \cs_set_nopar:Npn \l_@@_rows_tl { #1 } - \cs_set_nopar:Npn \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:en - { \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:en - { \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:en - { \tl_if_blank:nF { #1 } { [ #1 ] } { #2 } } - { \@@_rectanglecolor:nnn { #3 } { #4 } { \c_zero_dim } } - } - } -% \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:en - { \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 \c@iRow - { - \int_step_inline:nn \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 |\CodeBefore|) 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]|. -% -% In \pkg{nicematrix}, the commmand |\@@_rowcolors| appears as a special case of -% |\@@_rowlistcolors|. -% -% |#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 - \cs_set_nopar:Npn \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_eq:NN \l_@@_color_int \c_one_int - \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'' (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 } - { - \cs_set_nopar:Npn \l_tmpa_tl { ##1 } - \tl_if_in:NnTF \l_tmpa_tl { - } - { \@@_cut_on_hyphen:w ##1 \q_stop } - { \tl_set:No \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 - \int_set:Nn \l_@@_color_int - { \bool_if:NTF \l_@@_rowcolors_restart_bool 1 \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:No \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:ee - { \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 more general command |\rowlistcolors|. The last argument, which is a -% optional argument between square brackets is provided by curryfication. -% \begin{macrocode} -\NewDocumentCommand \@@_rowcolors { O { } m m m } - { \@@_rowlistcolors [ #1 ] { #2 } { { #3 } , { #4 } } } -% \end{macrocode} -% The braces around |#3| and |#4| are mandatory. -% -% \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 - { - \int_if_zero:nTF { #4 } - \prg_return_false: - { - \int_compare:nNnTF { #2 } > \c@jCol - \prg_return_false: - \prg_return_true: - } - } -% \end{macrocode} -% -% \bigskip -% The following command return |true| when the block intersects the row -% |\l_tmpa_int|. -% \begin{macrocode} -\prg_new_conditional:Nnn \@@_intersect_our_row:nnnnn p - { - \int_compare:nNnTF { #1 } > \l_tmpa_int - \prg_return_false: - { - \int_compare:nNnTF \l_tmpa_int > { #3 } - \prg_return_false: - \prg_return_true: - } - } -% \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_normal:n #1 - { - \dim_compare:nNnTF { #1 } = \c_zero_dim - { - \bool_if:NTF - \@@_nocolor_used_bool - \@@_cartesian_path_normal_ii: - { - \seq_if_empty:NTF \l_@@_corners_cells_seq - { \@@_cartesian_path_normal_i:n { #1 } } - \@@_cartesian_path_normal_ii: - } - } - { \@@_cartesian_path_normal_i:n { #1 } } - } -% \end{macrocode} -% -% -% \bigskip -% First, the situation where is a rectangular zone of cells will be colored as a -% whole (in the instructions of the resulting \textsc{pdf}). The argument is the -% radius of the corners. -% \begin{macrocode} -\cs_new_protected:Npn \@@_cartesian_path_normal_i:n #1 - { - \pgfsetcornersarced { \pgfpoint { #1 } { #1 } } -% \end{macrocode} -% We begin the loop over the columns. -% \begin{macrocode} - \clist_map_inline:Nn \l_@@_cols_tl - { - \cs_set_nopar:Npn \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:NTF \l_tmpa_tl - { \cs_set_nopar:Npn \l_tmpa_tl { 1 } } - { - \tl_if_eq:NNT \l_tmpa_tl \c_@@_star_tl - { \cs_set_nopar:Npn \l_tmpa_tl { 1 } } - } - \tl_if_empty:NTF \l_tmpb_tl - { \tl_set:No \l_tmpb_tl { \int_use:N \c@jCol } } - { - \tl_if_eq:NNT \l_tmpb_tl \c_@@_star_tl - { \tl_set:No \l_tmpb_tl { \int_use:N \c@jCol } } - } - \int_compare:nNnT \l_tmpb_tl > \g_@@_col_total_int - { \tl_set:No \l_tmpb_tl { \int_use:N \g_@@_col_total_int } } -% \end{macrocode} -% |\l_@@_tmpc_tl| will contain the number of column. -% \begin{macrocode} - \tl_set_eq:NN \l_@@_tmpc_tl \l_tmpa_tl - \@@_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 - { - \cs_set_nopar:Npn \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:NTF \l_tmpa_tl - { \cs_set_nopar:Npn \l_tmpa_tl { 1 } } - { - \tl_if_eq:NNT \l_tmpa_tl \c_@@_star_tl - { \cs_set_nopar:Npn \l_tmpa_tl { 1 } } - } - \tl_if_empty:NTF \l_tmpb_tl - { \tl_set:No \l_tmpb_tl { \int_use:N \c@iRow } } - { - \tl_if_eq:NNT \l_tmpb_tl \c_@@_star_tl - { \tl_set:No \l_tmpb_tl { \int_use:N \c@iRow } } - } - \int_compare:nNnT \l_tmpb_tl > \g_@@_row_total_int - { \tl_set:No \l_tmpb_tl { \int_use:N \g_@@_row_total_int } } -% \end{macrocode} -% Now, the numbers of both rows are in |\l_tmpa_tl| and |\l_tmpb_tl|. -% \begin{macrocode} - \cs_if_exist:cF - { @@ _ \l_tmpa_tl _ \l_@@_tmpc_tl _ nocolor } - { - \@@_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 } - \pgfpathrectanglecorners - { \pgfpoint \l_@@_tmpc_dim \l_@@_tmpd_dim } - { \pgfpoint \l_tmpa_dim \l_tmpb_dim } - } - } - } - } -% \end{macrocode} -% -% -% Now, the case where the cells will be colored cell by cell (it's mandatory for -% example if the key |corners| is used). -% \begin{macrocode} -\cs_new_protected:Npn \@@_cartesian_path_normal_ii: - { - \@@_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 - { - \@@_qpoint:n { col - ##1 } - \int_compare:nNnTF \l_@@_first_col_int = { ##1 } - { \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 { ##1 + 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 - { - \seq_if_in:NnF \l_@@_corners_cells_seq - { ####1 - ##1 } - { - \@@_qpoint:n { row - \int_eval:n { ####1 + 1 } } - \dim_set:Nn \l_tmpb_dim { \pgf@y + 0.5 \arrayrulewidth } - \@@_qpoint:n { row - ####1 } - \dim_set:Nn \l_@@_tmpd_dim { \pgf@y + 0.5 \arrayrulewidth } - \cs_if_exist:cF - { @@ _ ####1 _ ##1 _ nocolor } - { - \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 \c_zero_dim } -% \end{macrocode} -% -% -% \bigskip -% Despite its name, the following command does not create a PGF path. It -% declares as colored by the ``empty color'' all the cells in what would be the -% path. Hence, the other coloring instructions of \pkg{nicematrix} won't put -% color in those cells. -% the -% \begin{macrocode} -\cs_new_protected:Npn \@@_cartesian_path_nocolor:n #1 - { - \bool_set_true:N \@@_nocolor_used_bool - \@@_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_@@_rows_tl - { - \clist_map_inline:Nn \l_@@_cols_tl - { \cs_set:cpn { @@ _ ##1 _ ####1 _ nocolor } { } } - } - } -% \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 - { - \cs_set_nopar:Npn \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:o \l_tmpa_tl } - { \str_if_eq_p:on \l_tmpa_tl { * } } - { \cs_set_nopar:Npn \l_tmpa_tl { 1 } } - \bool_lazy_or:nnT - { \tl_if_blank_p:o \l_tmpb_tl } - { \str_if_eq_p:on \l_tmpb_tl { * } } - { \tl_set:No \l_tmpb_tl { \int_use:N #2 } } - \int_compare:nNnT \l_tmpb_tl > #2 - { \tl_set:No \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 |color-inside|, the following command will -% be linked to |\cellcolor| in the tabular. -% \begin{macrocode} -\NewDocumentCommand \@@_cellcolor_tabular { O { } m } - { - \@@_test_color_inside: - \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 |color-inside|, the following command will -% be linked to |\rowcolor| in the tabular. -% \begin{macrocode} -\NewDocumentCommand \@@_rowcolor_tabular { O { } m } - { - \@@_test_color_inside: - \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 -% When the user uses the key |color-inside|, the following command will -% be linked to |\rowcolors| in the tabular. The last argument (an optional -% argument between square brackets is taken by curryfication). -% \begin{macrocode} -\NewDocumentCommand { \@@_rowcolors_tabular } { O { } m m } - { \@@_rowlistcolors_tabular [ #1 ] { { #2 } , { #3 } } } -% \end{macrocode} -% The braces around |#2| and |#3| are mandatory. -% -% \bigskip -% When the user uses the key |color-inside|, the following command will -% be linked to |\rowlistcolors| in the tabular. -% \begin{macrocode} -\NewDocumentCommand { \@@_rowlistcolors_tabular } { O { } m O { } } - { - \@@_test_color_inside: - \peek_remove_spaces:n - { \@@_rowlistcolors_tabular:nnn { #1 } { #2 } { #3 } } - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_rowlistcolors_tabular:nnn #1 #2 #3 - { -% \end{macrocode} -% A use of |\rowlistcolors| in the tabular erases the instructions -% |\rowlistcolors| which are in force. However, it's possible to put \emph{several} -% instructions |\rowlistcolors| in the same row of a tabular: it may be useful -% when those instructions |\rowlistcolors| concerns different columns of the -% tabular (thanks to the key |cols| of |\rowlistcolors|). That's why we store -% the different instructions |\rowlistcolors| which are in force in a sequence -% |\g_@@_rowlistcolors_seq|. Now, we will filter that sequence to keep only the -% elements which have been issued on the actual row. We will store the elements -% to keep in the |\g_tmpa_seq|. -% \begin{macrocode} - \seq_gclear:N \g_tmpa_seq - \seq_map_inline:Nn \g_@@_rowlistcolors_seq - { \@@_rowlistcolors_tabular_i:nnnn ##1 } - \seq_gset_eq:NN \g_@@_rowlistcolors_seq \g_tmpa_seq -% \end{macrocode} -% Now, we add to the sequence |\g_@@_rowlistcolors_seq| (which is the list of -% the commands |\rowlistcolors| which are in force) the current instruction -% |\rowlistcolors|. -% \begin{macrocode} - \seq_gput_right:Nx \g_@@_rowlistcolors_seq - { - { \int_use:N \c@iRow } - { \exp_not:n { #1 } } - { \exp_not:n { #2 } } - { restart , cols = \int_use:N \c@jCol - , \exp_not:n { #3 } } - } - } -% \end{macrocode} -% -% -% \bigskip -% The following command will be applied to each component of -% |\g_@@_rowlistcolors_seq|. Each component of that sequence is a kind of 4-uple -% of the form |{#1}{#2}{#3}{#4}|. -% -% |#1| is the number of the row where the command |\rowlistcolors| has been -% issued. -% -% |#2| is the colorimetric space (optional argument of the |\rowlistcolors|). -% -% |#3| is the list of colors (mandatory argument of |\rowlistcolors|). -% -% |#4| is the list of \textsl{key=value} pairs (last optional argument of -% |\rowlistcolors|). -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_rowlistcolors_tabular_i:nnnn #1 #2 #3 #4 - { - \int_compare:nNnTF { #1 } = \c@iRow -% \end{macrocode} -% We (temporary) keep in memory in |\g_tmpa_seq| the instructions which will -% still be in force after the current instruction (because they have been issued -% in the same row of the tabular). -% \begin{macrocode} - { \seq_gput_right:Nn \g_tmpa_seq { { #1 } { #2 } { #3 } { #4 } } } - { - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { - \@@_rowlistcolors - [ \exp_not:n { #2 } ] - { #1 - \int_eval:n { \c@iRow - 1 } } - { \exp_not:n { #3 } } - [ \exp_not:n { #4 } ] - } - } - } -% \end{macrocode} -% -% \bigskip -% The following command will be used at the end of the tabular, just before the -% execution of the |\g_@@_pre_code_before_tl|. It clears the sequence -% |\g_@@_rowlistcolors_seq| of all the commands |\rowlistcolors| which are -% (still) in force. -% \begin{macrocode} -\cs_new_protected:Npn \@@_clear_rowlistcolors_seq: - { - \seq_map_inline:Nn \g_@@_rowlistcolors_seq - { \@@_rowlistcolors_tabular_ii:nnnn ##1 } - \seq_gclear:N \g_@@_rowlistcolors_seq - } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\cs_new_protected:Npn \@@_rowlistcolors_tabular_ii:nnnn #1 #2 #3 #4 - { - \tl_gput_right:Nn \g_@@_pre_code_before_tl - { \@@_rowlistcolors [ #2 ] { #1 } { #3 } [ #4 ] } - } -% \end{macrocode} -% The first mandatory argument of the command |\@@_rowlistcolors| which is -% writtent in the pre-|\CodeBefore| is of the form |i|: it means that the -% command must be applied to all the rows from the row~$i$ until the end of the -% tabular. -% -% \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 -% \begin{macrocode} -\hook_gput_code:nnn { begindocument } { . } - { - \IfPackageLoadedTF { colortbl } - { - \cs_set_eq:NN \@@_old_cellcolor \cellcolor - \cs_set_eq:NN \@@_old_rowcolor \rowcolor - \cs_new_protected:Npn \@@_revert_colortbl: - { - \hook_gput_code:nnn { env / tabular / begin } { . } - { - \cs_set_eq:NN \cellcolor \@@_old_cellcolor - \cs_set_eq:NN \rowcolor \@@_old_rowcolor - } - } - } - { \cs_new_protected:Npn \@@_revert_colortbl: { } } - } -% \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_if_zero:nTF \l_@@_first_col_int - { \@@_OnlyMainNiceMatrix_i:n { #1 } } - { - \int_if_zero:nTF \c@jCol - { - \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_if_zero:nF \c@iRow - { - \int_compare:nNnF \c@iRow = \l_@@_last_row_int - { - \int_compare:nNnT \c@jCol > \c_zero_int - { \bool_if:NF \l_@@_in_last_col_bool { #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 , - 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 , -% \end{macrocode} -% We want that, even when the rule has been defined with TikZ by the key |tikz|, -% the user has still the possibility to change the color of the rule with the key -% |color| (in the command |\Hline|, not in the key |tikz| of the command -% |\Hline|). The main use is, when the user has defined its own command -% |\MyDashedLine| by |\newcommand{\MyDashedRule}{\Hline[tikz=dashed]}|, to give -% the ability to write |\MyDashedRule[color=red]|. -% \begin{macrocode} - color .code:n = - \@@_set_CT@arc@:n { #1 } - \tl_set:Nn \l_@@_rule_color_tl { #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 .code:n = - \IfPackageLoadedTF { tikz } - { \clist_put_right:Nn \l_@@_tikz_rule_tl { #1 } } - { \@@_error:n { tikz~without~tikz } } , - tikz .value_required:n = true , - 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_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: - { -% \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:No \l_tmpb_tl { \int_use: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_if_zero:nT \l_@@_local_start_int -% \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 > \c_zero_int - { - \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 > \c_zero_int - { - \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 = \c_one_int - { \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: - { - \tl_clear:N \l_@@_tikz_rule_tl - \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 > \c_one_int } - { \cs_if_exist_p:N \CT@drsc@ } - { ! \tl_if_blank_p:o \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|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_vline_v: - { - \begin {tikzpicture } - % added 2023/09/25 -% \end{macrocode} -% By default, the color defined by |\arrayrulecolor| or by |rules/color| will be -% used, but it's still possible to change the color by using the key |color| or, -% of course, the key |color| inside the key |tikz| (that is to say the key -% |color| provided by \textsc{pgf}. -% \begin{macrocode} - \CT@arc@ - \tl_if_empty:NF \l_@@_rule_color_tl - { \tl_put_right:Nx \l_@@_tikz_rule_tl { , color = \l_@@_rule_color_tl } } - \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:No \tikzset \l_@@_tikz_rule_tl - \use:e { \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_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool 2 1 } - { - \bool_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool - \c@jCol - { \int_eval:n { \c@jCol + 1 } } - } - { - \tl_if_eq:NNF \l_@@_vlines_clist \c_@@_all_tl - { \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:No \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_if_zero:nT \l_@@_local_start_int -% \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 > \c_zero_int - { - \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 > \c_zero_int - { - \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 = \c_one_int - { \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: - { - \tl_clear:N \l_@@_tikz_rule_tl - \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 > \c_one_int } - { \cs_if_exist_p:N \CT@drsc@ } - { ! \tl_if_blank_p:o \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 = \c_one_int - { - \dim_sub:Nn \l_@@_x_initial_dim \l_@@_left_margin_dim - \bool_if:NF \g_@@_delims_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:NF \g_@@_delims_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 } - % added 2023/09/25 -% \end{macrocode} -% By default, the color defined by |\arrayrulecolor| or by |rules/color| will be -% used, but it's still possible to change the color by using the key |color| or, -% of course, the key |color| inside the key |tikz| (that is to say the key -% |color| provided by \textsc{pgf}. -% \begin{macrocode} - \CT@arc@ - \tl_if_empty:NF \l_@@_rule_color_tl - { \tl_put_right:Nx \l_@@_tikz_rule_tl { , color = \l_@@_rule_color_tl } } - \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:No \tikzset \l_@@_tikz_rule_tl - \use:e { \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_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool 2 1 } - { - \bool_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool - \c@iRow - { \int_eval:n { \c@iRow + 1 } } - } - { - \tl_if_eq:NNF \l_@@_hlines_clist \c_@@_all_tl - { \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 - { \@@_collect_options:n { \@@_Hline_iv:nn { #1 } } } -% \end{macrocode} -% -% -% \begin{macrocode} -\cs_set:Npn \@@_Hline_iv:nn #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 -% 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 - \tl_clear_new:N \l_@@_other_keys_tl - \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:No \@@_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 \l_@@_dotted_rule_bool - { - \int_compare:nNnT \l_@@_multiplicity_int > \c_one_int - { \@@_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:ne { Forbidden~letter } \l_@@_letter_str } - { -% \end{macrocode} -% During the analyse of the preamble provided by the final user, our automaton, -% for the letter corresponding at the custom line, will directly use the -% following command that you define in the main hash table of TeX. -% \begin{macrocode} - \cs_set:cpn { @@ _ \l_@@_letter_str } ##1 - { \@@_v_custom_line: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} -\tl_const:Nn \c_@@_forbidden_letters_tl { lcrpmbVX|()[]!@<> } -\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| (which is in |\Hline|). -% \begin{macrocode} - \cs_set:cpn { nicematrix - \l_@@_command_str } { \Hline [ #1 ] } - \seq_put_left:No \l_@@_custom_line_commands_seq \l_@@_command_str - } -% \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:No \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 - } - } - } -% \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_@@_array_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 - } - } - \@@_rec_preamble:n - } -% \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 - { - \int_compare:nNnT \l_tmpa_tl > { #1 } - { - \int_compare:nNnT \l_tmpa_tl < { #3 + 1 } - { - \int_compare:nNnT \l_tmpb_tl > { #2 - 1 } - { - \int_compare:nNnT \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 - { - \int_compare:nNnT \l_tmpa_tl > { #1 - 1 } - { - \int_compare:nNnT \l_tmpa_tl < { #3 + 1 } - { - \int_compare:nNnT \l_tmpb_tl > { #2 } - { - \int_compare:nNnT \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 - { - \int_compare:nNnT \l_tmpb_tl > { #2 - 1 } - { - \int_compare:nNnT \l_tmpb_tl < { #4 + 1 } - { - \int_compare:nNnTF \l_tmpa_tl = { #1 } - { \bool_gset_false:N \g_tmpa_bool } - { - \int_compare:nNnT \l_tmpa_tl = { #3 + 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 - { - \int_compare:nNnT \l_tmpa_tl > { #1 - 1 } - { - \int_compare:nNnT \l_tmpa_tl < { #3 + 1 } - { - \int_compare:nNnTF \l_tmpb_tl = { #2 } - { \bool_gset_false:N \g_tmpa_bool } - { - \int_compare:nNnT \l_tmpb_tl = { #4 + 1 } - { \bool_gset_false:N \g_tmpa_bool } - } - } - } - } -% \end{macrocode} -% -% \bigskip -% \section{The empty corners} -% -% When the key |corners| is raised, the rules are not drawn in the corners; they -% are not colored and |\TikzEveryCell| does not apply. 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_set_protected:Npn \@@_test_if_cell_in_block:nnnnnnn #1 #2 #3 #4 #5 #6 #7 - { - \int_compare:nNnF { #3 } > { #1 } - { - \int_compare:nNnF { #1 } > { #5 } - { - \int_compare:nNnF { #4 } > { #2 } - { - \int_compare:nNnF { #2 } > { #6 } - { \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 } - { - % is \exp_args:NNe mandatory? - \exp_args:NNe \dim_set:Nn \l_@@_columns_width_dim - { - \use:c - { @@_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} - { - \legacy_if:nTF { measuring@ } -% \end{macrocode} -% If |{NiceMatrixBlock}| is used in an environment of \pkg{amsmath} such as -% |{align}|: cf. question 694957 on TeX StackExchange. The most important line -% in that case is the following one. -% \begin{macrocode} - { \int_gdecr:N \g_@@_NiceMatrixBlock_int } - { - \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 - } - } - \ignorespacesafterend - } -% \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} - \cs_set_nopar:Npn \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: - \cs_set_nopar:Npn \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} - \cs_set_nopar:Npn \l_@@_suffix_tl { - medium } - \@@_create_nodes: - \@@_computations_for_large_nodes: - \cs_set_nopar:Npn \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_eq:NN \l_@@_first_row_int \c_one_int - \int_set_eq:NN \l_@@_first_col_int \c_one_int -% \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_map_pairwise_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_block_str t , - t .value_forbidden:n = true , - T .code:n = \str_set:Nn \l_@@_vpos_block_str T , - T .value_forbidden:n = true , - b .code:n = \str_set:Nn \l_@@_vpos_block_str b , - b .value_forbidden:n = true , - B .code:n = \str_set:Nn \l_@@_vpos_block_str B , - B .value_forbidden:n = true , - color .code:n = - \@@_color:n { #1 } - \tl_set_rescan:Nnn - \l_@@_draw_tl - { \char_set_catcode_other:N ! } - { #1 } , - color .value_required:n = true , - respect-arraystretch .code:n = - \cs_set_eq:NN \@@_reset_arraystretch: \prg_do_nothing: , - respect-arraystretch .value_forbidden: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} -\cs_new_protected:Npn \@@_Block: { \@@_collect_options:n { \@@_Block_i: } } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\NewExpandableDocumentCommand \@@_Block_i: { m 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 been 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_ii:nnnnn \c_one_int \c_one_int } - { - \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 before the composition of the block -% and |#5| is the label (=content) 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 = \c_one_int - { - \tl_if_empty:NTF \l_@@_hpos_cell_tl - { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_c_str } - { \str_set:NV \l_@@_hpos_block_str \l_@@_hpos_cell_tl } - } - { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_c_str } -% \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 = \c_one_int - || - \int_compare_p:nNn \l_tmpb_int = \c_one_int - ) - && ! \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_bool - } - { \exp_args:Nee \@@_Block_iv:nnnnn } - { \exp_args:Nee \@@_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}) with |\@@_draw_blocks:| and -% above all |\@@_Block_v:nnnnnn| which will do the main job. -% -% |#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 potential math mode and before the composition of -% the block and |#5| is the label (=content) of the block. -% \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 } } - { \g_@@_row_style_tl \exp_not:n { ##1 } } - { \g_@@_row_style_tl \exp_not:n { ##2 } } - } - } - \box_gclear_new:c - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } -% \end{macrocode} -% Now, we will actually compose the content of the |\Block| in a TeX box. -% \emph{Be careful}: if after the construction of the box, the boolean -% |\g_@@_rotate_bool| is raised (which means that the command |\rotate| was -% present in the content of the |\Block|) we will rotate the box but also, -% maybe, change the position of the baseline! -% \begin{macrocode} - \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 } = \c_one_int \set@color } - { \@@_color:o \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 } = \c_one_int - { - \int_if_zero:nTF \c@iRow - \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 - } -% \end{macrocode} -% The following command will be no-op when |respect-arraystretch| is in force. -% \begin{macrocode} - \@@_reset_arraystretch: - \dim_zero:N \extrarowheight -% \end{macrocode} -% |#4| is the optional argument of the command |\Block|, provided with the -% syntax |<...>|. -% \begin{macrocode} - #4 -% \end{macrocode} -% We adjust |\l_@@_hpos_block_str| when |\rotate| has been used (in the cell -% where the command |\Block| is used but maybe in |#4|, |\RowStyle|, -% |code-for-first-row|, etc.). -% \begin{macrocode} - \@@_adjust_hpos_rotate: -% \end{macrocode} -% The boolean |\g_@@_rotate_bool| will be also considered \emph{after the composition -% of the box} (in order to rotate the box). -% -% \medskip -% Remind that we are in the command of composition of the box of the block. -% Previously, we have only done some tuning. Now, we will actually compose the -% content with a |{tabular}|, an |{array}| or a |{minipage}|. -% \begin{macrocode} - \bool_if:NTF \l_@@_tabular_bool - { - \bool_lazy_all:nTF - { - { \int_compare_p:nNn { #2 } = \c_one_int } -% \end{macrocode} -% Remind that, when the column has not a fixed width, the dimension -% |\l_@@_col_width_dim| has the conventional value of $-1$~cm. -% \begin{macrocode} - { ! \dim_compare_p:nNn \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}|), we -% use a |{minipage}|. -% \begin{macrocode} - { - \use:e - { - \exp_not:N \begin { minipage }% - [ \str_lowercase:V \l_@@_vpos_block_str ] - { \l_@@_col_width_dim } - \str_case:on \l_@@_hpos_block_str - { c \centering r \raggedleft l \raggedright } - } - #5 - \end { minipage } - } -% \end{macrocode} -% In the other cases, we use a |{tabular}|. -% \begin{macrocode} - { - \use:e - { - \exp_not:N \begin { tabular }% - [ \str_lowercase:V \l_@@_vpos_block_str ] - { @ { } \l_@@_hpos_block_str @ { } } - } - #5 - \end { tabular } - } - } -% \end{macrocode} -% If we are in a mathematical array (|\l_@@_tabular_bool| is |false|). The -% composition is always done with an |{array}| (never with a |{minipage}|). -% \begin{macrocode} - { - \c_math_toggle_token - \use:e - { - \exp_not:N \begin { array }% - [ \str_lowercase:V \l_@@_vpos_block_str ] - { @ { } \l_@@_hpos_block_str @ { } } - } - #5 - \end { array } - \c_math_toggle_token - } - } -% \end{macrocode} -% The box which will contain the content of the block has now been composed. -% -% \bigskip -% If there were |\rotate| (which raises |\g_@@_rotate_bool|) in the content of -% the |\Block|, we do a rotation of the box (and we also adjust the -% baseline the rotated box). -% \begin{macrocode} - \bool_if:NT \g_@@_rotate_bool \@@_rotate_box_of_block: -% \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 } = \c_one_int - { - \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 and if that block has no vertical option for the -% position\footnote{If the block has a key of a vertical position, that means -% that it has to be put in a vertical space determined by the \emph{others} -% cells of the row. Therefore there is no point creating space here. Moreover, -% that would lead to problems when a multi-row block with a position key such as -% |b| or |B|.}, we take into account the height and the depth of that block for the -% height and the depth of the row. -% \begin{macrocode} - \str_if_eq:VnT \l_@@_vpos_block_str { c } - { - \int_compare:nNnT { #1 } = \c_one_int - { - \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 , -% \end{macrocode} -% Now, we put a key for the vertical alignment. -% \begin{macrocode} - \bool_if:NT \g_@@_rotate_bool - { - \bool_if:NTF \g_@@_rotate_c_bool - { v-center } - { \int_compare:nNnT \c@iRow = \l_@@_last_row_int T } - } - - } - { - \box_use_drop:c - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } - } - } - \bool_set_false:N \g_@@_rotate_c_bool - } -% \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new:Npn \@@_adjust_hpos_rotate: - { - \bool_if:NT \g_@@_rotate_bool - { - \str_set:Nx \l_@@_hpos_block_str - { - \bool_if:NTF \g_@@_rotate_c_bool - { c } - { - \str_case:onF \l_@@_vpos_block_str - { b l B l t r T r } - { \int_compare:nNnTF \c@iRow = \l_@@_last_row_int r l } - } - } - } - } -% \end{macrocode} -% -% \bigskip -% Despite its name the following command rotates the box of the block \emph{but -% also does vertical adjustement of the baseline of the block}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_rotate_box_of_block: - { - \box_grotate:cn - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } - { 90 } - \int_compare:nNnT \c@iRow = \l_@@_last_row_int - { - \vbox_gset_top:cn - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } - { - \skip_vertical:n { 0.8 ex } - \box_use:c - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } - } - } - \bool_if:NT \g_@@_rotate_c_bool - { - \hbox_gset:cn - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } - { - \c_math_toggle_token - \vcenter - { - \box_use:c - { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box } - } - \c_math_toggle_token - } - } - } -% \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 (cf. |\@@_draw_blocks:| and -% above all |\@@_Block_v:nnnnnn|). -% -% |#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 before the composition of the block -% and |#5| is the label (=content) of the block. -% \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_@@_tabular_bool - { - \group_begin: -% \end{macrocode} -% The following command will be no-op when |respect-arraystretch| is in force. -% \begin{macrocode} - \@@_reset_arraystretch: - \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} - \use:e - { - \exp_not:N \begin { tabular } [ \l_@@_vpos_block_str ] - { @ { } \l_@@_hpos_block_str @ { } } - } - #5 - \end { tabular } - } - \group_end: - } -% \end{macrocode} -% When we are \emph{not} in an environments |{NiceTabular}| (or similar). -% \begin{macrocode} - { - \group_begin: -% \end{macrocode} -% The following will be no-op when |respect-arraystretch| is in force. -% \begin{macrocode} - \@@_reset_arraystretch: - \exp_not:n - { - \dim_zero:N \extrarowheight - #4 - \c_math_toggle_token - \use:e - { - \exp_not:N \begin { array } [ \l_@@_vpos_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 , - opacity .tl_set:N = \l_@@_opacity_tl , - opacity .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 } , - 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 , -% \end{macrocode} -% Some keys have not a property |.value_required:n| (or similar) because they -% are in |FirstPass|. -% \begin{macrocode} - l .code:n = \str_set:Nn \l_@@_hpos_block_str l , - r .code:n = \str_set:Nn \l_@@_hpos_block_str r , - c .code:n = \str_set:Nn \l_@@_hpos_block_str c , - L .code:n = \str_set:Nn \l_@@_hpos_block_str l - \bool_set_true:N \l_@@_hpos_of_block_cap_bool , - R .code:n = \str_set:Nn \l_@@_hpos_block_str r - \bool_set_true:N \l_@@_hpos_of_block_cap_bool , - C .code:n = \str_set:Nn \l_@@_hpos_block_str c - \bool_set_true:N \l_@@_hpos_of_block_cap_bool , - t .code:n = \str_set:Nn \l_@@_vpos_block_str t , - T .code:n = \str_set:Nn \l_@@_vpos_block_str T , - b .code:n = \str_set:Nn \l_@@_vpos_block_str b , - B .code:n = \str_set:Nn \l_@@_vpos_block_str B , - v-center .code:n = \str_set:Nn \l_@@_vpos_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 .code:n = - \cs_set_eq:NN \@@_reset_arraystretch: \prg_do_nothing: , - respect-arraystretch .value_forbidden: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 - { - \bool_lazy_and:nnTF - \l_@@_preamble_bool - { - \int_compare_p:n - { \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 -% The following command |\@@_Block_v:nnnnnn| will actually draw the block. -% |#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_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 - { - \bool_lazy_and:nnF \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} - \tl_if_empty:NF \l_@@_draw_tl - { - \bool_lazy_or:nnT \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 } } % #5 are the options - { #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_if_empty:NF \l_@@_opacity_tl - { - \tl_if_head_eq_meaning:nNTF \l_@@_fill_tl [ - { - \tl_set:Nx \l_@@_fill_tl - { - [ opacity = \l_@@_opacity_tl , - \tl_tail:o \l_@@_fill_tl - } - } - { - \tl_set:Nx \l_@@_fill_tl - { [ opacity = \l_@@_opacity_tl ] { \l_@@_fill_tl } } - } - } - \tl_gput_right:Nx \g_@@_pre_code_before_tl - { - \exp_not:N \roundedrectanglecolor - \exp_args:No \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:on \l_@@_vpos_block_str { c } } - { \str_if_eq_p:on \l_@@_vpos_block_str { T } } - { \str_if_eq_p:on \l_@@_vpos_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_if_zero:nT { #2 } { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_r_str } -% \end{macrocode} -% If we are in the last column, we must put the block as if it was with the key~|l|. -% \begin{macrocode} - \bool_if:nT \g_@@_last_col_found_bool - { - \int_compare:nNnT { #2 } = \g_@@_col_total_int - { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_l_str } - } -% \end{macrocode} -% |\l_tmpa_tl| will contain the anchor of the \textsc{pgf} node which will be used. -% \begin{macrocode} - \tl_set:Nx \l_tmpa_tl - { - \str_case:on \l_@@_vpos_block_str - { - c { - \str_case:on \l_@@_hpos_block_str - { - c { center } - l { west } - r { east } - } - - } - T { - \str_case:on \l_@@_hpos_block_str - { - c { north } - l { north~west } - r { north~east } - } - - } - B { - \str_case:on \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 = \c_zero_dim - } - \pgfnode - { rectangle } - { \l_tmpa_tl } - { \box_use_drop:N \l_@@_cell_box } { } { } - } -% \end{macrocode} -% End of the case when |\l_@@_vpos_block_str| is equal to |c|, |T| or |B|. -% Now, the other cases. -% \begin{macrocode} - { -% \end{macrocode} -% -% \begin{macrocode} - \pgfextracty \l_tmpa_dim - { - \@@_qpoint:n - { - row - \str_if_eq:onTF \l_@@_vpos_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:on \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:on \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} - \tl_if_eq:NNTF \l_@@_draw_tl \c_@@_default_tl - { \CT@arc@ } - { \@@_color:o \l_@@_draw_tl } - } - \pgfsetcornersarced - { - \pgfpoint - { \l_@@_rounded_corners_dim } - { \l_@@_rounded_corners_dim } - } - \@@_cut_on_hyphen:w #2 \q_stop - \int_compare:nNnF \l_tmpa_tl > \c@iRow - { - \int_compare:nNnF \l_tmpb_tl > \c@jCol - { - \@@_qpoint:n { row - \l_tmpa_tl } - \dim_set_eq:NN \l_tmpb_dim \pgf@y - \@@_qpoint:n { col - \l_tmpb_tl } - \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x - \@@_cut_on_hyphen:w #3 \q_stop - \int_compare:nNnT \l_tmpa_tl > \c@iRow - { \tl_set:No \l_tmpa_tl { \int_use:N \c@iRow } } - \int_compare:nNnT \l_tmpb_tl > \c@jCol - { \tl_set:No \l_tmpb_tl { \int_use:N \c@jCol } } - \@@_qpoint:n { row - \int_eval:n { \l_tmpa_tl + 1 } } - \dim_set_eq:NN \l_tmpa_dim \pgf@y - \@@_qpoint:n { col - \int_eval:n { \l_tmpb_tl + 1 } } - \dim_set_eq:NN \l_@@_tmpd_dim \pgf@x - \pgfsetlinewidth { 1.1 \l_@@_line_width_dim } - \pgfpathrectanglecorners - { \pgfpoint \l_@@_tmpc_dim \l_tmpb_dim } - { \pgfpoint \l_@@_tmpd_dim \l_tmpa_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 .code:n = - \exp_args:Ne \tl_if_empty:nF { #1 } { \tl_set:Nn \l_@@_draw_tl { #1 } } , - 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:e - { - \@@_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 - } - } - } - } -\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:e - { - \@@_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 - } - } - } - } -% \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:e { \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:e { \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. However, among -% those keys, you have added in \pkg{nicematrix} a special key |offset| (an -% offset for the rectangle of the block). That's why we have to extract that key -% first. -% \begin{macrocode} -\cs_new_protected:Npn \@@_block_tikz:nnnnn #1 #2 #3 #4 #5 - { - \begin { tikzpicture } - \@@_clip_with_rounded_corners: - \clist_map_inline:nn { #5 } - { - \keys_set_known:nnN { NiceMatrix / SpecialOffset } { ##1 } \l_tmpa_tl - \use:e { \exp_not:N \path [ \l_tmpa_tl ] } - ( - [ - xshift = \dim_use:N \l_@@_offset_dim , - yshift = - \dim_use:N \l_@@_offset_dim - ] - #1 -| #2 - ) - rectangle - ( - [ - xshift = - \dim_use:N \l_@@_offset_dim , - yshift = \dim_use:N \l_@@_offset_dim - ] - \int_eval:n { #3 + 1 } -| \int_eval:n { #4 + 1 } - ) ; - } - \end { tikzpicture } - } -\cs_generate_variant:Nn \@@_block_tikz:nnnnn { n n n n V } -% \end{macrocode} -% -% \medskip -% \begin{macrocode} -\keys_define:nn { NiceMatrix / SpecialOffset } - { offset .dim_set:N = \l_@@_offset_dim } -% \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 some keys and pass the other keys to the environment -% |{NiceArrayWithDelims}|. -% \begin{macrocode} -\keys_define:nn { NiceMatrix / Auto } - { - columns-type .tl_set:N = \l_@@_columns_type_tl , - 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 , - rounded-corners .dim_set:N = \l_@@_tab_rounded_corners_dim , - rounded-corners .default:n = 4 pt - } -% \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: - \keys_set_known:nnN { NiceMatrix / Auto } { #6 } \l_tmpa_tl - \use:e - { - \exp_not:N \begin { NiceArrayWithDelims } { #1 } { #2 } - { * { #4 } { \exp_not:o \l_@@_columns_type_tl } } - [ \exp_not:o \l_tmpa_tl ] - } - \int_if_zero:nT \l_@@_first_row_int - { - \int_if_zero:nT \l_@@_first_col_int { & } - \prg_replicate:nn { #4 - 1 } { & } - \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\ - } - \prg_replicate:nn { #3 } - { - \int_if_zero:nT \l_@@_first_col_int { & } -% \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_if_zero:nT \l_@@_first_col_int { & } - \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_true:N \g_@@_delims_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_false:N \g_@@_delims_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 } -% \end{macrocode} -% |\g_@@_row_style_tl| contains several instructions of the form: -% -% \qquad |\@@_if_row_less_than:nn { number } { instructions }| -% -% The command |\@@_if_row_less:nn| is fully expandable and, thus, the -% instructions will be inserted in the |\g_@@_pre_code_after_tl| only if -% |\diagbox| is used in a row which is the scope of that chunck of instructions. -% \begin{macrocode} - { \g_@@_row_style_tl \exp_not:n { #1 } } - { \g_@@_row_style_tl \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: #5 \@@_math_toggle: - \end { minipage } - } - { } - { } - \endpgfscope - \pgftransformshift { \pgfpoint \l_@@_tmpd_dim \l_tmpa_dim } - \pgfnode { rectangle } { north~east } - { - \begin { minipage } { 20 cm } - \raggedleft - \@@_math_toggle: #6 \@@_math_toggle: - \end { minipage } - } - { } - { } - \endpgfpicture - } -% \end{macrocode} -% -% -% -% -% \bigskip -% \section{The keyword \textbackslash CodeAfter} -% -% -% -% \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:o \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 , - 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 } { . } - { - \cs_set_nopar:Npn \l_@@_argspec_tl { m m m m O { } E { _ ^ } { { } { } } } - \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl - \exp_args:NNo \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 - { - \cs_set_nopar:Npn \l_@@_first_i_tl { #1 } - \cs_set_nopar:Npn \l_@@_first_j_tl { #2 } - \cs_set_nopar:Npn \l_@@_last_i_tl { #3 } - \cs_set_nopar:Npn \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 } - \int_compare:nNnT \l_@@_first_i_tl = \l_@@_last_i_tl - { \cs_set_nopar:Npn \arraystretch { 1 } } - \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 - } - } - \@@_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 } } - \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@:o \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 \c_@@_all_tl - { \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 } > \c_zero_int } - { - \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 \c_@@_all_tl - { \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 } > \c_zero_int } - { - \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:o \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:o \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 } - { - \vtop - { - \group_begin: - \everycr { } - \halign - { - \hfil ## \hfil \crcr - \@@_math_toggle: #1 \@@_math_toggle: \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 - { - \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: #1 \@@_math_toggle: \cr - } - } - \group_end: - } - { } - { } - } -% \end{macrocode} -% -% \bigskip -% \section{The command TikzEveryCell} -% -% \begin{macrocode} -\bool_new:N \l_@@_not_empty_bool -\bool_new:N \l_@@_empty_bool - -\keys_define:nn { NiceMatrix / TikzEveryCell } - { - not-empty .code:n = - \bool_lazy_or:nnTF - \l_@@_in_code_after_bool - \g_@@_recreate_cell_nodes_bool - { \bool_set_true:N \l_@@_not_empty_bool } - { \@@_error:n { detection~of~empty~cells } } , - not-empty .value_forbidden:n = true , - empty .code:n = - \bool_lazy_or:nnTF - \l_@@_in_code_after_bool - \g_@@_recreate_cell_nodes_bool - { \bool_set_true:N \l_@@_empty_bool } - { \@@_error:n { detection~of~empty~cells } } , - empty .value_forbidden:n = true , - unknown .code:n = \@@_error:n { Unknown~key~for~TikzEveryCell } - } - - -\NewDocumentCommand { \@@_TikzEveryCell } { O { } m } - { - \IfPackageLoadedTF { tikz } - { - \group_begin: - \keys_set:nn { NiceMatrix / TikzEveryCell } { #1 } -% \end{macrocode} -% The inner pair of braces in the following line is mandatory because, the last -% argument of |\@@_tikz:nnnnn| is \emph{a list of lists} of TikZ keys. -% \begin{macrocode} - \tl_set:Nn \l_tmpa_tl { { #2 } } - \seq_map_inline:Nn \g_@@_pos_of_blocks_seq - { \@@_for_a_block:nnnnn ##1 } - \@@_all_the_cells: - \group_end: - } - { \@@_error:n { TikzEveryCell~without~tikz } } - } - -\tl_new:N \@@_i_tl -\tl_new:N \@@_j_tl - -\cs_new_protected:Nn \@@_all_the_cells: - { - \int_step_variable:nNn { \int_use:c { c@iRow } } \@@_i_tl - { - \int_step_variable:nNn { \int_use:c { c@jCol } } \@@_j_tl - { - \cs_if_exist:cF { cell - \@@_i_tl - \@@_j_tl } - { - \exp_args:NNe \seq_if_in:NnF \l_@@_corners_cells_seq - { \@@_i_tl - \@@_j_tl } - { - \bool_set_false:N \l_tmpa_bool - \cs_if_exist:cTF - { pgf @ sh @ ns @ \@@_env: - \@@_i_tl - \@@_j_tl } - { - \bool_if:NF \l_@@_empty_bool - { \bool_set_true:N \l_tmpa_bool } - } - { - \bool_if:NF \l_@@_not_empty_bool - { \bool_set_true:N \l_tmpa_bool } - } - \bool_if:NT \l_tmpa_bool - { - \@@_block_tikz:nnnnV - \@@_i_tl \@@_j_tl \@@_i_tl \@@_j_tl \l_tmpa_tl - } - } - } - } - } - } - -\cs_new_protected:Nn \@@_for_a_block:nnnnn - { - \bool_if:NF \l_@@_empty_bool - { - \@@_block_tikz:nnnnV - { #1 } { #2 } { #3 } { #4 } \l_tmpa_tl - } - \@@_mark_cells_of_block:nnnn { #1 } { #2 } { #3 } { #4 } - } - -\cs_new_protected:Nn \@@_mark_cells_of_block:nnnn - { - \int_step_inline:nnn { #1 } { #3 } - { - \int_step_inline:nnn { #2 } { #4 } - { \cs_set:cpn { cell - ##1 - ####1 } { } } - } - } -% \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 \g_@@_footnotehyper_bool -% \end{macrocode} -% -% \medskip -% The boolean |\g_@@_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 \g_@@_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~<return>. - } - { - 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 = \g_@@_messages_for_Overleaf_bool , - footnote .bool_set:N = \g_@@_footnote_bool , - footnotehyper .bool_set:N = \g_@@_footnotehyper_bool , - no-test-for-array .bool_set:N = \g_@@_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 \g_@@_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} - \IfClassLoadedTF { beamer } - { \bool_set_false:N \g_@@_footnote_bool } - { - \IfPackageLoadedTF { footnotehyper } - { \@@_error:n { footnote~with~footnotehyper~package } } - { \usepackage { footnote } } - } - } -% \end{macrocode} -% -% \begin{macrocode} -\bool_if:NT \g_@@_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 \g_@@_footnote_bool } - { - \IfPackageLoadedTF { footnote } - { \@@_error:n { footnotehyper~with~footnote~package } } - { \usepackage { footnotehyper } } - } - \bool_set_true:N \g_@@_footnote_bool - } -% \end{macrocode} -% The flag |\g_@@_footnote_bool| is raised and so, we will only have to test -% |\g_@@_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 \g_@@_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~<return>. } - } -% \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:NoTF| 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:NoTF \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 } } - } - } - } - { \@@_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:oF \g_@@_HVdotsfor_lines_tl - { ~Maybe~your~use~of~\token_to_str:N \Hdotsfor\ is~incorrect.} - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { hvlines,~rounded-corners~and~corners } - { - Incompatible~options.\\ - You~should~not~use~'hvlines',~'rounded-corners'~and~'corners'~at~this~time.\\ - The~output~will~not~be~reliable. - } -% \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). - 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.\\ - You~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.\\ - Your~key~'\l_keys_key_str'~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Unknown~key~for~TikzEveryCell } - { - Unknown~key.\\ - There~is~only~two~keys~available~here:~ - 'empty'~and~'not-empty'.\\ - Your~key~'\l_keys_key_str'~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Unknown~key~for~rotate } - { - Unknown~key.\\ - The~only~key~available~here~is~'c'.\\ - Your~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',~ - 'horizontal-labels',~ - '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 { detection~of~empty~cells } - { - Problem~with~'not-empty'\\ - For~technical~reasons,~you~must~activate~ - 'create-cell-nodes'~in~\token_to_str:N \CodeBefore\ - in~order~to~use~the~key~'\l_keys_key_str'.\\ - That~key~will~be~ignored. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { siunitx~not~loaded } - { - siunitx~not~loaded\\ - You~can't~use~the~columns~'S'~because~'siunitx'~is~not~loaded.\\ - That~error~is~fatal. - } -% \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:nnn { width~without~X~columns } - { - You~have~used~the~key~'width'~but~you~have~put~no~'X'~column.~ - That~key~will~be~ignored. - } - { - This~message~is~the~message~'width~without~X~columns'~ - of~the~module~'nicematrix'.~ - The~experimented~users~can~disable~that~message~with~ - \token_to_str:N \msg_redirect_name:nnn.\\ - } - -% \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~'#1'~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 \g_@@_messages_for_Overleaf_bool - { For~a~list~of~the~names~already~used,~type~H~<return>. } - } - { - 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 { TikzEveryCell~without~tikz } - { - TikZ~not~loaded.\\ - You~can't~use~\token_to_str:N \TikzEveryCell\ - because~you~have~not~loaded~tikz.~ - This~command~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~\token_to_str:N \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. \\ - This~block~and~maybe~others~will~be~ignored. - } -% \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~without~tikz } - { - Tikz~not~loaded.\\ - You~can't~use~the~key~'tikz'~here~because~Tikz~is~not~ - loaded.~If~you~go~on,~that~key~will~be~ignored. - } -% \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 { without~color-inside } - { - If~order~to~use~\token_to_str:N \cellcolor,~\token_to_str:N \rowcolor,~ - \token_to_str:N \rowcolors\ or~\token_to_str:N \rowlistcolors\ - outside~\token_to_str:N \CodeBefore,~you~ - should~have~used~the~key~'color-inside'~in~your~\@@_full_name_env:.\\ - You~can~go~on~but~you~may~need~more~compilations. - } -% \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,~opacity,~rounded-corners,~r,~ - respect-arraystretch,~t,~T,~tikz,~transparent~and~vlines. - } -% \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,~ - light-syntax-expanded,~ - matrix/columns-type,~ - no-cell-nodes,~ - notes~(several~subkeys),~ - nullify-dots,~ - pgf-node-code,~ - renew-dots,~ - renew-matrix,~ - respect-arraystretch,~ - rounded-corners,~ - 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,~ - color-inside,~ - 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,~ - light-syntax-expanded,~ - name,~ - no-cell-nodes,~ - nullify-dots,~ - pgf-node-code,~ - renew-dots,~ - respect-arraystretch,~ - right-margin,~ - rounded-corners,~ - 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,~ - color-inside,~ - 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,~ - light-syntax-expanded,~ - name,~ - no-cell-nodes,~ - nullify-dots,~ - pgf-node-code,~ - r,~ - renew-dots,~ - respect-arraystretch,~ - right-margin,~ - rounded-corners,~ - 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,~ - color-inside,~ - 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,~ - light-syntax-expanded,~ - name,~ - no-cell-nodes,~ - 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'.\\ - \bool_if:NF \g_@@_messages_for_Overleaf_bool - { For~a~list~of~the~names~already~used,~type~H~<return>. } - } - { - 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} -% -% \begin{macrocode} -\@@_msg_new:nn { NiceTabularX~without~X } - { - NiceTabularX~without~X.\\ - You~should~not~use~{NiceTabularX}~without~X~columns.\\ - However,~you~can~go~on. - } -% \end{macrocode} -% -% \begin{macrocode} -\@@_msg_new:nn { Preamble~forgotten } - { - Preamble~forgotten.\\ - You~have~probably~forgotten~the~preamble~of~your~ - \@@_full_name_env:. \\ - This~error~is~fatal. - } -% \end{macrocode} -% -% \newpage -% \tableofcontents -% -% \endinput -% Local Variables: -% TeX-fold-mode: t -% TeX-fold-preserve-comments: nil -% fill-column: 80 -% End: - - +% \iffalse meta-comment
+%
+% This file should be compiled with $xelatex$.
+%
+% Copyright (C) 2018-2024 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.27a}
+\def\myfiledate{2024/02/19}
+%
+%
+%<*batchfile>
+\begingroup
+\input l3docstrip.tex
+\keepsilent
+\usedir{tex/latex/nicematrix}
+\preamble
+
+
+Copyright (C) 2018-2024 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
+%</batchfile>
+%
+%<*driver>
+\documentclass[dvipsnames]{l3doc}% dvipsnames is for xcolor (loaded by Tikz)
+\VerbatimFootnotes
+
+\usepackage[luatex]{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{formatcom=\color{gray}}
+
+\usepackage{upquote}
+
+\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}
+%</driver>
+% \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 e }
+\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, by default, 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 \g_@@_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 generate usually an error but only a
+% warning on Overleaf. The argument is given by curryfication.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_error_or_warning:n
+ { \bool_if:NTF \g_@@_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_new:N \g_@@_messages_for_Overleaf_bool
+\bool_gset:Nn \g_@@_messages_for_Overleaf_bool
+ {
+ \str_if_eq_p:on \c_sys_jobname_str { _region_ } % for Emacs
+ || \str_if_eq_p:on \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 \g_@@_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{Collecting options}
+%
+% The following technic allows to create user commands with the ability to put
+% an arbitrary number of |[|\textsl{list of (key=val)}|]| after the name of the
+% command.
+%
+% \medskip
+% \emph{Exemple} :\par\nobreak
+%
+% |\@@_collect_options:n { \F } [x=a,y=b] [z=c,t=d] { arg }|
+%
+% will be transformed in :\quad |\F{x=a,y=b,z=c,t=d}{arg}|
+%
+% \smallskip
+% Therefore, by writing : |\def\G{\@@_collect_options:n{\F}}|,
+%
+% the command |\G| takes in an arbitrary number of optional arguments between
+% square brackets.
+%
+% Be careful: that command is \emph{not} ``fully expandable'' (because of
+% |\peek_meaning:NTF|).
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_collect_options:n #1
+ {
+ \peek_meaning:NTF [
+ { \@@_collect_options:nw { #1 } }
+ { #1 { } }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% We use |\NewDocumentCommand| in order to be able to allow nested brackets
+% within the argument between |[| and |]|.
+% \begin{macrocode}
+\NewDocumentCommand \@@_collect_options:nw { m r[] }
+ { \@@_collect_options:nn { #1 } { #2 } }
+
+\cs_new_protected:Npn \@@_collect_options:nn #1 #2
+ {
+ \peek_meaning:NTF [
+ { \@@_collect_options:nnw { #1 } { #2 } }
+ { #1 { #2 } }
+ }
+
+\cs_new_protected:Npn \@@_collect_options:nnw #1#2[#3]
+ { \@@_collect_options:nn { #1 } { #2 , #3 } }
+% \end{macrocode}
+%
+%
+% \bigskip
+% \section{Technical definitions}
+%
+%
+% The following constants are defined only for efficiency in the tests.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_b_tl { b }
+\tl_const:Nn \c_@@_c_tl { c }
+\tl_const:Nn \c_@@_l_tl { l }
+\tl_const:Nn \c_@@_r_tl { r }
+\tl_const:Nn \c_@@_all_tl { all }
+\tl_const:Nn \c_@@_dot_tl { . }
+\tl_const:Nn \c_@@_default_tl { default }
+\tl_const:Nn \c_@@_star_tl { * }
+\str_const:Nn \c_@@_r_str { r }
+\str_const:Nn \c_@@_c_str { c }
+\str_const:Nn \c_@@_l_str { l }
+\str_const:Nn \c_@@_R_str { R }
+\str_const:Nn \c_@@_C_str { C }
+\str_const:Nn \c_@@_L_str { L }
+\str_const:Nn \c_@@_j_str { j }
+\str_const:Nn \c_@@_si_str { si }
+% \end{macrocode}
+%
+% The following token list will be used for definitions of user commands (with
+% |\NewDocumentCommand|) with an embellishment using an \emph{underscore} (there
+% may be problems because of the catcode of the underscore).
+% \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 \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 May 2023, the current
+% version \cls{revtex4-2} is 4.2f (compatible with \pkg{booktabs}).
+%
+% \begin{macrocode}
+\IfClassLoadedTF { revtex4-1 }
+ { \bool_const:Nn \c_@@_revtex_bool \c_true_bool }
+ {
+ \IfClassLoadedTF { 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
+% 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 { . } }
+ \tex_mkern:D 2 mu
+ \box_move_up:nn { 4 pt } { \hbox { . } }
+ \tex_mkern:D 2 mu
+ \box_move_up:nn { 7 pt }
+ { \vbox:n { \kern 7 pt \hbox { . } } }
+ \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_nopar: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_if_zero:nT \l_@@_first_col_int { \omit & }
+ \int_compare:nNnT { #1 } > \c_one_int
+ { \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 will be nullified in the environment |{NiceTabular}|,
+% |{NiceTabular*}| and |{NiceTabularX}|.
+% \begin{macrocode}
+\cs_set_eq:NN \@@_math_toggle: \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 { o }
+% \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 { o }
+% \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 o }
+% \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 { o }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_set_eq:NN \@@_old_pgfpointanchor \pgfpointanchor
+% \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
+% If the user uses |{NiceTabular}|, |{NiceTabular*}| or |{NiceTabularX}|, we
+% will raise the following flag.
+% \begin{macrocode}
+\bool_new:N \l_@@_tabular_bool
+% \end{macrocode}
+%
+% \bigskip
+% |\g_@@_delims_bool| will be true for the environments with delimiters (ex. :
+% |{pNiceMatrix}|, |{pNiceArray}|, |\pAutoNiceMatrix|, etc.).
+% \begin{macrocode}
+\bool_new:N \g_@@_delims_bool
+\bool_gset_true:N \g_@@_delims_bool
+% \end{macrocode}
+% In fact, if there is delimiters in the preamble of |{NiceArray}| (eg:
+% |[cccc]|), this boolean will be set to false.
+%
+% \medskip
+% The following boolean will be equal to |true| in the environments which have
+% a preamble (provided by the final user): |{NiceTabular}|, |{NiceArray}|,
+% |{pNiceArray}|, etc.
+% \begin{macrocode}
+\bool_new:N \l_@@_preamble_bool
+\bool_set_true:N \l_@@_preamble_bool
+% \end{macrocode}
+%
+% \medskip
+% We need a special treatment for |{NiceMatrix}| when |vlines| is not used, in
+% order to retrieve |\arraycolsep| on both sides.
+% \begin{macrocode}
+\bool_new:N \l_@@_NiceMatrix_without_vlines_bool
+% \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| and |j|. For example, a column |p[l]{3cm}| will provide the
+% value |l| for all the cells of the column.
+% \begin{macrocode}
+\tl_new:N \l_@@_hpos_cell_tl
+\tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_c_tl
+% \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 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 |{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
+% The key |color| in a command of rule such as |\Hline| (or the specifier
+% ``\verb+|+'' in the preamble of an environment).
+% \begin{macrocode}
+\tl_new:N \l_@@_rule_color_tl
+% \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
+% The following boolean will be raise then the command |\rotate| is used with
+% the key |c|.
+% \begin{macrocode}
+\bool_new:N \g_@@_rotate_c_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_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}
+%
+% During the second run, if informations concerning the current environment has
+% been found in the |aux| file, the following flag will be raised.
+% \begin{macrocode}
+\bool_new:N \g_@@_aux_found_bool
+% \end{macrocode}
+%
+% \bigskip
+% In particuler, in that |aux| file, there will be, for each environment of
+% \pkg{nicematrix}, an affectation for the the following sequence that will
+% contain informations about the size of the array.
+% \begin{macrocode}
+\seq_new:N \g_@@_size_seq
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\tl_new:N \g_@@_left_delim_tl
+\tl_new:N \g_@@_right_delim_tl
+% \end{macrocode}
+%
+% \bigskip
+% The token list |\g_@@_user_preamble_tl| will contain the preamble provided by
+% the the final user of \pkg{nicematrix} (eg the preamble of an environment
+% |{NiceTabular}|).
+% \begin{macrocode}
+\tl_new:N \g_@@_user_preamble_tl
+% \end{macrocode}
+% The token list |\g_@@_array_preamble_tl| will contain the preamble constructed
+% by \pkg{nicematrix} for the environment |{array}| (of \pkg{array}).
+% \begin{macrocode}
+\tl_new:N \g_@@_array_preamble_tl
+% \end{macrocode}
+% For |\multicolumn|.
+% \begin{macrocode}
+\tl_new:N \g_@@_preamble_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|.
+% \begin{macrocode}
+\tl_new:N \l_@@_columns_type_tl
+\str_set:Nn \l_@@_columns_type_tl { c }
+% \end{macrocode}
+%
+% \bigskip
+% The following parameters correspond to the keys |down|, |up| and |middle| of a
+% command such as |\Cdots|. Usually, the final user doesn't use that keys
+% directly because he uses the syntax with the embellishments |_|, |^| and |:|.
+% \begin{macrocode}
+\tl_new:N \l_@@_xdots_down_tl
+\tl_new:N \l_@@_xdots_up_tl
+\tl_new:N \l_@@_xdots_middle_tl
+% \end{macrocode}
+%
+% \bigskip
+% We will store in the following sequence informations provided by the
+% instructions |\rowlistcolors| in the main array (not in the |\CodeBefore|).
+% \begin{macrocode}
+\seq_new:N \g_@@_rowlistcolors_seq
+% \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}
+%
+%
+% 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
+% \begin{macrocode}
+\bool_new:N \l_@@_bold_row_style_bool
+% \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
+% 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 so-called |\CodeBefore| is splitted in two parts because we want to control
+% the order of execution of some instructions.
+% \begin{macrocode}
+\tl_new:N \g_@@_pre_code_before_tl
+\tl_new:N \g_nicematrix_code_before_tl
+% \end{macrocode}
+% 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|.
+%
+% \bigskip
+% The so-called |\CodeAfter| is splitted in two parts because we want to control
+% the order of execution of some instructions.
+% \begin{macrocode}
+\tl_new:N \g_@@_pre_code_after_tl
+\tl_new:N \g_nicematrix_code_after_tl
+% \end{macrocode}
+% The |\CodeAfter| provided by the final user (with the key |code-after| or the
+% keyword |\CodeAfter|) will be stored in the second token list.
+%
+% \bigskip
+% \begin{macrocode}
+\bool_new:N \l_@@_in_code_after_bool
+% \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 counters will be used when drawing the rules.
+% \begin{macrocode}
+\int_new:N \l_@@_start_int
+\int_set_eq:NN \l_@@_start_int \c_one_int
+\int_new:N \l_@@_end_int
+\int_new:N \l_@@_local_start_int
+\int_new:N \l_@@_local_end_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|, |opacity|, |draw|,
+% |tikz|, |borders|, and |rounded-corners| of the command |\Block|.
+% \begin{macrocode}
+\tl_new:N \l_@@_fill_tl
+\tl_new:N \l_@@_opacity_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
+% In the key |tikz| of a command |\Block| or in the argument of a command
+% |\TikzEveryCell|, the final user puts a list of tikz keys. But, you have added
+% another key, named |offset| (which means that an offset will be used for the
+% frame of the block or the cell). The following parameter corresponds to that key.
+% \begin{macrocode}
+\dim_new:N \l_@@_offset_dim
+% \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
+% If the final user has used the special color ``|nocolor|'', the following flag
+% will be raised.
+% \begin{macrocode}
+\bool_new:N \@@_nocolor_used_bool
+% \end{macrocode}
+%
+% \medskip
+% For the vertical position, the possible values are |c|, |t| and |b|.
+% \begin{macrocode}
+\str_new:N \l_@@_vpos_block_str
+\str_set:Nn \l_@@_vpos_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_eq:NN \l_@@_first_col_int \c_one_int
+% \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. The command |\NiceMatrixOptions| also sets
+% |\l_@@_last_col_int| to~$0$.
+% \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:|.
+%
+% \medskip
+% In the last column, we will raise the following flag (it will be used by
+% |\OnlyMainNiceMatrix|).
+% \begin{macrocode}
+\bool_new:N \l_@@_in_last_col_bool
+% \end{macrocode}
+% \end{itemize}
+%
+% \bigskip
+% \textbf{Some utilities}
+%
+% \medskip
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_cut_on_hyphen:w #1-#2\q_stop
+ {
+ \cs_set_nopar:Npn \l_tmpa_tl { #1 }
+ \cs_set_nopar:Npn \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:NVF #1 \c_@@_all_tl
+ {
+ \clist_clear:N \l_tmpa_clist
+ \clist_map_inline:Nn #1
+ {
+ \tl_if_in:nnTF { ##1 } { - }
+ { \@@_cut_on_hyphen:w ##1 \q_stop }
+ {
+ \cs_set_nopar:Npn \l_tmpa_tl { ##1 }
+ \cs_set_nopar:Npn \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
+% The following internal parameters are for:
+% \begin{itemize}
+% \item |\Ldots| \emph{with both extremities open} (and hence also |\Hdotsfor| in an
+% exterior row;
+% \item |\Vdots| \emph{with both extremities open} (and hence also |\Vdotsfor| in an
+% exterior column;
+% \item when the special character ``|:|'' is used in order to put the label of
+% a so-called ``dotted line'' \emph{on the line}, a margin of
+% |\c_@@_innersep_middle_dim| will be added around the label.
+% \end{itemize}
+%
+% \begin{macrocode}
+\hook_gput_code:nnn { begindocument } { . }
+ {
+ \dim_const:Nn \c_@@_shift_Ldots_last_row_dim { 0.5 em }
+ \dim_const:Nn \c_@@_shift_exterior_Vdots_dim { 0.6 em }
+ \dim_const:Nn \c_@@_innersep_middle_dim { 0.17 em }
+ }
+% \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 component of |\g_@@_notes_seq| will be a kind of
+% couple of the form : \texttt{\{\textsl{label}\}\{\textsl{text of the
+% tabularnote}\}}. The first component 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 expressed by |\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 components 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_lazy_or:nnT { \cs_if_exist_p:N \@captype } \l_@@_in_env_bool
+ {
+ \bool_lazy_and:nnTF { ! \l_@@_tabular_bool } \l_@@_in_env_bool
+ { \@@_error:n { tabularnote~forbidden } }
+ {
+ \bool_if:NTF \l_@@_in_caption_bool
+ \@@_tabularnote_caption:nn
+ \@@_tabularnote:nn
+ { #1 } { #2 }
+ }
+ }
+ }
+ }
+ {
+ \NewDocumentCommand \tabularnote { o m }
+ {
+ \@@_error_or_warning:n { enumitem~not~loaded }
+ \@@_gredirect_none:n { enumitem~not~loaded }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_test_first_novalue:nnn #1 #2 #3
+ { \tl_if_novalue:nT { #1 } { #3 } }
+% \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 expressed by |\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 expressed by |\c_novalue_tl|.
+%
+% When we will go through the sequence |\g_@@_notes_seq|, we will count in
+% |\l_tmpb_int| the notes without explicit label in order to have the
+% ``current'' value of the counter |\c@tabularnote|.
+% \begin{macrocode}
+ \int_zero:N \l_tmpb_int
+ \seq_map_indexed_inline:Nn \g_@@_notes_seq
+ {
+ \@@_test_first_novalue:nnn ##2 { \int_incr:N \l_tmpb_int }
+ \tl_if_eq:nnT { { #1 } { #2 } } { ##2 }
+ {
+ \tl_if_novalue:nTF { #1 }
+ { \int_set_eq:NN \l_tmpa_int \l_tmpb_int }
+ { \int_set:Nn \l_tmpa_int { ##1 } }
+ \seq_map_break:
+ }
+ }
+ \int_if_zero:nF \l_tmpa_int
+ { \int_add:Nn \l_tmpa_int \g_@@_notes_caption_int }
+ }
+ \int_if_zero:nT \l_tmpa_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_if_zero:nTF \l_tmpa_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 when
+% |\l_@@_hpos_cell_tl| is equal to |c| or |r|.
+% \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_gdecr:N \c@tabularnote
+ \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
+ \bool_lazy_or:nnTF
+ { \tl_if_eq_p:NN \l_@@_hpos_cell_tl \c_@@_c_tl }
+ { \tl_if_eq_p:NN \l_@@_hpos_cell_tl \c_@@_r_tl }
+ {
+ \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 }
+ }
+ { \box_use: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.
+% Be careful! We must put |\tl_if_in:NnF| and not |\tl_if_in:NnT|!
+% \begin{macrocode}
+ \seq_if_in:NnF \g_@@_notes_in_caption_seq { { #1 } { #2 } }
+ { \@@_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.
+% \begin{macrocode}
+ \seq_if_in:NnTF \g_@@_notes_in_caption_seq { { #1 } { #2 } }
+ {
+% \end{macrocode}
+% Now, we know 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 \@@_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
+ {
+ 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
+ {
+ 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 |color-inside| is used, these
+% commands are available.
+% \begin{macrocode}
+\bool_new:N \l_@@_color_inside_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 parameter corresponds to the key |xdots/horizontal_labels|.
+% \begin{macrocode}
+\bool_new:N \l_@@_xdots_h_labels_bool
+% \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}
+% The unit is |em| and that's why we fix the dimension after the preamble.
+%
+% \bigskip
+% The following dimension is the distance between a node (in fact an
+% anchor of that node) and a dotted line (for real dotted lines, the actual
+% distance may, of course, be a bit larger, depending of the exact position of
+% the dots).
+% \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}
+% The unit is |em| and that's why we fix the dimension after the preamble.
+%
+% \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}
+% The unit is |em| and that's why we fix the dimension after the preamble.
+%
+%
+% \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|
+% and the boolean |\l_@@_light_syntax_expanded_bool| correspond to the the
+% option |light-syntax-expanded|.
+% \begin{macrocode}
+\bool_new:N \l_@@_light_syntax_bool
+\bool_new:N \l_@@_light_syntax_expanded_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 within |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
+% When the key |respect-arraystretch| is used, the following command will be nullified.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_reset_arraystretch:
+ { \cs_set_nopar:Npn \arraystretch { 1 } }
+% \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 }
+ {
+ 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 } } ,
+ shorten-start .value_required:n = true ,
+ shorten-end .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 .value_required:n = true ,
+ horizontal-labels .bool_set:N = \l_@@_xdots_h_labels_bool ,
+ horizontal-labels .default:n = true ,
+ 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 ,
+ 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|, |up| and |middle| are not documented for the final user
+% because he should use the syntax with |^|, |_| and |:|. We use
+% |\tl_put_right:Nn| and not |\tl_set:Nn| (or |.tl_set:N|) because we don't want
+% a direct use of |up=...| erased by a absent |^{...}|.
+% \begin{macrocode}
+ down .code:n = \tl_put_right:Nn \l_@@_xdots_down_tl { #1 } ,
+ up .code:n = \tl_put_right:Nn \l_@@_xdots_up_tl { #1 } ,
+ middle .code:n = \tl_put_right:Nn \l_@@_xdots_middle_tl { #1 } ,
+% \end{macrocode}
+% The key |draw-first|, which is meant to be used only with |\Ddots| and
+% |\Iddots|, will 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 }
+ {
+ no-cell-nodes .code:n =
+ \cs_set_protected:Npn \@@_node_for_cell:
+ { \box_use_drop:N \l_@@_cell_box } ,
+ no-cell-nodes .value_forbidden:n = true ,
+ rounded-corners .dim_set:N = \l_@@_tab_rounded_corners_dim ,
+ rounded-corners .default:n = 4 pt ,
+ 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 .code:n =
+ \bool_set_true:N \l_@@_light_syntax_bool
+ \bool_set_false:N \l_@@_light_syntax_expanded_bool ,
+ light-syntax .value_forbidden:n = true ,
+ light-syntax-expanded .code:n =
+ \bool_set_true:N \l_@@_light_syntax_bool
+ \bool_set_true:N \l_@@_light_syntax_expanded_bool ,
+ light-syntax-expanded .value_forbidden: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_if_in:NnTF \c_@@_forbidden_letters_tl { #1 }
+ { \@@_error:nn { Forbidden~letter } { #1 } }
+% \end{macrocode}
+% We write directly a command for the automata which reads the preamble provided
+% by the final user.
+% \begin{macrocode}
+ { \cs_set_eq:cN { @@ _ #1 } \@@_make_preamble_vlism:n }
+ }
+ { \@@_error:n { One~letter~allowed } }
+ } ,
+ vlines-in-sub-matrix .value_required:n = true ,
+ hvlines .code:n =
+ {
+ \bool_set_true:N \l_@@_hvlines_bool
+ \tl_set_eq:NN \l_@@_vlines_clist \c_@@_all_tl
+ \tl_set_eq:NN \l_@@_hlines_clist \c_@@_all_tl
+ } ,
+ hvlines-except-borders .code:n =
+ {
+ \tl_set_eq:NN \l_@@_vlines_clist \c_@@_all_tl
+ \tl_set_eq:NN \l_@@_hlines_clist \c_@@_all_tl
+ \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 .code:n =
+ \cs_set_eq:NN \@@_reset_arraystretch: \prg_do_nothing: ,
+ respect-arraystretch .value_forbidden: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:Nx \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 ,
+ color-inside .code:n =
+ \bool_set_true:N \l_@@_color_inside_bool
+ \bool_set_true:N \l_@@_code_before_bool ,
+ color-inside .value_forbidden:n = true ,
+ colortbl-like .meta:n = color-inside
+ }
+% \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 .cs_set:Np = \@@_notes_style:n #1 ,
+ style .value_required:n = true ,
+ label-in-tabular .cs_set:Np = \@@_notes_label_in_tabular:n #1 ,
+ label-in-tabular .value_required:n = true ,
+ label-in-list .cs_set:Np = \@@_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 ,
+ CodeAfter / 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 .dim_set:N = \l_@@_width_dim ,
+ 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 .tl_set:N = \l_@@_columns_type_tl ,
+ 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 .tl_set:N = \l_@@_columns_type_tl ,
+ 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 ,
+ 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
+% 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.
+%
+% We \emph{must} put the following instructions \emph{after} the :
+%
+% \begin{verbatim}
+% CodeAfter / sub-matrix .inherit:n = NiceMatrix / sub-matrix
+% \end{verbatim}
+%
+% \begin{macrocode}
+\keys_define:nn { NiceMatrix / CodeAfter }
+ {
+ 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 ,
+ xdots .code:n = \keys_set:nn { NiceMatrix / xdots } { #1 } ,
+ sub-matrix .code:n = \keys_set:nn { NiceMatrix / sub-matrix } { #1 } ,
+ sub-matrix .value_required:n = true ,
+ unknown .code:n = \@@_error:n { Unknown~key~for~CodeAfter }
+ }
+% \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 the LaTeX counter |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 = \c_one_int
+ { \int_compare:nNnT \l_@@_first_col_int = \c_one_int \@@_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| is in the
+% |\@@_cell_end:|.
+% \begin{macrocode}
+ \hbox_set:Nw \l_@@_cell_box
+% \end{macrocode}
+% The following command is nullified in the tabulars.
+% \begin{macrocode}
+ \@@_tuning_not_tabular_begin:
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \@@_tuning_first_row:
+ \@@_tuning_last_row:
+ \g_@@_row_style_tl
+ }
+% \end{macrocode}
+%
+% The following command will be nullified unless there is a first row.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tuning_first_row:
+ {
+ \int_if_zero:nT \c@iRow
+ {
+ \int_compare:nNnT \c@jCol > \c_zero_int
+ {
+ \l_@@_code_for_first_row_tl
+ \xglobal \colorlet { nicematrix-first-row } { . }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% The following command will be nullified unless there is a last row and we
+% know its value (\emph{ie}: |\l_@@_lat_row_int > 0|).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tuning_last_row:
+ {
+ \int_compare:nNnT \c@iRow = \l_@@_last_row_int
+ {
+ \l_@@_code_for_last_row_tl
+ \xglobal \colorlet { nicematrix-last-row } { . }
+ }
+ }
+% \end{macrocode}
+%
+% A different value will be provided to the following command when the key
+% |small| is in force.
+% \begin{macrocode}
+\cs_set_eq:NN \@@_tuning_key_small: \prg_do_nothing:
+% \end{macrocode}
+%
+% The following commands are nullified in the tabulars.
+% \begin{macrocode}
+\cs_set_nopar:Npn \@@_tuning_not_tabular_begin:
+ {
+ \c_math_toggle_token
+% \end{macrocode}
+% A special value is provided by the following controls sequence when the key
+% |small| is in force.
+% \begin{macrocode}
+ \@@_tuning_key_small:
+ }
+\cs_set_eq:NN \@@_tuning_not_tabular_end: \c_math_toggle_token
+% \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_if_zero:nTF \c@iRow
+ {
+ \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 = \c_one_int
+ {
+ \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 }
+ \bool_if:NTF \g_@@_rotate_c_bool
+ {
+ \hbox_set:Nn \l_@@_cell_box
+ {
+ \c_math_toggle_token
+ \vcenter { \box_use:N \l_@@_cell_box }
+ \c_math_toggle_token
+ }
+ }
+ {
+ \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
+ \bool_gset_false:N \g_@@_rotate_c_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:
+ {
+% \end{macrocode}
+% The following command is nullified in the tabulars.
+% \begin{macrocode}
+ \@@_tuning_not_tabular_end:
+ \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}
+ \@@_update_max_cell_width:
+% \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_if:NTF \g_@@_not_empty_cell_bool
+ \@@_node_for_cell:
+ {
+ \dim_compare:nNnTF { \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 command will be nullified in our redefinition of |\multicolumn|.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_update_max_cell_width:
+ {
+ \dim_gset:Nn \g_@@_max_cell_width_dim
+ { \dim_max:nn \g_@@_max_cell_width_dim { \box_wd:N \l_@@_cell_box } }
+ }
+% \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:
+ \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
+% \begin{macrocode}
+\pgfset
+ {
+ nicematrix / cell-node /.style =
+ {
+ inner~sep = \c_zero_dim ,
+ minimum~width = \c_zero_dim
+ }
+ }
+% \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}
+\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 (with
+% consequences for the parallelisation of the diagonal lines).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_instruction_of_type:nnn #1 #2 #3
+ {
+ \bool_if:nTF { #1 } \tl_gput_left:cx \tl_gput_right:cx
+ { g_@@_ #2 _ lines _ tl }
+ {
+ \use:c { @@ _ draw _ #2 : nnn }
+ { \int_use:N \c@iRow }
+ { \int_use:N \c@jCol }
+ { \exp_not:n { #3 } }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_array:
+ {
+% \begin{macrocode}
+ \dim_set:Nn \col@sep
+ { \bool_if:NTF \l_@@_tabular_bool \tabcolsep \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 we need something fully expandable here.
+% \begin{macrocode}
+ [ \str_if_eq:VnTF \l_@@_baseline_tl c c t ]
+ }
+% \end{macrocode}
+%
+% \medskip
+% We keep in memory the standard version of |\ialign| because we will redefine
+% |\ialign| in the environment |{NiceArrayWithDelims}| but restore the standard
+% version for use in the cells of the array.
+% \begin{macrocode}
+\cs_set_eq:NN \@@_old_ialign: \ialign
+% \end{macrocode}
+%
+%
+% The following command creates a |row| node (and not a row of nodes!).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_create_row_node:
+ {
+ \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 \c_@@_all_tl
+ {
+ \exp_args:NNe
+ \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
+% 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}
+%
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_test_color_inside:
+ {
+ \bool_if:NF \l_@@_color_inside_bool
+ {
+% \end{macrocode}
+% We will issue an error only during the first run.
+% \begin{macrocode}
+ \bool_if:NF \g_@@_aux_found_bool
+ { \@@_error:n { without~color-inside } }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_redefine_everycr: { \everycr { \@@_everycr: } }
+\hook_gput_code:nnn { begindocument } { . }
+ {
+ \IfPackageLoadedTF { colortbl }
+ {
+ \cs_set_protected:Npn \@@_redefine_everycr:
+ {
+ \CT@everycr
+ {
+ \noalign { \cs_gset_eq:NN \CT@row@color \prg_do_nothing: }
+ \@@_everycr:
+ }
+ }
+ }
+ { }
+ }
+% \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}
+\hook_gput_code:nnn { begindocument } { . }
+ {
+ \IfPackageLoadedTF { booktabs }
+ {
+ \cs_new_protected:Npn \@@_patch_booktabs:
+ { \tl_put_left:Nn \@BTnormal \@@_create_row_node_i: }
+ }
+ { \cs_new_protected:Npn \@@_patch_booktabs: { } }
+ }
+% \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
+ \@@_patch_booktabs:
+ \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}
+% By default, |\@@_small_scripstyle:| is null.
+% \begin{macrocode}
+ \cs_set_eq:NN \@@_tuning_key_small: \scriptstyle
+ }
+% \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
+ {
+ \@@_redefine_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 } }
+ \cs_set_eq:NN \cellcolor \@@_cellcolor_tabular
+ \cs_set_eq:NN \rowcolor \@@_rowcolor_tabular
+ \cs_set_eq:NN \rowcolors \@@_rowcolors_tabular
+ \cs_set_eq:NN \rowlistcolors \@@_rowlistcolors_tabular
+ \int_compare:nNnT \l_@@_first_row_int > \c_zero_int
+ { \cs_set_eq:NN \@@_tuning_first_row: \prg_do_nothing: }
+ \int_compare:nNnT \l_@@_last_row_int < \c_zero_int
+ { \cs_set_eq:NN \@@_tuning_last_row: \prg_do_nothing: }
+ \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 }
+ \@@_revert_colortbl:
+% \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 counting the tabular notes in
+% the main array at the right value (we 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}
+ \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:
+ {
+ \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_@@_delims_bool
+ {
+% \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 }
+ }
+ {
+ \dim_gset:Nn \l_@@_left_delim_dim
+ { 2 \bool_if:NTF \l_@@_tabular_bool \tabcolsep \arraycolsep }
+ \dim_gset_eq:NN \l_@@_right_delim_dim \l_@@_left_delim_dim
+ }
+% \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_set:Nn \l_tmpa_tl { #1 }
+ \int_compare:nNnT { \char_value_catcode:n { 60 } } = { 13 }
+ { \@@_rescan_for_spanish:N \l_tmpa_tl }
+ \tl_gput_left:NV \g_@@_pre_code_before_tl \l_tmpa_tl
+ \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 (that commmand will be used only once and is present only for legibility).
+% \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
+ \cs_set_eq:NN \TikzEveryCell \@@_TikzEveryCell
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_exec_code_before:
+ {
+ \seq_gclear_new:N \g_@@_colors_seq
+% \end{macrocode}
+% The sequence |\g_@@_colors_seq| will always contain as first element the
+% special color |nocolor|: when that color is used, no color will be applied in
+% the corresponding cells by the other coloring commands of \pkg{nicematrix}.
+% \begin{macrocode}
+ \@@_add_to_colors_seq:nn { { nocolor } } { }
+ \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_@@_tabular_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 \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_@@_tabular_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 |\CodeBefore|, 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
+% 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 \g_@@_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_@@_user_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_@@_tabular_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| and the |\multicolumn|.
+%
+% \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}
+ \tl_if_exist:cTF { 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 }
+ }
+ { \bool_gset_false:N \g_@@_aux_found_bool }
+% \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_@@_delims_bool
+ { \keys_set:nn { NiceMatrix / pNiceArray } }
+ { \keys_set:nn { NiceMatrix / NiceArray } }
+ { #3 , #5 }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+ \@@_set_CT@arc@:o \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_if_zero:nT \g_@@_total_X_weight_int
+ { \@@_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 > \c_zero_int
+ {
+ \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_if_zero:nT \l_@@_first_col_int
+ { \skip_horizontal:N \g_@@_width_first_col_dim }
+% \end{macrocode}
+%
+% The construction of the real box is different whether we have delimiters to
+% put.
+% \begin{macrocode}
+ \bool_if:nTF { ! \g_@@_delims_bool }
+ {
+ \tl_if_eq:NNTF \l_@@_baseline_tl \c_@@_c_tl
+ \@@_use_arraybox_with_notes_c:
+ {
+ \tl_if_eq:NNTF \l_@@_baseline_tl \c_@@_b_tl
+ \@@_use_arraybox_with_notes_b:
+ \@@_use_arraybox_with_notes:
+ }
+ }
+% \end{macrocode}
+%
+% Now, in the case of an environment with delimiters. 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_if_zero:nTF \l_@@_first_row_int
+ {
+ \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:o \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_@@_tabular_bool
+ { \skip_horizontal:N -\tabcolsep }
+ { \skip_horizontal:N -\arraycolsep }
+ \@@_use_arraybox_with_notes_c:
+ \bool_if:NTF \l_@@_tabular_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
+ \skip_vertical:N \arrayrulewidth
+ }
+ \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 }
+ \bool_if:NT \l_@@_preamble_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:o \g_@@_aux_tl }
+ }
+ \iow_now:Nn \@mainaux { \ExplSyntaxOff }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+ \bool_if:NT \g_@@_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 final user provides a preamble, but we must convert that preamble into a
+% preamble that will be given to |{array}| (of the package \pkg{array}).
+%
+% \bigskip
+% The preamble given by the final user is stored in |\g_@@_user_preamble_tl|.
+% The modified version will be stored in |\g_@@_array_preamble_tl| also.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_transform_preamble:
+ {
+ \@@_transform_preamble_i:
+ \@@_transform_preamble_ii:
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_transform_preamble_i:
+ {
+ \int_gzero:N \c@jCol
+% \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_gclear:N \g_@@_cols_vlism_seq
+% \end{macrocode}
+% |\g_tmpb_bool| will be raised if you have a \verb+|+ at the end of the
+% preamble provided by the final user.
+% \begin{macrocode}
+ \bool_gset_false:N \g_tmpb_bool
+% \end{macrocode}
+%
+% 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
+ \tl_gclear:N \g_@@_array_preamble_tl
+ \tl_if_eq:NNTF \l_@@_vlines_clist \c_@@_all_tl
+ {
+ \tl_gset:Nn \g_@@_array_preamble_tl
+ { ! { \skip_horizontal:N \arrayrulewidth } }
+ }
+ {
+ \clist_if_in:NnT \l_@@_vlines_clist 1
+ {
+ \tl_gset:Nn \g_@@_array_preamble_tl
+ { ! { \skip_horizontal:N \arrayrulewidth } }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% Now, we actually make the preamble (which will be given to |{array}|). It will
+% be stored in |\g_@@_array_preamble_tl|.
+% \begin{macrocode}
+ \exp_last_unbraced:NV \@@_rec_preamble:n \g_@@_user_preamble_tl \stop
+ \int_gset_eq:NN \g_@@_static_num_of_col_int \c@jCol
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+ \@@_replace_columncolor:
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\hook_gput_code:nnn { begindocument } { . }
+ {
+ \IfPackageLoadedTF { colortbl }
+ {
+ \regex_const:Nn \c_@@_columncolor_regex { \c { columncolor } }
+ \cs_new_protected:Npn \@@_replace_columncolor:
+ {
+ \regex_replace_all:NnN
+ \c_@@_columncolor_regex
+ { \c { @@_columncolor_preamble } }
+ \g_@@_array_preamble_tl
+ }
+ }
+ {
+ \cs_new_protected:Npn \@@_replace_columncolor:
+ { \cs_set_eq:NN \columncolor \@@_columncolor_preamble }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_transform_preamble_ii:
+ {
+% \end{macrocode}
+%
+% \medskip
+% If there were delimiters at the beginning or at the end of the preamble, the
+% environment |{NiceArray}| is transformed into an environment |{xNiceMatrix}|.
+% \begin{macrocode}
+ \tl_if_eq:NNTF \g_@@_left_delim_tl \c_@@_dot_tl
+ {
+ \tl_if_eq:NNF \g_@@_right_delim_tl \c_@@_dot_tl
+ { \bool_gset_true:N \g_@@_delims_bool }
+ }
+ { \bool_gset_true:N \g_@@_delims_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_if_zero:nTF \l_@@_first_col_int
+ { \tl_gput_left:No \g_@@_array_preamble_tl \c_@@_preamble_first_col_tl }
+ {
+ \bool_if:NF \g_@@_delims_bool
+ {
+ \bool_if:NF \l_@@_tabular_bool
+ {
+ \tl_if_empty:NT \l_@@_vlines_clist
+ {
+ \bool_if:NF \l_@@_exterior_arraycolsep_bool
+ { \tl_gput_left:Nn \g_@@_array_preamble_tl { @ { } } }
+ }
+ }
+ }
+ }
+ \int_compare:nNnTF \l_@@_last_col_int > { -1 }
+ { \tl_gput_right:No \g_@@_array_preamble_tl \c_@@_preamble_last_col_tl }
+ {
+ \bool_if:NF \g_@@_delims_bool
+ {
+ \bool_if:NF \l_@@_tabular_bool
+ {
+ \tl_if_empty:NT \l_@@_vlines_clist
+ {
+ \bool_if:NF \l_@@_exterior_arraycolsep_bool
+ { \tl_gput_right:Nn \g_@@_array_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_@@_array_preamble_tl
+ { > { \@@_error_too_much_cols: } l }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% The preamble provided by the final user will be read by a finite
+% automata. The following function |\@@_rec_preamble:n| will read that preamble
+% (usually letter by letter) in a recursive way (hence the name of that function).
+% in the preamble.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rec_preamble:n #1
+ {
+% \end{macrocode}
+% For the majority of the letters, we will trigger the corresponding action by
+% calling directly a function in the main hashtable of TeX (thanks to the
+% mechanism |\csname...\endcsname|. Be careful: all these functions take in as
+% first argument the letter (or token) itself.\footnote{We do that because it's
+% an easy way to insert the letter at some places in the code that we will add to
+% |\g_@@_array_preamble_tl|.}
+% \begin{macrocode}
+ \cs_if_exist:cTF { @@ _ \token_to_str:N #1 }
+ { \use:c { @@ _ \token_to_str:N #1 } { #1 } }
+ {
+% \end{macrocode}
+% Now, the columns defined by |\newcolumntype| of \pkg{array}.
+% \begin{macrocode}
+ \cs_if_exist:cTF { NC @ find @ #1 }
+ {
+ \tl_set_eq:Nc \l_tmpb_tl { NC @ rewrite @ #1 }
+ \exp_last_unbraced:NV \@@_rec_preamble:n \l_tmpb_tl
+ }
+ {
+ \tl_if_eq:nnT { #1 } { S }
+ { \@@_fatal:n { unknown~column~type~S } }
+ { \@@_fatal:nn { unknown~column~type } { #1 } }
+ }
+ }
+ }
+% \end{macrocode}
+%
+%
+%
+% \bigskip
+% For |c|, |l| and |r|
+% \begin{macrocode}
+\cs_new:Npn \@@_c #1
+ {
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ { > \@@_cell_begin:w c < \@@_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
+ \@@_rec_preamble_after_col:n
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn \@@_l #1
+ {
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ {
+ > { \@@_cell_begin:w \tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_l_tl }
+ l
+ < \@@_cell_end:
+ }
+ \int_gincr:N \c@jCol
+ \@@_rec_preamble_after_col:n
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn \@@_r #1
+ {
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ {
+ > { \@@_cell_begin:w \tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_r_tl }
+ r
+ < \@@_cell_end:
+ }
+ \int_gincr:N \c@jCol
+ \@@_rec_preamble_after_col:n
+ }
+% \end{macrocode}
+%
+% \medskip
+% For |!| and |@|
+% \begin{macrocode}
+\cs_new:cpn { @@ _ \token_to_str:N ! } #1 #2
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl { #1 { #2 } }
+ \@@_rec_preamble:n
+ }
+\cs_set_eq:cc { @@ _ \token_to_str:N @ } { @@ _ \token_to_str:N ! }
+% \end{macrocode}
+%
+%
+% \medskip
+% For \verb+|+
+% \begin{macrocode}
+\cs_new:cpn { @@ _ | } #1
+ {
+% \end{macrocode}
+% |\l_tmpa_int| is the number of successive occurrences of \verb+|+
+% \begin{macrocode}
+ \int_incr:N \l_tmpa_int
+ \@@_make_preamble_i_i:n
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_i_i:n #1
+ {
+ \str_if_eq:nnTF { #1 } |
+ { \use:c { @@ _ | } | }
+ { \@@_make_preamble_i_ii:nn { } #1 }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_i_ii:nn #1 #2
+ {
+ \str_if_eq:nnTF { #2 } [
+ { \@@_make_preamble_i_ii:nw { #1 } [ }
+ { \@@_make_preamble_i_iii:nn { #2 } { #1 } }
+ }
+\cs_new_protected:Npn \@@_make_preamble_i_ii:nw #1 [ #2 ]
+ { \@@_make_preamble_i_ii:nn { #1 , #2 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_i_iii:nn #1 #2
+ {
+ \@@_compute_rule_width:n { multiplicity = \l_tmpa_int , #2 }
+ \tl_gput_right:Nx \g_@@_array_preamble_tl
+ {
+% \end{macrocode}
+% Here, the command |\dim_eval:n| is mandatory.
+% \begin{macrocode}
+ \exp_not:N ! { \skip_horizontal:n { \dim_eval:n { \l_@@_rule_width_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_@@_rule_width_dim ,
+ #2
+ }
+% \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 } { \stop } { \bool_gset_true:N \g_tmpb_bool }
+ \@@_rec_preamble:n #1
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new:cpn { @@ _ > } #1 #2
+ {
+ \tl_gput_right:Nn \g_@@_pre_cell_tl { > { #2 } }
+ \@@_rec_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_eq:NN \l_@@_hpos_col_str \c_@@_r_str ,
+ r .value_forbidden:n = true ,
+ c .code:n = \str_set_eq:NN \l_@@_hpos_col_str \c_@@_c_str ,
+ c .value_forbidden:n = true ,
+ l .code:n = \str_set_eq:NN \l_@@_hpos_col_str \c_@@_l_str ,
+ l .value_forbidden:n = true ,
+ R .code:n =
+ \IfPackageLoadedTF { ragged2e }
+ { \str_set_eq:NN \l_@@_hpos_col_str \c_@@_R_str }
+ {
+ \@@_error_or_warning:n { ragged2e~not~loaded }
+ \str_set_eq:NN \l_@@_hpos_col_str \c_@@_r_str
+ } ,
+ R .value_forbidden:n = true ,
+ L .code:n =
+ \IfPackageLoadedTF { ragged2e }
+ { \str_set_eq:NN \l_@@_hpos_col_str \c_@@_L_stsr }
+ {
+ \@@_error_or_warning:n { ragged2e~not~loaded }
+ \str_set_eq:NN \l_@@_hpos_col_str \c_@@_l_str
+ } ,
+ L .value_forbidden:n = true ,
+ C .code:n =
+ \IfPackageLoadedTF { ragged2e }
+ { \str_set_eq:NN \l_@@_hpos_col_str \c_@@_C_str }
+ {
+ \@@_error_or_warning:n { ragged2e~not~loaded }
+ \str_set_eq:NN \l_@@_hpos_col_str \c_@@_c_str
+ } ,
+ C .value_forbidden:n = true ,
+ S .code:n = \str_set_eq:NN \l_@@_hpos_col_str \c_@@_si_str ,
+ 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|.
+% \begin{macrocode}
+\cs_new:Npn \@@_p #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}
+ \@@_make_preamble_ii_i:n
+ }
+\cs_set_eq:NN \@@_b \@@_p
+\cs_set_eq:NN \@@_m \@@_p
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_ii_i:n #1
+ {
+ \str_if_eq:nnTF { #1 } { [ }
+ { \@@_make_preamble_ii_ii:w [ }
+ { \@@_make_preamble_ii_ii:w [ ] { #1 } }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_ii_ii:w [ #1 ]
+ { \@@_make_preamble_ii_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 \@@_make_preamble_ii_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_eq:NN \l_@@_hpos_col_str \c_@@_j_str
+ \@@_keys_p_column:n { #1 }
+ \@@_make_preamble_ii_iv:nnn { #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 }
+% \end{macrocode}
+%
+% \medskip
+% The first argument is the width of the column. The second is the type of
+% environment: |minipage| or |varwidth|. The third is some code added at the
+% beginning of the cell.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_ii_iv:nnn #1 #2 #3
+ {
+ \use:e
+ {
+ \@@_make_preamble_ii_v:nnnnnnnn
+ { \str_if_eq:onTF \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_tl| which
+% will provide the horizontal alignment of the column to which belongs the cell.
+% \begin{macrocode}
+ \str_if_eq:NNTF \l_@@_hpos_col_str \c_@@_j_str
+ { \tl_clear:N \exp_not:N \l_@@_hpos_cell_tl }
+ {
+ \cs_set_nopar:Npn \exp_not:N \l_@@_hpos_cell_tl
+ { \str_lowercase:V \l_@@_hpos_col_str }
+ }
+ \str_case:on \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 }
+ }
+ #3
+ }
+ { \str_if_eq:onT \l_@@_vpos_col_str { m } \@@_center_cell_box: }
+ { \str_if_eq:onT \l_@@_hpos_col_str { si } \siunitx_cell_begin:w }
+ { \str_if_eq:onT \l_@@_hpos_col_str { si } \siunitx_cell_end: }
+ { #2 }
+ {
+ \str_case:onF \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
+ \@@_rec_preamble_after_col:n
+ }
+% \end{macrocode}
+%
+% \medskip
+% |#1| is the optional argument of |{minipage}| (or |{varwidth}|): |t| or |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_tl| 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 \@@_make_preamble_ii_v:nnnnnnnn #1 #2 #3 #4 #5 #6 #7 #8
+ {
+ \tl_if_eq:NNTF \l_@@_hpos_col_str \c_@@_si_str
+ { \tl_gput_right:Nn \g_@@_array_preamble_tl { > { \@@_test_if_empty_for_S: } } }
+ { \tl_gput_right:Nn \g_@@_array_preamble_tl { > { \@@_test_if_empty: } } }
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_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
+% \end{macrocode}
+% We use the form |\minipage|--|\endminipage| (|\varwidth|--|\endvarwidth|) for
+% compatibility with \pkg{collcell} (2023-10-31).
+% \begin{macrocode}
+ \use:c { #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
+ \use:c { 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}
+\str_new:N \c_@@_ignorespaces_str
+\str_set:Nx \c_@@_ignorespaces_str { \ignorespaces }
+\str_remove_all:Nn \c_@@_ignorespaces_str { ~ }
+% \end{macrocode}
+%
+% \bigskip
+% In order to test whether a cell is empty, we test whether it begins by
+% |\ignorespaces\unskip|. However, in some circunstancies, for example when
+% |\collectcell| of \pkg{collcell} is used, the cell does not begin with
+% |\ignorespaces|. In that case, we consider as not empty...
+%
+% First, we test if the next token is |\ignorespaces| and it's not very easy...
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_test_if_empty: { \peek_after:Nw \@@_test_if_empty_i: }
+\cs_new_protected:Npn \@@_test_if_empty_i:
+ {
+ \str_set:Nx \l_tmpa_str { \token_to_meaning:N \l_peek_token }
+ \str_if_eq:NNT \l_tmpa_str \c_@@_ignorespaces_str
+ { \@@_test_if_empty:w }
+ }
+\cs_new_protected:Npn \@@_test_if_empty:w \ignorespaces
+ {
+ \peek_meaning:NT \unskip
+ {
+ \tl_gput_right:Nn \g_@@_cell_after_hook_tl
+ {
+ \box_set_wd:Nn \l_@@_cell_box \c_zero_dim
+ \skip_horizontal:N \l_@@_col_width_dim
+ }
+ }
+ }
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_test_if_empty_for_S:
+ {
+ \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 }
+ }
+ }
+% \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:Npn \@@_V #1 #2
+ {
+ \str_if_eq:nnTF { #2 } { [ }
+ { \@@_make_preamble_V_i:w [ }
+ { \@@_make_preamble_V_i:w [ ] { #2 } }
+ }
+\cs_new_protected:Npn \@@_make_preamble_V_i:w [ #1 ]
+ { \@@_make_preamble_V_ii:nn { #1 } }
+\cs_new_protected:Npn \@@_make_preamble_V_ii:nn #1 #2
+ {
+ \str_set:Nn \l_@@_vpos_col_str { p }
+ \str_set_eq:NN \l_@@_hpos_col_str \c_@@_j_str
+ \@@_keys_p_column:n { #1 }
+ \IfPackageLoadedTF { varwidth }
+ { \@@_make_preamble_ii_iv:nnn { #2 } { varwidth } { } }
+ {
+ \@@_error_or_warning:n { varwidth~not~loaded }
+ \@@_make_preamble_ii_iv:nnn { #2 } { minipage } { }
+ }
+ }
+% \end{macrocode}
+%
+% \medskip
+% For |w| and |W|
+% \begin{macrocode}
+\cs_new:Npn \@@_w { \@@_make_preamble_w:nnnn { } }
+\cs_new:Npn \@@_W { \@@_make_preamble_w:nnnn { \@@_special_W: } }
+% \end{macrocode}
+%
+% |#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 \@@_make_preamble_w:nnnn #1 #2 #3 #4
+ {
+ \str_if_eq:nnTF { #3 } { s }
+ { \@@_make_preamble_w_i:nnnn { #1 } { #4 } }
+ { \@@_make_preamble_w_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 \@@_make_preamble_w_i:nnnn #1 #2
+ {
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ {
+ > {
+ \dim_set:Nn \l_@@_col_width_dim { #2 }
+ \@@_cell_begin:w
+ \tl_set_eq:NN \l_@@_hpos_cell_tl \c_@@_c_tl
+ }
+ c
+ < {
+ \@@_cell_end_for_w_s:
+ #1
+ \@@_adjust_size_box:
+ \box_use_drop:N \l_@@_cell_box
+ }
+ }
+ \int_gincr:N \c@jCol
+ \@@_rec_preamble_after_col: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 \@@_make_preamble_w_ii:nnnn #1 #2 #3 #4
+ {
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_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
+ \cs_set_nopar:Npn \l_@@_hpos_cell_tl { #3 }
+ }
+ c
+ < {
+ \@@_cell_end:
+ \hbox_set_end:
+ #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
+ \@@_rec_preamble_after_col: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| (of \pkg{siunitx}).
+% \begin{macrocode}
+\cs_new:Npn \@@_S #1 #2
+ {
+ \str_if_eq:nnTF { #2 } { [ }
+ { \@@_make_preamble_S:w [ }
+ { \@@_make_preamble_S:w [ ] { #2 } }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_S:w [ #1 ]
+ { \@@_make_preamble_S_i:n { #1 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_S_i:n #1
+ {
+ \IfPackageLoadedTF { siunitx }
+ {
+ \tl_gput_right:No \g_@@_array_preamble_tl \g_@@_pre_cell_tl
+ \tl_gclear:N \g_@@_pre_cell_tl
+ \tl_gput_right:Nn \g_@@_array_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
+ \@@_rec_preamble_after_col:n
+ }
+ { \@@_fatal:n { siunitx~not~loaded } }
+ }
+% \end{macrocode}
+%
+%
+% \medskip
+% For |(|, |[| and |\{|.
+% \begin{macrocode}
+\cs_new:cpn { @@ _ \token_to_str:N ( } #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_if_zero:nTF \c@jCol
+ {
+ \tl_if_eq:NNTF \g_@@_left_delim_tl \c_@@_dot_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_eq:NN \g_@@_right_delim_tl \c_@@_dot_tl
+ \@@_rec_preamble:n #2
+ }
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl { ! { \enskip } }
+ \@@_make_preamble_iv:nn { #1 } { #2 }
+ }
+ }
+ { \@@_make_preamble_iv:nn { #1 } { #2 } }
+ }
+\cs_set_eq:cc { @@ _ \token_to_str:N [ } { @@ _ \token_to_str:N ( }
+\cs_set_eq:cc { @@ _ \token_to_str:N \{ } { @@ _ \token_to_str:N ( }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_iv: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 }
+ \@@_rec_preamble:n
+ }
+ { \@@_rec_preamble:n #2 }
+ }
+% \end{macrocode}
+%
+% In fact, if would be possible to define |\left| and |\right| as no-op.
+% \begin{macrocode}
+\cs_new:cpn { @@ _ \token_to_str:N \left } #1 { \use:c { @@ _ \token_to_str:N ( } }
+% \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:cpn { @@ _ \token_to_str:N ) } #1 #2
+ {
+ \bool_if:NT \l_@@_small_bool { \@@_fatal:n { Delimiter~with~small } }
+ \tl_if_in:nnTF { ) ] \} } { #2 }
+ { \@@_make_preamble_v:nnn #1 #2 }
+ {
+ \tl_if_eq:nnTF { \stop } { #2 }
+ {
+ \tl_if_eq:NNTF \g_@@_right_delim_tl \c_@@_dot_tl
+ { \tl_gset:Nn \g_@@_right_delim_tl { #1 } }
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl { ! { \enskip } }
+ \tl_gput_right:Nx \g_@@_pre_code_after_tl
+ { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool }
+ \@@_rec_preamble:n #2
+ }
+ }
+ {
+ \tl_if_in:nnT { ( [ \{ \left } { #2 }
+ { \tl_gput_right:Nn \g_@@_array_preamble_tl { ! { \enskip } } }
+ \tl_gput_right:Nx \g_@@_pre_code_after_tl
+ { \@@_delimiter:nnn #1 { \int_use:N \c@jCol } \c_false_bool }
+ \@@_rec_preamble:n #2
+ }
+ }
+ }
+\cs_set_eq:cc { @@ _ \token_to_str:N ] } { @@ _ \token_to_str:N ) }
+\cs_set_eq:cc { @@ _ \token_to_str:N \} } { @@ _ \token_to_str:N ) }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_v:nnn #1 #2 #3
+ {
+ \tl_if_eq:nnTF { \stop } { #3 }
+ {
+ \tl_if_eq:NNTF \g_@@_right_delim_tl \c_@@_dot_tl
+ {
+ \tl_gput_right:Nn \g_@@_array_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_@@_array_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 }
+ \@@_rec_preamble:n #3
+ }
+ }
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+\cs_new:cpn { @@ _ \token_to_str:N \right } #1
+ { \use:c { @@ _ \token_to_str: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 \@@_rec_preamble_after_col:n #1
+ {
+ \str_if_eq:nnTF { #1 } { < }
+ \@@_rec_preamble_after_col_i:n
+ {
+ \str_if_eq:nnTF { #1 } { @ }
+ \@@_rec_preamble_after_col_ii:n
+ {
+ \tl_if_eq:NNTF \l_@@_vlines_clist \c_@@_all_tl
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ { ! { \skip_horizontal:N \arrayrulewidth } }
+ }
+ {
+ \exp_args:NNe
+ \clist_if_in:NnT \l_@@_vlines_clist { \int_eval:n { \c@jCol + 1 } }
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ { ! { \skip_horizontal:N \arrayrulewidth } }
+ }
+ }
+ \@@_rec_preamble:n { #1 }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rec_preamble_after_col_i:n #1
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl { < { #1 } }
+ \@@_rec_preamble_after_col: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 \@@_rec_preamble_after_col_ii:n #1
+ {
+ \tl_if_eq:NNTF \l_@@_vlines_clist \c_@@_all_tl
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ { @ { #1 \skip_horizontal:N \arrayrulewidth } }
+ }
+ {
+ \exp_args:NNe
+ \clist_if_in:NnTF \l_@@_vlines_clist { \int_eval:n { \c@jCol + 1 } }
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ { @ { #1 \skip_horizontal:N \arrayrulewidth } }
+ }
+ { \tl_gput_right:Nn \g_@@_array_preamble_tl { @ { #1 } } }
+ }
+ \@@_rec_preamble:n
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new:cpn { @@ _ * } #1 #2 #3
+ {
+ \tl_clear:N \l_tmpa_tl
+ \int_step_inline:nn { #2 } { \tl_put_right:Nn \l_tmpa_tl { #3 } }
+ \exp_last_unbraced:No \@@_rec_preamble:n \l_tmpa_tl
+ }
+% \end{macrocode}
+%
+% \bigskip
+% The token |\NC@find| is at the head of the definition of the columns type done
+% by |\newcolumntype|. We wan't that token to be no-op here.
+% \begin{macrocode}
+\cs_new:cpn { @@ _ \token_to_str:N \NC@find } #1 { \@@_rec_preamble:n }
+% \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:Npn \@@_X #1 #2
+ {
+ \str_if_eq:nnTF { #2 } { [ }
+ { \@@_make_preamble_X:w [ }
+ { \@@_make_preamble_X:w [ ] #2 }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_X:w [ #1 ]
+ { \@@_make_preamble_X_i: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 \@@_make_preamble_X_i: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}
+ \str_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_eq:NN \l_@@_weight_int \c_one_int
+ \@@_keys_p_column:n { #1 }
+% \end{macrocode}
+% The unknown keys are put in |\l_tmpa_tl|
+% \begin{macrocode}
+ \keys_set:no { WithArrows / X-column } \l_tmpa_tl
+ \int_compare:nNnT \l_@@_weight_int < \c_zero_int
+ {
+ \@@_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:Nne
+ \@@_make_preamble_ii_iv:nnn
+ { \l_@@_weight_int \l_@@_X_columns_dim }
+ { minipage }
+ { \@@_no_update_width: }
+ }
+ {
+ \tl_gput_right:Nn \g_@@_array_preamble_tl
+ {
+ > {
+ \@@_cell_begin:w
+ \bool_set_true:N \l_@@_X_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
+ \@@_rec_preamble_after_col:n
+ }
+ }
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_no_update_width:
+ {
+ \tl_gput_right:Nn \g_@@_cell_after_hook_tl
+ { \cs_set_eq:NN \@@_update_max_cell_width: \prg_do_nothing: }
+ }
+% \end{macrocode}
+%
+% \medskip
+% For the letter set by the user with |vlines-in-sub-matrix| (vlism).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_preamble_vlism:n #1
+ {
+ \seq_gput_right:Nx \g_@@_cols_vlism_seq
+ { \int_eval:n { \c@jCol + 1 } }
+ \tl_gput_right:Nx \g_@@_array_preamble_tl
+ { \exp_not:N ! { \skip_horizontal:N \arrayrulewidth } }
+ \@@_rec_preamble:n
+ }
+% \end{macrocode}
+%
+% \medskip
+% The token |\stop| is a marker that we have inserted to mark the end of the
+% preamble (as provided by the final user) that we have inserted in the TeX flow.
+% \begin{macrocode}
+\cs_set_eq:cN { @@ _ \token_to_str:N \stop } \use_none:n
+% \end{macrocode}
+%
+% \medskip
+% The following lines try to catch some errors (when the final user has
+% forgotten the preamble of its environment).
+% \begin{macrocode}
+\cs_new_protected:cpn { @@ _ \token_to_str:N \hline }
+ { \@@_fatal:n { Preamble~forgotten } }
+\cs_set_eq:cc { @@ _ \token_to_str:N \Hline } { @@ _ \token_to_str:N \hline }
+\cs_set_eq:cc { @@ _ \token_to_str:N \toprule } { @@ _ \token_to_str:N \hline }
+\cs_set_eq:cc { @@ _ \token_to_str:N \CodeBefore } { @@ _ \token_to_str:N \hline }
+% \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 }
+ \cs_set_eq:NN \@@_update_max_cell_width: \prg_do_nothing: % added 2023-10-04
+ \begingroup
+ \cs_set:Npn \@addamp
+ { \legacy_if:nTF { @firstamp } { \@firstampfalse } { \@preamerr 5 } }
+% \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
+ \@@_make_m_preamble:n #2 \q_stop
+% \end{macrocode}
+%
+% \medskip
+% The following lines are an adaptation of the definition of |\multicolumn| in
+% \pkg{array}.
+% \begin{macrocode}
+ \exp_args:No \@mkpream \g_@@_preamble_tl
+ \@addtopreamble \@empty
+ \endgroup
+% \end{macrocode}
+%
+% \medskip
+% Now, we do a treatment specific to \pkg{nicematrix} which has no equivalent
+% in the original definition of |\multicolumn|.
+% \begin{macrocode}
+ \int_compare:nNnT { #1 } > \c_one_int
+ {
+ \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_if_zero:nTF \c@jCol
+ { \int_eval:n { \c@iRow + 1 } }
+ { \int_use:N \c@iRow }
+ }
+ { \int_eval:n { \c@jCol + 1 } }
+ {
+ \int_if_zero:nTF \c@jCol
+ { \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 \@@_make_m_preamble:n #1
+ {
+ \str_case:nnF { #1 }
+ {
+ c { \@@_make_m_preamble_i:n #1 }
+ l { \@@_make_m_preamble_i:n #1 }
+ r { \@@_make_m_preamble_i:n #1 }
+ > { \@@_make_m_preamble_ii:nn #1 }
+ ! { \@@_make_m_preamble_ii:nn #1 }
+ @ { \@@_make_m_preamble_ii:nn #1 }
+ | { \@@_make_m_preamble_iii:n #1 }
+ p { \@@_make_m_preamble_iv:nnn t #1 }
+ m { \@@_make_m_preamble_iv:nnn c #1 }
+ b { \@@_make_m_preamble_iv:nnn b #1 }
+ w { \@@_make_m_preamble_v:nnnn { } #1 }
+ W { \@@_make_m_preamble_v:nnnn { \@@_special_W: } #1 }
+ \q_stop { }
+ }
+ {
+ \cs_if_exist:cTF { NC @ find @ #1 }
+ {
+ \tl_set_eq:Nc \l_tmpa_tl { NC @ rewrite @ #1 }
+ \exp_last_unbraced:No \@@_make_m_preamble:n \l_tmpa_tl
+ }
+ {
+ \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 \@@_make_m_preamble_i:n #1
+ {
+ \tl_gput_right:Nn \g_@@_preamble_tl
+ {
+ > { \@@_cell_begin:w \cs_set_nopar:Npn \l_@@_hpos_cell_tl { #1 } }
+ #1
+ < \@@_cell_end:
+ }
+% \end{macrocode}
+%
+% We test for the presence of a |<|.
+% \begin{macrocode}
+ \@@_make_m_preamble_x:n
+ }
+% \end{macrocode}
+%
+% \medskip
+% For |>|, |!| and |@|
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_m_preamble_ii:nn #1 #2
+ {
+ \tl_gput_right:Nn \g_@@_preamble_tl { #1 { #2 } }
+ \@@_make_m_preamble:n
+ }
+% \end{macrocode}
+%
+%
+% \medskip
+% For \verb+|+
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_m_preamble_iii:n #1
+ {
+ \tl_gput_right:Nn \g_@@_preamble_tl { #1 }
+ \@@_make_m_preamble:n
+ }
+% \end{macrocode}
+%
+% \medskip
+% For |p|, |m| and |b|
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_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}
+ \@@_make_m_preamble_x:n
+ }
+% \end{macrocode}
+%
+% \medskip
+% For |w| and |W|
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_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
+ \cs_set_nopar:Npn \l_@@_hpos_cell_tl { #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}
+ \@@_make_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 \@@_make_m_preamble_x:n #1
+ {
+ \str_if_eq:nnTF { #1 } { < }
+ \@@_make_m_preamble_ix:n
+ { \@@_make_m_preamble:n { #1 } }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_make_m_preamble_ix:n #1
+ {
+ \tl_gput_right:Nn \g_@@_preamble_tl { < { #1 } }
+ \@@_make_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_@@_c_tl
+ { \box_use_drop:N \l_tmpa_box }
+ \@@_put_box_in_flow_i:
+ }
+% \end{macrocode}
+%
+% \bigskip
+%
+% \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}
+ \tl_if_in:NnTF \l_@@_baseline_tl { line- }
+ {
+ \int_set:Nn \l_tmpa_int
+ {
+ \str_range:Nnn
+ \l_@@_baseline_tl
+ 6
+ { \tl_count:o \l_@@_baseline_tl }
+ }
+ \@@_qpoint:n { row - \int_use:N \l_tmpa_int }
+ }
+ {
+ \tl_if_eq:NnTF \l_@@_baseline_tl { t }
+ { \int_set_eq:NN \l_tmpa_int \c_one_int }
+ {
+ \tl_if_eq:NnTF \l_@@_baseline_tl { 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_eq:NN \l_tmpa_int \c_one_int
+ }
+ \@@_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_if:NT \l_@@_NiceMatrix_without_vlines_bool
+ {
+ \int_compare:nNnT \c@jCol > \c_one_int
+ {
+ \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 > \c_zero_int
+ {
+ \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:o \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 }
+% \end{macrocode}
+% In some circonstancies (in particular when the package \pkg{caption} is
+% loaded), the caption is composed several times. That's why, when the same
+% tabular note is encountered (in the caption!), we consider that you are in the
+% second compilation and you can give to |\g_@@_notes_caption_int| its final
+% value, which is the number of tabular notes in the caption. But sometimes, the
+% caption is composed only once. In that case, we fix the value of
+% |\g_@@_caption_finished_bool| now.
+% \begin{macrocode}
+ \bool_if:NF \g_@@_caption_finished_bool
+ {
+ \bool_gset_true:N \g_@@_caption_finished_bool
+ \int_gset_eq:NN \g_@@_notes_caption_int \c@tabularnote
+ \int_gzero:N \c@tabularnote
+ }
+ \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 > \c_zero_int
+ {
+ \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
+% curryfication.
+% \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_if_zero:nT \l_@@_first_row_int
+ {
+ \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 }
+ { \cs_set_nopar:Npn \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:o \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_if_zero:nT \l_@@_first_row_int
+ {
+ \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:| because
+% of compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}).
+% \begin{macrocode}
+ \exp_args:No \@@_array: \g_@@_array_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
+ \bool_if:NTF \l_@@_light_syntax_expanded_bool
+ \seq_set_split:Nee
+ \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:No \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| in order to allow the use of commands such as
+% |\hline| or |\hdottedline| with the key |light-syntax|).
+% \begin{macrocode}
+ \tl_build_begin: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:o \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_build_put_right:Nn \l_@@_new_body_tl { \\ }
+ \@@_line_with_light_syntax:n { ##1 }
+ }
+ \tl_build_end:N \l_@@_new_body_tl
+% \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}
+% \bigskip
+%
+% The call to |\array| is in the following command (we have a dedicated macro
+% |\@@_array:| because of compatibility with the classes \cls{revtex4-1} and
+% \cls{revtex4-2}).
+% \begin{macrocode}
+ \exp_args:No \@@_array: \g_@@_array_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
+ \exp_args:NNo \tl_build_put_right:Nn \l_@@_new_body_tl \l_tmpa_tl
+ \seq_map_inline:Nn \l_@@_cells_seq
+ { \tl_build_put_right:Nn \l_@@_new_body_tl { & ##1 } }
+ }
+\cs_generate_variant:Nn \@@_line_with_light_syntax:n { o }
+% \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:onT \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_if_zero:nT \l_@@_first_col_int
+ {
+ \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_if_zero:nTF \l_@@_first_col_int
+ {
+ \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 that 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 we will
+% add some dimensions to it.
+% \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_gadd:Nn \g_tmpa_skip \g_@@_max_cell_width_dim }
+ { \skip_gadd: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_eq:NN \g_tmpa_int \c_one_int
+ \bool_if:NTF \g_@@_last_col_found_bool
+ { \prg_replicate:nn { \int_max:nn { \g_@@_col_total_int - 3 } \c_zero_int } }
+ { \prg_replicate:nn { \int_max:nn { \g_@@_col_total_int - 2 } \c_zero_int } }
+ {
+ &
+ \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_if_zero:nT \g_@@_col_total_int
+ { \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_any:nF % modified 2023/12/13
+ {
+ \g_@@_delims_bool
+ \l_@@_tabular_bool
+ { ! \clist_if_empty_p:N \l_@@_vlines_clist }
+ \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_if:NT \l_@@_NiceMatrix_without_vlines_bool
+ { \skip_horizontal:N -\arraycolsep }
+ \pgfsys@markposition
+ { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } }
+ \skip_horizontal:N 0.5\arrayrulewidth
+ \bool_if:NT \l_@@_NiceMatrix_without_vlines_bool
+ { \skip_horizontal:N \arraycolsep }
+ }
+ }
+ \pgfpicture
+ \pgfrememberpicturepositiononpagetrue
+ \pgfcoordinate { \@@_env: - col - \int_eval:n { \g_tmpa_int + 1 } }
+ {
+ \bool_if:NT \l_@@_NiceMatrix_without_vlines_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
+ \skip_horizontal:N \col@sep % added 2023-11-05
+ \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:
+ \@@_tuning_key_small:
+% \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}
+ \int_compare:nNnT \c@iRow > \c_zero_int
+ {
+ \bool_lazy_or:nnT
+ { \int_compare_p:nNn \l_@@_last_row_int < \c_zero_int }
+ { \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:
+ \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
+ {
+ >
+ {
+ \bool_set_true:N \l_@@_in_last_col_bool
+% \end{macrocode}
+% At the beginning of the cell, we link |\CodeAfter| to a command which
+% 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:
+ \@@_tuning_key_small:
+% \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 > \c_zero_int
+ {
+ \bool_lazy_or:nnT
+ { \int_compare_p:nNn \l_@@_last_row_int < \c_zero_int }
+ { \int_compare_p:nNn \c@iRow < \l_@@_last_row_int }
+ {
+ \l_@@_code_for_last_col_tl
+ \xglobal \colorlet { nicematrix-last-col } { . }
+ }
+ }
+ }
+ l
+ <
+ {
+ \@@_math_toggle:
+ \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}|.
+% \begin{macrocode}
+\NewDocumentEnvironment { NiceArray } { }
+ {
+ \bool_gset_false:N \g_@@_delims_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_@@_delims_bool| is set to false).
+% \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_true:N \g_@@_delims_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_false:N \l_@@_preamble_bool
+ \tl_clear:N \l_tmpa_tl
+ \bool_if:NT \l_@@_NiceMatrix_without_vlines_bool
+ { \tl_set:Nn \l_tmpa_tl { @ { } } }
+ \tl_put_right:Nn \l_tmpa_tl
+ {
+ *
+ {
+ \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 }
+ }
+ \tl_set:Nn \l_tmpb_tl { \use:c { #1 NiceArray } }
+ \exp_args:No \l_tmpb_tl \l_tmpa_tl
+ }
+% \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_true:N \g_@@_delims_bool
+ \str_gset:Nn \g_@@_name_env_str { #1 NiceMatrix }
+ % added 2023/10/01
+ \int_if_zero:nT \l_@@_last_col_int
+ {
+ \bool_set_true:N \l_@@_last_col_without_value_bool
+ \int_set:Nn \l_@@_last_col_int { -1 }
+ }
+ \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 { } }
+ {
+ \str_gset:Nn \g_@@_name_env_str { NiceMatrix }
+ % added 2023/10/01
+ \int_if_zero:nT \l_@@_last_col_int
+ {
+ \bool_set_true:N \l_@@_last_col_without_value_bool
+ \int_set:Nn \l_@@_last_col_int { -1 }
+ }
+ \keys_set:nn { NiceMatrix / NiceMatrix } { #1 }
+ \bool_lazy_or:nnT
+ { \clist_if_empty_p:N \l_@@_vlines_clist }
+ { \l_@@_except_borders_bool }
+ { \bool_set_true:N \l_@@_NiceMatrix_without_vlines_bool }
+ \@@_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 }
+ \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 }
+ }
+ }
+ { }
+ \@@_settings_for_tabular:
+ \NiceArray { #2 }
+ }
+ { \endNiceArray }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_settings_for_tabular:
+ {
+ \bool_set_true:N \l_@@_tabular_bool
+ \cs_set_eq:NN \@@_math_toggle: \prg_do_nothing:
+ \cs_set_eq:NN \@@_tuning_not_tabular_begin: \prg_do_nothing:
+ \cs_set_eq:NN \@@_tuning_not_tabular_end: \prg_do_nothing:
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewDocumentEnvironment { NiceTabularX } { m O { } m ! O { } }
+ {
+ \str_gset:Nn \g_@@_name_env_str { NiceTabularX }
+ \dim_zero_new:N \l_@@_width_dim
+ \dim_set:Nn \l_@@_width_dim { #1 }
+ \keys_set:nn { NiceMatrix / NiceTabular } { #2 , #4 }
+ \@@_settings_for_tabular:
+ \NiceArray { #3 }
+ }
+ {
+ \endNiceArray
+ \int_if_zero:nT \g_@@_total_X_weight_int
+ { \@@_error:n { NiceTabularX~without~X } }
+ }
+% \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 }
+ \@@_settings_for_tabular:
+ \NiceArray { #3 }
+ }
+ { \endNiceArray }
+% \end{macrocode}
+%
+%
+% \bigskip
+% \section{After the construction of the array}
+%
+% \bigskip
+% The following command will be used when the key |rounded-corners| is in force
+% (this is the key |rounded-corners| for the whole environment and \emph{not}
+% the key |rounded-corners| of a command |\Block|).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_deal_with_rounded_corners:
+ {
+ \bool_lazy_all:nT
+ {
+ { \int_compare_p:nNn \l_@@_tab_rounded_corners_dim > \c_zero_dim }
+ \l_@@_hvlines_bool
+ { ! \g_@@_delims_bool }
+ { ! \l_@@_except_borders_bool }
+ }
+ {
+ \bool_set_true:N \l_@@_except_borders_bool
+ \clist_if_empty:NF \l_@@_corners_clist
+ { \@@_error:n { hvlines,~rounded-corners~and~corners } }
+ \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 }
+ }
+ }
+ }
+% \end{macrocode}
+%
+%
+% \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}
+ \@@_deal_with_rounded_corners:
+ \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 \TikzEveryCell \@@_TikzEveryCell
+ \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:No \@@_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 |color-inside| 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}
+ \seq_if_empty:NF \g_@@_rowlistcolors_seq { \@@_clear_rowlistcolors_seq: }
+ \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:o \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:o \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 } = \c_one_int
+ { \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 } = \c_one_int
+ { \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 } = \c_one_int
+ { \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 } = \c_one_int
+ { \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
+% If the final user uses the key |xdots/shorten| in |\NiceMatrixOptions| or at the
+% level of an environment (such as |{pNiceMatrix}|, etc.), only the so called
+% ``closed extremities'' will be shortened by that key. The following command
+% will be used \emph{after} the detection of the extremities of a dotted line
+% (hence at a time when we known wheter the extremities are closed or open) but
+% before the analyse of the keys of the individual command |\Cdots|, |\Vdots|.
+% Hence, the keys |shorten|, |shorten-start| and |shorten-end| of that
+% individual command will be applied.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_open_shorten:
+ {
+ \bool_if:NT \l_@@_initial_open_bool
+ { \dim_zero:N \l_@@_xdots_shorten_start_dim }
+ \bool_if:NT \l_@@_final_open_bool
+ { \dim_zero:N \l_@@_xdots_shorten_end_dim }
+ }
+% \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
+ {
+ \int_compare:nNnF { #3 } > { #1 }
+ {
+ \int_compare:nNnF { #1 } > { #5 }
+ {
+ \int_compare:nNnF { #4 } > { #2 }
+ {
+ \int_compare:nNnF { #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 column 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:
+ \@@_open_shorten:
+ \int_if_zero:nTF { #1 }
+ { \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:oF \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}
+% Now the case of a |\Hdotsfor| (or when there is only a |\Ldots|) in the ``last
+% row'' (that case will probably arise when the final user draws an arrow to
+% indicate the number of columns of the matrix). In the ``first row'', we don't
+% need any adjustment.
+% \begin{macrocode}
+ \bool_lazy_all:nTF
+ {
+ \l_@@_initial_open_bool
+ \l_@@_final_open_bool
+ { \int_compare_p:nNn \l_@@_initial_i_int = \l_@@_last_row_int }
+ }
+ {
+ \dim_add:Nn \l_@@_y_initial_dim \c_@@_shift_Ldots_last_row_dim
+ \dim_add:Nn \l_@@_y_final_dim \c_@@_shift_Ldots_last_row_dim
+ }
+% \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:
+ \@@_open_shorten:
+ \int_if_zero:nTF { #1 }
+ { \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:oF \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:
+ {
+ \dim_set:Nn \l_@@_y_initial_dim { - \c_max_dim }
+ \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 }
+ }
+ }
+ \dim_compare:nNnT \l_@@_y_initial_dim = { - \c_max_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
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_open_y_final_dim:
+ {
+ \dim_set_eq:NN \l_@@_y_final_dim \c_max_dim
+ \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 }
+ }
+ }
+ \dim_compare:nNnT \l_@@_y_final_dim = \c_max_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 } }
+ }
+ }
+% \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:
+ \@@_open_shorten:
+ \int_if_zero:nTF { #2 }
+ { \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:oF \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}
+%
+% First, the case of a dotted line open on both sides.
+% \begin{macrocode}
+ \bool_lazy_and:nnTF \l_@@_initial_open_bool \l_@@_final_open_bool
+% \end{macrocode}
+%
+% We have to determine the $x$-value of the vertical rule that we will have
+% to draw.
+% \begin{macrocode}
+ {
+ \@@_open_y_initial_dim:
+ \@@_open_y_final_dim:
+ \int_if_zero:nTF \l_@@_initial_j_int
+% \end{macrocode}
+% We have a dotted line open on both sides in the ``first column''.
+% \begin{macrocode}
+ {
+ \@@_qpoint:n { col - 1 }
+ \dim_set_eq:NN \l_@@_x_initial_dim \pgf@x
+ \dim_sub:Nn \l_@@_x_initial_dim \l_@@_left_margin_dim
+ \dim_sub:Nn \l_@@_x_initial_dim \l_@@_extra_left_margin_dim
+ \dim_sub:Nn \l_@@_x_initial_dim \c_@@_shift_exterior_Vdots_dim
+ }
+ {
+ \bool_lazy_and:nnTF
+ { \int_compare_p:nNn \l_@@_last_col_int > { -2 } }
+ { \int_compare_p:nNn \l_@@_initial_j_int = \g_@@_col_total_int }
+% \end{macrocode}
+% We have a dotted line open on both sides in the ``last column''.
+% \begin{macrocode}
+ {
+ \@@_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 \l_@@_right_margin_dim
+ \dim_add:Nn \l_@@_x_initial_dim \l_@@_extra_right_margin_dim
+ \dim_add:Nn \l_@@_x_initial_dim \c_@@_shift_exterior_Vdots_dim
+ }
+% \end{macrocode}
+% We have a dotted line open on both sides which is \emph{not} in an exterior column.
+% \begin{macrocode}
+ {
+ \@@_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 }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% Now, the dotted line is \emph{not} open on both sides (maybe open on only one side).
+%
+% The boolean |\l_tmpa_bool| will indicate whether the column is of type |l| or
+% may be considered as if.
+% \begin{macrocode}
+ {
+ \bool_set_false:N \l_tmpa_bool
+ \bool_if:NF \l_@@_initial_open_bool
+ {
+ \bool_if:NF \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_final_coords_from_anchor:n { north }
+ \dim_set_eq:NN \l_@@_x_initial_dim \l_@@_x_final_dim
+ }
+ {
+ \@@_set_initial_coords_from_anchor:n { south }
+ \bool_if:NTF \l_@@_final_open_bool
+ \@@_open_y_final_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}
+ {
+ \@@_set_final_coords_from_anchor:n { north }
+ \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:
+ \@@_open_shorten:
+ \keys_set:nn { NiceMatrix / xdots } { #3 }
+ \tl_if_empty:oF \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 = \c_one_int
+% \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:
+ \@@_open_shorten:
+ \keys_set:nn { NiceMatrix / xdots } { #3 }
+ \tl_if_empty:oF \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 = \c_one_int
+ {
+ \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:No| 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:nooo
+ { #1 }
+ \l_@@_xdots_up_tl
+ \l_@@_xdots_down_tl
+ \l_@@_xdots_middle_tl
+ }
+\cs_generate_variant:Nn \@@_draw_unstandard_dotted_line:n { o }
+% \end{macrocode}
+%
+%
+% \bigskip
+% The following Tikz styles are for the three labels (set by the symbols |_|,
+% |^| and |=|) of a continous line with a non-standard style.
+% \begin{macrocode}
+\hook_gput_code:nnn { begindocument } { . }
+ {
+ \IfPackageLoadedTF { tikz }
+ {
+ \tikzset
+ {
+ @@_node_above / .style = { sloped , above } ,
+ @@_node_below / .style = { sloped , below } ,
+ @@_node_middle / .style =
+ {
+ sloped ,
+ inner~sep = \c_@@_innersep_middle_dim
+ }
+ }
+ }
+ { }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_unstandard_dotted_line:nnnn #1 #2 #3 #4
+ {
+% \end{macrocode}
+% We take into account the parameters |xdots/shorten-start| and
+% |xdots/shorten-end| ``by hand'' because, when we use the key |shorten >| and
+% |shorten <| of TikZ in the command |\draw|, we don't have the expected output
+% with |{decorate,decoration=brace}| is used.
+%
+% \medskip
+% 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}
+ \dim_compare:nNnT \l_@@_l_dim < \c_@@_max_l_dim
+ {
+ \dim_compare:nNnT \l_@@_l_dim > { 1 pt }
+ \@@_draw_unstandard_dotted_line_i:
+ }
+% \end{macrocode}
+%
+% If the key |xdots/horizontal-labels| has been used.
+% \begin{macrocode}
+ \bool_if:NT \l_@@_xdots_h_labels_bool
+ {
+ \tikzset
+ {
+ @@_node_above / .style = { auto = left } ,
+ @@_node_below / .style = { auto = right } ,
+ @@_node_middle / .style = { inner~sep = \c_@@_innersep_middle_dim }
+ }
+ }
+ \tl_if_empty:nF { #4 }
+ { \tikzset { @@_node_middle / .append~style = { fill = white } } }
+ \draw
+ [ #1 ]
+ ( \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 [ @@_node_middle] { $ \scriptstyle #4 $ }
+ node [ @@_node_below ] { $ \scriptstyle #3 $ }
+ node [ @@_node_above ] { $ \scriptstyle #2 $ }
+ ( \l_@@_x_final_dim , \l_@@_y_final_dim ) ;
+ \end { scope }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_unstandard_dotted_line_i:
+ {
+ \dim_set:Nn \l_tmpa_dim
+ {
+ \l_@@_x_initial_dim
+ + ( \l_@@_x_final_dim - \l_@@_x_initial_dim )
+ * \dim_ratio:nn \l_@@_xdots_shorten_start_dim \l_@@_l_dim
+ }
+ \dim_set:Nn \l_tmpb_dim
+ {
+ \l_@@_y_initial_dim
+ + ( \l_@@_y_final_dim - \l_@@_y_initial_dim )
+ * \dim_ratio:nn \l_@@_xdots_shorten_start_dim \l_@@_l_dim
+ }
+ \dim_set:Nn \l_@@_tmpc_dim
+ {
+ \l_@@_x_final_dim
+ - ( \l_@@_x_final_dim - \l_@@_x_initial_dim )
+ * \dim_ratio:nn \l_@@_xdots_shorten_end_dim \l_@@_l_dim
+ }
+ \dim_set:Nn \l_@@_tmpd_dim
+ {
+ \l_@@_y_final_dim
+ - ( \l_@@_y_final_dim - \l_@@_y_initial_dim )
+ * \dim_ratio:nn \l_@@_xdots_shorten_end_dim \l_@@_l_dim
+ }
+ \dim_set_eq:NN \l_@@_x_initial_dim \l_tmpa_dim
+ \dim_set_eq:NN \l_@@_y_initial_dim \l_tmpb_dim
+ \dim_set_eq:NN \l_@@_x_final_dim \l_@@_tmpc_dim
+ \dim_set_eq:NN \l_@@_y_final_dim \l_@@_tmpd_dim
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_generate_variant:Nn \@@_draw_unstandard_dotted_line:nnnn { n o o o }
+% \end{macrocode}
+%
+% \bigskip
+% The command |\@@_draw_standard_dotted_line:| draws the line with our system of dots
+% (which gives a dotted line with real rounded dots).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_standard_dotted_line:
+ {
+ \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}
+ \dim_compare:nNnT \l_@@_l_dim < \c_@@_max_l_dim
+ {
+ \dim_compare:nNnT \l_@@_l_dim > { 1 pt }
+ \@@_draw_standard_dotted_line_i:
+ }
+ \group_end:
+% \end{macrocode}
+% \begin{macrocode}
+ \bool_lazy_all:nF
+ {
+ { \tl_if_empty_p:N \l_@@_xdots_up_tl }
+ { \tl_if_empty_p:N \l_@@_xdots_down_tl }
+ { \tl_if_empty_p:N \l_@@_xdots_middle_tl }
+ }
+ \l_@@_labels_standard_dotted_line:
+ }
+% \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}
+ \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 \c_zero_int \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
+% \begin{macrocode}
+\cs_new_protected:Npn \l_@@_labels_standard_dotted_line:
+ {
+ \pgfscope
+ \pgftransformshift
+ {
+ \pgfpointlineattime { 0.5 }
+ { \pgfpoint \l_@@_x_initial_dim \l_@@_y_initial_dim }
+ { \pgfpoint \l_@@_x_final_dim \l_@@_y_final_dim }
+ }
+ \fp_set:Nn \l_tmpa_fp
+ {
+ atand
+ (
+ \l_@@_y_final_dim - \l_@@_y_initial_dim ,
+ \l_@@_x_final_dim - \l_@@_x_initial_dim
+ )
+ }
+ \pgftransformrotate { \fp_use:N \l_tmpa_fp }
+ \bool_if:NF \l_@@_xdots_h_labels_bool { \fp_zero:N \l_tmpa_fp }
+ \tl_if_empty:NF \l_@@_xdots_middle_tl
+ {
+ \begin { pgfscope }
+ \pgfset { inner~sep = \c_@@_innersep_middle_dim }
+ \pgfnode
+ { rectangle }
+ { center }
+ {
+ \rotatebox { \fp_eval:n { - \l_tmpa_fp } }
+ {
+ \c_math_toggle_token
+ \scriptstyle \l_@@_xdots_middle_tl
+ \c_math_toggle_token
+ }
+ }
+ { }
+ {
+ \pgfsetfillcolor { white }
+ \pgfusepath { fill }
+ }
+ \end { pgfscope }
+ }
+ \tl_if_empty:NF \l_@@_xdots_up_tl
+ {
+ \pgfnode
+ { rectangle }
+ { south }
+ {
+ \rotatebox { \fp_eval:n { - \l_tmpa_fp } }
+ {
+ \c_math_toggle_token
+ \scriptstyle \l_@@_xdots_up_tl
+ \c_math_toggle_token
+ }
+ }
+ { }
+ { \pgfusepath { } }
+ }
+ \tl_if_empty:NF \l_@@_xdots_down_tl
+ {
+ \pgfnode
+ { rectangle }
+ { north }
+ {
+ \rotatebox { \fp_eval:n { - \l_tmpa_fp } }
+ {
+ \c_math_toggle_token
+ \scriptstyle \l_@@_xdots_down_tl
+ \c_math_toggle_token
+ }
+ }
+ { }
+ { \pgfusepath { } }
+ }
+ \endpgfscope
+ }
+% \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 } { . }
+ {
+ \cs_set_nopar:Npn \l_@@_argspec_tl { m E { _ ^ : } { { } { } { } } }
+ \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl
+ \cs_new_protected:Npn \@@_Ldots
+ { \@@_collect_options:n { \@@_Ldots_i } }
+ \exp_args:NNo \NewDocumentCommand \@@_Ldots_i \l_@@_argspec_tl
+ {
+ \int_if_zero:nTF \c@jCol
+ { \@@_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 , middle = #4 }
+ }
+ }
+ \bool_if:NF \l_@@_nullify_dots_bool
+ { \phantom { \ensuremath { \@@_old_ldots } } }
+ \bool_gset_true:N \g_@@_empty_cell_bool
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+ \cs_new_protected:Npn \@@_Cdots
+ { \@@_collect_options:n { \@@_Cdots_i } }
+ \exp_args:NNo \NewDocumentCommand \@@_Cdots_i \l_@@_argspec_tl
+ {
+ \int_if_zero:nTF \c@jCol
+ { \@@_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 , middle = #4 }
+ }
+ }
+ \bool_if:NF \l_@@_nullify_dots_bool
+ { \phantom { \ensuremath { \@@_old_cdots } } }
+ \bool_gset_true:N \g_@@_empty_cell_bool
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+ \cs_new_protected:Npn \@@_Vdots
+ { \@@_collect_options:n { \@@_Vdots_i } }
+ \exp_args:NNo \NewDocumentCommand \@@_Vdots_i \l_@@_argspec_tl
+ {
+ \int_if_zero:nTF \c@iRow
+ { \@@_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 , middle = #4 }
+ }
+ }
+ \bool_if:NF \l_@@_nullify_dots_bool
+ { \phantom { \ensuremath { \@@_old_vdots } } }
+ \bool_gset_true:N \g_@@_empty_cell_bool
+ }
+% \end{macrocode}
+%
+%
+% \bigskip
+% \begin{macrocode}
+ \cs_new_protected:Npn \@@_Ddots
+ { \@@_collect_options:n { \@@_Ddots_i } }
+ \exp_args:NNo \NewDocumentCommand \@@_Ddots_i \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 , middle = #4 }
+ }
+
+ }
+ \bool_if:NF \l_@@_nullify_dots_bool
+ { \phantom { \ensuremath { \@@_old_ddots } } }
+ \bool_gset_true:N \g_@@_empty_cell_bool
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+ \cs_new_protected:Npn \@@_Iddots
+ { \@@_collect_options:n { \@@_Iddots_i } }
+ \exp_args:NNo \NewDocumentCommand \@@_Iddots_i \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 , middle = #4 }
+ }
+ }
+ \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_if_zero_p:n \c@jCol }
+ { \int_if_zero_p:n \l_@@_first_col_int }
+ {
+ \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 } { . }
+ {
+ \cs_set_nopar:Npn \l_@@_argspec_tl { m 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}
+ \cs_new_protected:Npn \@@_Hdotsfor_i
+ { \@@_collect_options:n { \@@_Hdotsfor_ii } }
+ \exp_args:NNo \NewDocumentCommand \@@_Hdotsfor_ii \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 } ,
+ middle = \exp_not:n { #6 }
+ }
+ }
+ \prg_replicate:nn { #2 - 1 }
+ {
+ &
+ \multicolumn { 1 } { c } { }
+ \cs_set_eq:NN \CodeAfter \@@_CodeAfter_i:
+ }
+ }
+ }
+% \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 } = \c_one_int
+ {
+ \int_set_eq:NN \l_@@_initial_j_int \c_one_int
+ \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:
+ \@@_open_shorten:
+ \int_if_zero:nTF { #1 }
+ { \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:oF \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 } { . }
+ {
+ \cs_set_nopar:Npn \l_@@_argspec_tl { m m O { } E { _ ^ : } { { } { } { } } }
+ \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl
+ \cs_new_protected:Npn \@@_Vdotsfor:
+ { \@@_collect_options:n { \@@_Vdotsfor_i } }
+ \exp_args:NNo \NewDocumentCommand \@@_Vdotsfor_i \l_@@_argspec_tl
+ {
+ \bool_gset_true:N \g_@@_empty_cell_bool
+ \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 } ,
+ middle = \exp_not:n { #6 }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \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 } = \c_one_int
+ {
+ \int_set_eq:NN \l_@@_initial_i_int \c_one_int
+ \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:
+ \@@_open_shorten:
+ \int_if_zero:nTF { #2 }
+ { \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:oF \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}
+\NewDocumentCommand \@@_rotate: { O { } }
+ {
+ \peek_remove_spaces:n
+ {
+ \bool_gset_true:N \g_@@_rotate_bool
+ \keys_set:nn { NiceMatrix / rotate } { #1 }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\keys_define:nn { NiceMatrix / rotate }
+ {
+ c .code:n = \bool_gset_true:N \g_@@_rotate_c_bool ,
+ c .value_forbidden:n = true ,
+ unknown .code:n = \@@_error:n { Unknown~key~for~rotate }
+ }
+% \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. In
+% fact, if also works with names of blocks.
+%
+% \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 } { . }
+ {
+ \cs_set_nopar:Npn \l_@@_argspec_tl
+ { O { } m m ! O { } E { _ ^ : } { { } { } { } } }
+ \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl
+ \exp_args:NNo \NewDocumentCommand \@@_line \l_@@_argspec_tl
+ {
+ \group_begin:
+ \keys_set:nn { NiceMatrix / xdots } { #1 , #4 , down = #5 , up = #6 }
+ \tl_if_empty:oF \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_lazy_or:nnTF
+ { \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 } }
+% \end{macrocode}
+% The test of |measuring@| is a security (cf. question 686649 on TeX StackExchange).
+% \begin{macrocode}
+ { \legacy_if:nF { measuring@ } { \@@_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}
+%
+%
+% |\g_@@_row_style_tl| may contain several instructions of the form:
+%
+% \qquad |\@@_if_row_less_than:nn { number } { instructions }|
+%
+% \smallskip
+% Then, |\g_@@_row_style_tl| will be inserted in all the cells of the array (and
+% also in both components of a |\diagbox| in a cell of in a mono-row block).
+%
+% The test |\@@_if_row_less_then:nn| ensures that the instructions are inserted
+% only if you are in a row which is (still) in the scope of that instructions
+% (which depends on the value of the key |nb-rows| of |\RowStyle|).
+%
+% That test will be active even in an expandable context because
+% |\@@_if_row_less_then:nn| is \emph{not} protected.
+%
+% |#1| is the first row \emph{after} the scope of the instructions in |#2|
+% \begin{macrocode}
+\cs_new:Npn \@@_if_row_less_than:nn #1 #2
+ { \int_compare:nNnT { \c@iRow } < { #1 } { #2 } }
+% \end{macrocode}
+%
+% \bigskip
+% |\@@_put_in_row_style| will be used several times by |\RowStyle|.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_put_in_row_style:n #1
+ {
+ \tl_gput_right:Nx \g_@@_row_style_tl
+ {
+% \end{macrocode}
+% Be careful, |\exp_not:N \@@_if_row_less_than:nn| can't be replaced by a
+% protected version of |\@@_if_row_less_than:nn|.
+% \begin{macrocode}
+ \exp_not:N
+ \@@_if_row_less_than:nn
+ { \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int } }
+% \end{macrocode}
+% The |\scan_stop:| is mandatory (for ex. for the case where |\rotate| is used
+% in the argument of |\RowStyle|).
+% \begin{macrocode}
+ { \exp_not:n { #1 } \scan_stop: }
+ }
+ }
+\cs_generate_variant:Nn \@@_put_in_row_style:n { e }
+% \end{macrocode}
+% \medskip
+% \begin{macrocode}
+\keys_define:nn { NiceMatrix / RowStyle }
+ {
+ cell-space-top-limit .dim_set:N = \l_tmpa_dim ,
+ cell-space-top-limit .value_required:n = true ,
+ cell-space-bottom-limit .dim_set:N = \l_tmpb_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_@@_bold_row_style_bool ,
+ bold .default:n = true ,
+ 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 ,
+ 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
+ \tl_clear:N \l_@@_color_tl
+ \int_set_eq:NN \l_@@_key_nb_rows_int \c_one_int
+ \dim_zero:N \l_tmpa_dim
+ \dim_zero:N \l_tmpb_dim
+ \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:No| is \emph{fully expandable}.
+% \begin{macrocode}
+ \@@_exp_color_arg:No \@@_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 > \c_one_int
+ {
+ \tl_gput_right:Nx \g_@@_pre_code_before_tl
+ {
+ \@@_exp_color_arg:No \@@_rowcolor \l_tmpa_tl
+ {
+ \int_eval:n { \c@iRow + 1 }
+ - \int_eval:n { \c@iRow + \l_@@_key_nb_rows_int - 1 }
+ }
+ }
+ }
+ }
+ \@@_put_in_row_style:n { \exp_not:n { #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
+ {
+ \exp_args:Nx \@@_put_in_row_style:n
+ {
+ \tl_gput_right:Nn \exp_not:N \g_@@_cell_after_hook_tl
+ {
+% \end{macrocode}
+% It's not possible to chanage the following code by using |\dim_set_eq:NN|
+% (because of expansion).
+% \begin{macrocode}
+ \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
+ {
+ \exp_args:Nx \@@_put_in_row_style:n
+ {
+ \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
+ {
+ \@@_put_in_row_style:e
+ {
+ \mode_leave_vertical:
+ \@@_color:n { \l_@@_color_tl }
+ }
+ }
+% \end{macrocode}
+% |\l_@@_bold_row_style_bool| is the value of the key |bold|.
+% \begin{macrocode}
+ \bool_if:NT \l_@@_bold_row_style_bool
+ {
+ \@@_put_in_row_style:n
+ {
+ \exp_not:n
+ {
+ \if_mode_math:
+ \c_math_toggle_token
+ \bfseries \boldmath
+ \c_math_toggle_token
+ \else:
+ \bfseries \boldmath
+ \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_if_zero:nTF \l_tmpa_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 { e n }
+\cs_generate_variant:Nn \@@_add_to_colors_seq:nn { e e }
+% \end{macrocode}
+%
+% \bigskip
+% The following command must be used within a |\pgfpicture|.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_clip_with_rounded_corners:
+ {
+ \dim_compare:nNnT \l_@@_tab_rounded_corners_dim > \c_zero_dim
+ {
+% \end{macrocode}
+% The TeX group is for |\pgfsetcornersarced| (whose scope is the TeX scope).
+% \begin{macrocode}
+ \group_begin:
+ \pgfsetcornersarced
+ {
+ \pgfpoint
+ { \l_@@_tab_rounded_corners_dim }
+ { \l_@@_tab_rounded_corners_dim }
+ }
+% \end{macrocode}
+% 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 }
+ \group_end:
+% \end{macrocode}
+% The TeX group was for |\pgfsetcornersarced|.
+% \begin{macrocode}
+ }
+ }
+% \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}
+ \@@_clip_with_rounded_corners:
+ \seq_map_indexed_inline:Nn \g_@@_colors_seq
+ {
+ \int_compare:nNnTF { ##1 } = \c_one_int
+ {
+ \cs_set_eq:NN \@@_cartesian_path:n \@@_cartesian_path_nocolor:n
+ \use:c { g_@@_color _ 1 _tl }
+ \cs_set_eq:NN \@@_cartesian_path:n \@@_cartesian_path_normal:n
+ }
+ {
+ \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 curryfication.
+% \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:No \pgfsetfillopacity \l_tmpa_tl }
+ \tl_if_empty:NTF \l_tmpb_tl
+ { \@declaredcolor }
+ { \use:e { \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
+ {
+ \cs_set_nopar:Npn \l_@@_rows_tl { #1 }
+ \cs_set_nopar:Npn \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:en
+ { \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:en
+ { \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:en
+ { \tl_if_blank:nF { #1 } { [ #1 ] } { #2 } }
+ { \@@_rectanglecolor:nnn { #3 } { #4 } { \c_zero_dim } }
+ }
+ }
+% \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:en
+ { \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 \c@iRow
+ {
+ \int_step_inline:nn \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 |\CodeBefore|) 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]|.
+%
+% In \pkg{nicematrix}, the commmand |\@@_rowcolors| appears as a special case of
+% |\@@_rowlistcolors|.
+%
+% |#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
+ \cs_set_nopar:Npn \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_eq:NN \l_@@_color_int \c_one_int
+ \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'' (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 }
+ {
+ \cs_set_nopar:Npn \l_tmpa_tl { ##1 }
+ \tl_if_in:NnTF \l_tmpa_tl { - }
+ { \@@_cut_on_hyphen:w ##1 \q_stop }
+ { \tl_set:No \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
+ \int_set:Nn \l_@@_color_int
+ { \bool_if:NTF \l_@@_rowcolors_restart_bool 1 \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:No \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:ee
+ { \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 more general command |\rowlistcolors|. The last argument, which is a
+% optional argument between square brackets is provided by curryfication.
+% \begin{macrocode}
+\NewDocumentCommand \@@_rowcolors { O { } m m m }
+ { \@@_rowlistcolors [ #1 ] { #2 } { { #3 } , { #4 } } }
+% \end{macrocode}
+% The braces around |#3| and |#4| are mandatory.
+%
+% \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
+ {
+ \int_if_zero:nTF { #4 }
+ \prg_return_false:
+ {
+ \int_compare:nNnTF { #2 } > \c@jCol
+ \prg_return_false:
+ \prg_return_true:
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% The following command return |true| when the block intersects the row
+% |\l_tmpa_int|.
+% \begin{macrocode}
+\prg_new_conditional:Nnn \@@_intersect_our_row:nnnnn p
+ {
+ \int_compare:nNnTF { #1 } > \l_tmpa_int
+ \prg_return_false:
+ {
+ \int_compare:nNnTF \l_tmpa_int > { #3 }
+ \prg_return_false:
+ \prg_return_true:
+ }
+ }
+% \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_normal:n #1
+ {
+ \dim_compare:nNnTF { #1 } = \c_zero_dim
+ {
+ \bool_if:NTF
+ \@@_nocolor_used_bool
+ \@@_cartesian_path_normal_ii:
+ {
+ \seq_if_empty:NTF \l_@@_corners_cells_seq
+ { \@@_cartesian_path_normal_i:n { #1 } }
+ \@@_cartesian_path_normal_ii:
+ }
+ }
+ { \@@_cartesian_path_normal_i:n { #1 } }
+ }
+% \end{macrocode}
+%
+%
+% \bigskip
+% First, the situation where is a rectangular zone of cells will be colored as a
+% whole (in the instructions of the resulting \textsc{pdf}). The argument is the
+% radius of the corners.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cartesian_path_normal_i:n #1
+ {
+ \pgfsetcornersarced { \pgfpoint { #1 } { #1 } }
+% \end{macrocode}
+% We begin the loop over the columns.
+% \begin{macrocode}
+ \clist_map_inline:Nn \l_@@_cols_tl
+ {
+ \cs_set_nopar:Npn \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:NTF \l_tmpa_tl
+ { \cs_set_nopar:Npn \l_tmpa_tl { 1 } }
+ {
+ \tl_if_eq:NNT \l_tmpa_tl \c_@@_star_tl
+ { \cs_set_nopar:Npn \l_tmpa_tl { 1 } }
+ }
+ \tl_if_empty:NTF \l_tmpb_tl
+ { \tl_set:No \l_tmpb_tl { \int_use:N \c@jCol } }
+ {
+ \tl_if_eq:NNT \l_tmpb_tl \c_@@_star_tl
+ { \tl_set:No \l_tmpb_tl { \int_use:N \c@jCol } }
+ }
+ \int_compare:nNnT \l_tmpb_tl > \g_@@_col_total_int
+ { \tl_set:No \l_tmpb_tl { \int_use:N \g_@@_col_total_int } }
+% \end{macrocode}
+% |\l_@@_tmpc_tl| will contain the number of column.
+% \begin{macrocode}
+ \tl_set_eq:NN \l_@@_tmpc_tl \l_tmpa_tl
+ \@@_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
+ {
+ \cs_set_nopar:Npn \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:NTF \l_tmpa_tl
+ { \cs_set_nopar:Npn \l_tmpa_tl { 1 } }
+ {
+ \tl_if_eq:NNT \l_tmpa_tl \c_@@_star_tl
+ { \cs_set_nopar:Npn \l_tmpa_tl { 1 } }
+ }
+ \tl_if_empty:NTF \l_tmpb_tl
+ { \tl_set:No \l_tmpb_tl { \int_use:N \c@iRow } }
+ {
+ \tl_if_eq:NNT \l_tmpb_tl \c_@@_star_tl
+ { \tl_set:No \l_tmpb_tl { \int_use:N \c@iRow } }
+ }
+ \int_compare:nNnT \l_tmpb_tl > \g_@@_row_total_int
+ { \tl_set:No \l_tmpb_tl { \int_use:N \g_@@_row_total_int } }
+% \end{macrocode}
+% Now, the numbers of both rows are in |\l_tmpa_tl| and |\l_tmpb_tl|.
+% \begin{macrocode}
+ \cs_if_exist:cF
+ { @@ _ \l_tmpa_tl _ \l_@@_tmpc_tl _ nocolor }
+ {
+ \@@_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 }
+ \pgfpathrectanglecorners
+ { \pgfpoint \l_@@_tmpc_dim \l_@@_tmpd_dim }
+ { \pgfpoint \l_tmpa_dim \l_tmpb_dim }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+%
+% Now, the case where the cells will be colored cell by cell (it's mandatory for
+% example if the key |corners| is used).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cartesian_path_normal_ii:
+ {
+ \@@_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
+ {
+ \@@_qpoint:n { col - ##1 }
+ \int_compare:nNnTF \l_@@_first_col_int = { ##1 }
+ { \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 { ##1 + 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
+ {
+ \seq_if_in:NnF \l_@@_corners_cells_seq
+ { ####1 - ##1 }
+ {
+ \@@_qpoint:n { row - \int_eval:n { ####1 + 1 } }
+ \dim_set:Nn \l_tmpb_dim { \pgf@y + 0.5 \arrayrulewidth }
+ \@@_qpoint:n { row - ####1 }
+ \dim_set:Nn \l_@@_tmpd_dim { \pgf@y + 0.5 \arrayrulewidth }
+ \cs_if_exist:cF
+ { @@ _ ####1 _ ##1 _ nocolor }
+ {
+ \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 \c_zero_dim }
+% \end{macrocode}
+%
+%
+% \bigskip
+% Despite its name, the following command does not create a PGF path. It
+% declares as colored by the ``empty color'' all the cells in what would be the
+% path. Hence, the other coloring instructions of \pkg{nicematrix} won't put
+% color in those cells.
+% the
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cartesian_path_nocolor:n #1
+ {
+ \bool_set_true:N \@@_nocolor_used_bool
+ \@@_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_@@_rows_tl
+ {
+ \clist_map_inline:Nn \l_@@_cols_tl
+ { \cs_set:cpn { @@ _ ##1 _ ####1 _ nocolor } { } }
+ }
+ }
+% \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
+ {
+ \cs_set_nopar:Npn \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:o \l_tmpa_tl }
+ { \str_if_eq_p:on \l_tmpa_tl { * } }
+ { \cs_set_nopar:Npn \l_tmpa_tl { 1 } }
+ \bool_lazy_or:nnT
+ { \tl_if_blank_p:o \l_tmpb_tl }
+ { \str_if_eq_p:on \l_tmpb_tl { * } }
+ { \tl_set:No \l_tmpb_tl { \int_use:N #2 } }
+ \int_compare:nNnT \l_tmpb_tl > #2
+ { \tl_set:No \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 |color-inside|, the following command will
+% be linked to |\cellcolor| in the tabular.
+% \begin{macrocode}
+\NewDocumentCommand \@@_cellcolor_tabular { O { } m }
+ {
+ \@@_test_color_inside:
+ \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 |color-inside|, the following command will
+% be linked to |\rowcolor| in the tabular.
+% \begin{macrocode}
+\NewDocumentCommand \@@_rowcolor_tabular { O { } m }
+ {
+ \@@_test_color_inside:
+ \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
+% When the user uses the key |color-inside|, the following command will
+% be linked to |\rowcolors| in the tabular. The last argument (an optional
+% argument between square brackets is taken by curryfication).
+% \begin{macrocode}
+\NewDocumentCommand { \@@_rowcolors_tabular } { O { } m m }
+ { \@@_rowlistcolors_tabular [ #1 ] { { #2 } , { #3 } } }
+% \end{macrocode}
+% The braces around |#2| and |#3| are mandatory.
+%
+% \bigskip
+% When the user uses the key |color-inside|, the following command will
+% be linked to |\rowlistcolors| in the tabular.
+% \begin{macrocode}
+\NewDocumentCommand { \@@_rowlistcolors_tabular } { O { } m O { } }
+ {
+ \@@_test_color_inside:
+ \peek_remove_spaces:n
+ { \@@_rowlistcolors_tabular:nnn { #1 } { #2 } { #3 } }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rowlistcolors_tabular:nnn #1 #2 #3
+ {
+% \end{macrocode}
+% A use of |\rowlistcolors| in the tabular erases the instructions
+% |\rowlistcolors| which are in force. However, it's possible to put \emph{several}
+% instructions |\rowlistcolors| in the same row of a tabular: it may be useful
+% when those instructions |\rowlistcolors| concerns different columns of the
+% tabular (thanks to the key |cols| of |\rowlistcolors|). That's why we store
+% the different instructions |\rowlistcolors| which are in force in a sequence
+% |\g_@@_rowlistcolors_seq|. Now, we will filter that sequence to keep only the
+% elements which have been issued on the actual row. We will store the elements
+% to keep in the |\g_tmpa_seq|.
+% \begin{macrocode}
+ \seq_gclear:N \g_tmpa_seq
+ \seq_map_inline:Nn \g_@@_rowlistcolors_seq
+ { \@@_rowlistcolors_tabular_i:nnnn ##1 }
+ \seq_gset_eq:NN \g_@@_rowlistcolors_seq \g_tmpa_seq
+% \end{macrocode}
+% Now, we add to the sequence |\g_@@_rowlistcolors_seq| (which is the list of
+% the commands |\rowlistcolors| which are in force) the current instruction
+% |\rowlistcolors|.
+% \begin{macrocode}
+ \seq_gput_right:Nx \g_@@_rowlistcolors_seq
+ {
+ { \int_use:N \c@iRow }
+ { \exp_not:n { #1 } }
+ { \exp_not:n { #2 } }
+ { restart , cols = \int_use:N \c@jCol - , \exp_not:n { #3 } }
+ }
+ }
+% \end{macrocode}
+%
+%
+% \bigskip
+% The following command will be applied to each component of
+% |\g_@@_rowlistcolors_seq|. Each component of that sequence is a kind of 4-uple
+% of the form |{#1}{#2}{#3}{#4}|.
+%
+% |#1| is the number of the row where the command |\rowlistcolors| has been
+% issued.
+%
+% |#2| is the colorimetric space (optional argument of the |\rowlistcolors|).
+%
+% |#3| is the list of colors (mandatory argument of |\rowlistcolors|).
+%
+% |#4| is the list of \textsl{key=value} pairs (last optional argument of
+% |\rowlistcolors|).
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rowlistcolors_tabular_i:nnnn #1 #2 #3 #4
+ {
+ \int_compare:nNnTF { #1 } = \c@iRow
+% \end{macrocode}
+% We (temporary) keep in memory in |\g_tmpa_seq| the instructions which will
+% still be in force after the current instruction (because they have been issued
+% in the same row of the tabular).
+% \begin{macrocode}
+ { \seq_gput_right:Nn \g_tmpa_seq { { #1 } { #2 } { #3 } { #4 } } }
+ {
+ \tl_gput_right:Nx \g_@@_pre_code_before_tl
+ {
+ \@@_rowlistcolors
+ [ \exp_not:n { #2 } ]
+ { #1 - \int_eval:n { \c@iRow - 1 } }
+ { \exp_not:n { #3 } }
+ [ \exp_not:n { #4 } ]
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% The following command will be used at the end of the tabular, just before the
+% execution of the |\g_@@_pre_code_before_tl|. It clears the sequence
+% |\g_@@_rowlistcolors_seq| of all the commands |\rowlistcolors| which are
+% (still) in force.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_clear_rowlistcolors_seq:
+ {
+ \seq_map_inline:Nn \g_@@_rowlistcolors_seq
+ { \@@_rowlistcolors_tabular_ii:nnnn ##1 }
+ \seq_gclear:N \g_@@_rowlistcolors_seq
+ }
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rowlistcolors_tabular_ii:nnnn #1 #2 #3 #4
+ {
+ \tl_gput_right:Nn \g_@@_pre_code_before_tl
+ { \@@_rowlistcolors [ #2 ] { #1 } { #3 } [ #4 ] }
+ }
+% \end{macrocode}
+% The first mandatory argument of the command |\@@_rowlistcolors| which is
+% writtent in the pre-|\CodeBefore| is of the form |i|: it means that the
+% command must be applied to all the rows from the row~$i$ until the end of the
+% tabular.
+%
+% \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
+% \begin{macrocode}
+\hook_gput_code:nnn { begindocument } { . }
+ {
+ \IfPackageLoadedTF { colortbl }
+ {
+ \cs_set_eq:NN \@@_old_cellcolor \cellcolor
+ \cs_set_eq:NN \@@_old_rowcolor \rowcolor
+ \cs_new_protected:Npn \@@_revert_colortbl:
+ {
+ \hook_gput_code:nnn { env / tabular / begin } { . }
+ {
+ \cs_set_eq:NN \cellcolor \@@_old_cellcolor
+ \cs_set_eq:NN \rowcolor \@@_old_rowcolor
+ }
+ }
+ }
+ { \cs_new_protected:Npn \@@_revert_colortbl: { } }
+ }
+% \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_if_zero:nTF \l_@@_first_col_int
+ { \@@_OnlyMainNiceMatrix_i:n { #1 } }
+ {
+ \int_if_zero:nTF \c@jCol
+ {
+ \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_if_zero:nF \c@iRow
+ {
+ \int_compare:nNnF \c@iRow = \l_@@_last_row_int
+ {
+ \int_compare:nNnT \c@jCol > \c_zero_int
+ { \bool_if:NF \l_@@_in_last_col_bool { #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 ,
+ 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 ,
+% \end{macrocode}
+% We want that, even when the rule has been defined with TikZ by the key |tikz|,
+% the user has still the possibility to change the color of the rule with the key
+% |color| (in the command |\Hline|, not in the key |tikz| of the command
+% |\Hline|). The main use is, when the user has defined its own command
+% |\MyDashedLine| by |\newcommand{\MyDashedRule}{\Hline[tikz=dashed]}|, to give
+% the ability to write |\MyDashedRule[color=red]|.
+% \begin{macrocode}
+ color .code:n =
+ \@@_set_CT@arc@:n { #1 }
+ \tl_set:Nn \l_@@_rule_color_tl { #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 .code:n =
+ \IfPackageLoadedTF { tikz }
+ { \clist_put_right:Nn \l_@@_tikz_rule_tl { #1 } }
+ { \@@_error:n { tikz~without~tikz } } ,
+ tikz .value_required:n = true ,
+ 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_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:
+ {
+% \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:No \l_tmpb_tl { \int_use: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_if_zero:nT \l_@@_local_start_int
+% \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 > \c_zero_int
+ {
+ \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 > \c_zero_int
+ {
+ \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 = \c_one_int
+ { \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:
+ {
+ \tl_clear:N \l_@@_tikz_rule_tl
+ \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 > \c_one_int }
+ { \cs_if_exist_p:N \CT@drsc@ }
+ { ! \tl_if_blank_p:o \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|.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_vline_v:
+ {
+ \begin {tikzpicture }
+ % added 2023/09/25
+% \end{macrocode}
+% By default, the color defined by |\arrayrulecolor| or by |rules/color| will be
+% used, but it's still possible to change the color by using the key |color| or,
+% of course, the key |color| inside the key |tikz| (that is to say the key
+% |color| provided by \textsc{pgf}.
+% \begin{macrocode}
+ \CT@arc@
+ \tl_if_empty:NF \l_@@_rule_color_tl
+ { \tl_put_right:Nx \l_@@_tikz_rule_tl { , color = \l_@@_rule_color_tl } }
+ \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:No \tikzset \l_@@_tikz_rule_tl
+ \use:e { \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_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool 2 1 }
+ {
+ \bool_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool
+ \c@jCol
+ { \int_eval:n { \c@jCol + 1 } }
+ }
+ {
+ \tl_if_eq:NNF \l_@@_vlines_clist \c_@@_all_tl
+ { \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:No \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_if_zero:nT \l_@@_local_start_int
+% \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 > \c_zero_int
+ {
+ \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 > \c_zero_int
+ {
+ \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 = \c_one_int
+ { \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:
+ {
+ \tl_clear:N \l_@@_tikz_rule_tl
+ \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 > \c_one_int }
+ { \cs_if_exist_p:N \CT@drsc@ }
+ { ! \tl_if_blank_p:o \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 = \c_one_int
+ {
+ \dim_sub:Nn \l_@@_x_initial_dim \l_@@_left_margin_dim
+ \bool_if:NF \g_@@_delims_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:NF \g_@@_delims_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 }
+ % added 2023/09/25
+% \end{macrocode}
+% By default, the color defined by |\arrayrulecolor| or by |rules/color| will be
+% used, but it's still possible to change the color by using the key |color| or,
+% of course, the key |color| inside the key |tikz| (that is to say the key
+% |color| provided by \textsc{pgf}.
+% \begin{macrocode}
+ \CT@arc@
+ \tl_if_empty:NF \l_@@_rule_color_tl
+ { \tl_put_right:Nx \l_@@_tikz_rule_tl { , color = \l_@@_rule_color_tl } }
+ \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:No \tikzset \l_@@_tikz_rule_tl
+ \use:e { \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_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool 2 1 }
+ {
+ \bool_lazy_or:nnTF \g_@@_delims_bool \l_@@_except_borders_bool
+ \c@iRow
+ { \int_eval:n { \c@iRow + 1 } }
+ }
+ {
+ \tl_if_eq:NNF \l_@@_hlines_clist \c_@@_all_tl
+ { \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
+ { \@@_collect_options:n { \@@_Hline_iv:nn { #1 } } }
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\cs_set:Npn \@@_Hline_iv:nn #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
+% 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
+ \tl_clear_new:N \l_@@_other_keys_tl
+ \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:No \@@_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 \l_@@_dotted_rule_bool
+ {
+ \int_compare:nNnT \l_@@_multiplicity_int > \c_one_int
+ { \@@_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:ne { Forbidden~letter } \l_@@_letter_str }
+ {
+% \end{macrocode}
+% During the analyse of the preamble provided by the final user, our automaton,
+% for the letter corresponding at the custom line, will directly use the
+% following command that you define in the main hash table of TeX.
+% \begin{macrocode}
+ \cs_set:cpn { @@ _ \l_@@_letter_str } ##1
+ { \@@_v_custom_line: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}
+\tl_const:Nn \c_@@_forbidden_letters_tl { lcrpmbVX|()[]!@<> }
+\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| (which is in |\Hline|).
+% \begin{macrocode}
+ \cs_set:cpn { nicematrix - \l_@@_command_str } { \Hline [ #1 ] }
+ \seq_put_left:No \l_@@_custom_line_commands_seq \l_@@_command_str
+ }
+% \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:No \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
+ }
+ }
+ }
+% \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_@@_array_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
+ }
+ }
+ \@@_rec_preamble:n
+ }
+% \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
+ {
+ \int_compare:nNnT \l_tmpa_tl > { #1 }
+ {
+ \int_compare:nNnT \l_tmpa_tl < { #3 + 1 }
+ {
+ \int_compare:nNnT \l_tmpb_tl > { #2 - 1 }
+ {
+ \int_compare:nNnT \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
+ {
+ \int_compare:nNnT \l_tmpa_tl > { #1 - 1 }
+ {
+ \int_compare:nNnT \l_tmpa_tl < { #3 + 1 }
+ {
+ \int_compare:nNnT \l_tmpb_tl > { #2 }
+ {
+ \int_compare:nNnT \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
+ {
+ \int_compare:nNnT \l_tmpb_tl > { #2 - 1 }
+ {
+ \int_compare:nNnT \l_tmpb_tl < { #4 + 1 }
+ {
+ \int_compare:nNnTF \l_tmpa_tl = { #1 }
+ { \bool_gset_false:N \g_tmpa_bool }
+ {
+ \int_compare:nNnT \l_tmpa_tl = { #3 + 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
+ {
+ \int_compare:nNnT \l_tmpa_tl > { #1 - 1 }
+ {
+ \int_compare:nNnT \l_tmpa_tl < { #3 + 1 }
+ {
+ \int_compare:nNnTF \l_tmpb_tl = { #2 }
+ { \bool_gset_false:N \g_tmpa_bool }
+ {
+ \int_compare:nNnT \l_tmpb_tl = { #4 + 1 }
+ { \bool_gset_false:N \g_tmpa_bool }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \section{The empty corners}
+%
+% When the key |corners| is raised, the rules are not drawn in the corners; they
+% are not colored and |\TikzEveryCell| does not apply. 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_set_protected:Npn \@@_test_if_cell_in_block:nnnnnnn #1 #2 #3 #4 #5 #6 #7
+ {
+ \int_compare:nNnF { #3 } > { #1 }
+ {
+ \int_compare:nNnF { #1 } > { #5 }
+ {
+ \int_compare:nNnF { #4 } > { #2 }
+ {
+ \int_compare:nNnF { #2 } > { #6 }
+ { \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 }
+ {
+ % is \exp_args:NNe mandatory?
+ \exp_args:NNe \dim_set:Nn \l_@@_columns_width_dim
+ {
+ \use:c
+ { @@_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}
+ {
+ \legacy_if:nTF { measuring@ }
+% \end{macrocode}
+% If |{NiceMatrixBlock}| is used in an environment of \pkg{amsmath} such as
+% |{align}|: cf. question 694957 on TeX StackExchange. The most important line
+% in that case is the following one.
+% \begin{macrocode}
+ { \int_gdecr:N \g_@@_NiceMatrixBlock_int }
+ {
+ \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
+ }
+ }
+ \ignorespacesafterend
+ }
+% \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}
+ \cs_set_nopar:Npn \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:
+ \cs_set_nopar:Npn \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}
+ \cs_set_nopar:Npn \l_@@_suffix_tl { - medium }
+ \@@_create_nodes:
+ \@@_computations_for_large_nodes:
+ \cs_set_nopar:Npn \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_eq:NN \l_@@_first_row_int \c_one_int
+ \int_set_eq:NN \l_@@_first_col_int \c_one_int
+% \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_map_pairwise_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_block_str t ,
+ t .value_forbidden:n = true ,
+ T .code:n = \str_set:Nn \l_@@_vpos_block_str T ,
+ T .value_forbidden:n = true ,
+ b .code:n = \str_set:Nn \l_@@_vpos_block_str b ,
+ b .value_forbidden:n = true ,
+ B .code:n = \str_set:Nn \l_@@_vpos_block_str B ,
+ B .value_forbidden:n = true ,
+ color .code:n =
+ \@@_color:n { #1 }
+ \tl_set_rescan:Nnn
+ \l_@@_draw_tl
+ { \char_set_catcode_other:N ! }
+ { #1 } ,
+ color .value_required:n = true ,
+ respect-arraystretch .code:n =
+ \cs_set_eq:NN \@@_reset_arraystretch: \prg_do_nothing: ,
+ respect-arraystretch .value_forbidden: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}
+\cs_new_protected:Npn \@@_Block: { \@@_collect_options:n { \@@_Block_i: } }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewExpandableDocumentCommand \@@_Block_i: { m 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 been 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_ii:nnnnn \c_one_int \c_one_int }
+ {
+ \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 before the composition of the block
+% and |#5| is the label (=content) 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 = \c_one_int
+ {
+ \tl_if_empty:NTF \l_@@_hpos_cell_tl
+ { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_c_str }
+ { \str_set:NV \l_@@_hpos_block_str \l_@@_hpos_cell_tl }
+ }
+ { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_c_str }
+% \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 = \c_one_int
+ ||
+ \int_compare_p:nNn \l_tmpb_int = \c_one_int
+ )
+ && ! \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_bool
+ }
+ { \exp_args:Nee \@@_Block_iv:nnnnn }
+ { \exp_args:Nee \@@_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}) with |\@@_draw_blocks:| and
+% above all |\@@_Block_v:nnnnnn| which will do the main job.
+%
+% |#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 potential math mode and before the composition of
+% the block and |#5| is the label (=content) of the block.
+% \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 } }
+ { \g_@@_row_style_tl \exp_not:n { ##1 } }
+ { \g_@@_row_style_tl \exp_not:n { ##2 } }
+ }
+ }
+ \box_gclear_new:c
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+% \end{macrocode}
+% Now, we will actually compose the content of the |\Block| in a TeX box.
+% \emph{Be careful}: if after the construction of the box, the boolean
+% |\g_@@_rotate_bool| is raised (which means that the command |\rotate| was
+% present in the content of the |\Block|) we will rotate the box but also,
+% maybe, change the position of the baseline!
+% \begin{macrocode}
+ \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 } = \c_one_int \set@color }
+ { \@@_color:o \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 } = \c_one_int
+ {
+ \int_if_zero:nTF \c@iRow
+ \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
+ }
+% \end{macrocode}
+% The following command will be no-op when |respect-arraystretch| is in force.
+% \begin{macrocode}
+ \@@_reset_arraystretch:
+ \dim_zero:N \extrarowheight
+% \end{macrocode}
+% |#4| is the optional argument of the command |\Block|, provided with the
+% syntax |<...>|.
+% \begin{macrocode}
+ #4
+% \end{macrocode}
+% We adjust |\l_@@_hpos_block_str| when |\rotate| has been used (in the cell
+% where the command |\Block| is used but maybe in |#4|, |\RowStyle|,
+% |code-for-first-row|, etc.).
+% \begin{macrocode}
+ \@@_adjust_hpos_rotate:
+% \end{macrocode}
+% The boolean |\g_@@_rotate_bool| will be also considered \emph{after the composition
+% of the box} (in order to rotate the box).
+%
+% \medskip
+% Remind that we are in the command of composition of the box of the block.
+% Previously, we have only done some tuning. Now, we will actually compose the
+% content with a |{tabular}|, an |{array}| or a |{minipage}|.
+% \begin{macrocode}
+ \bool_if:NTF \l_@@_tabular_bool
+ {
+ \bool_lazy_all:nTF
+ {
+ { \int_compare_p:nNn { #2 } = \c_one_int }
+% \end{macrocode}
+% Remind that, when the column has not a fixed width, the dimension
+% |\l_@@_col_width_dim| has the conventional value of $-1$~cm.
+% \begin{macrocode}
+ { ! \dim_compare_p:nNn \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}|), we
+% use a |{minipage}|.
+% \begin{macrocode}
+ {
+ \use:e
+ {
+ \exp_not:N \begin { minipage }%
+ [ \str_lowercase:V \l_@@_vpos_block_str ]
+ { \l_@@_col_width_dim }
+ \str_case:on \l_@@_hpos_block_str
+ { c \centering r \raggedleft l \raggedright }
+ }
+ #5
+ \end { minipage }
+ }
+% \end{macrocode}
+% In the other cases, we use a |{tabular}|.
+% \begin{macrocode}
+ {
+ \use:e
+ {
+ \exp_not:N \begin { tabular }%
+ [ \str_lowercase:V \l_@@_vpos_block_str ]
+ { @ { } \l_@@_hpos_block_str @ { } }
+ }
+ #5
+ \end { tabular }
+ }
+ }
+% \end{macrocode}
+% If we are in a mathematical array (|\l_@@_tabular_bool| is |false|). The
+% composition is always done with an |{array}| (never with a |{minipage}|).
+% \begin{macrocode}
+ {
+ \c_math_toggle_token
+ \use:e
+ {
+ \exp_not:N \begin { array }%
+ [ \str_lowercase:V \l_@@_vpos_block_str ]
+ { @ { } \l_@@_hpos_block_str @ { } }
+ }
+ #5
+ \end { array }
+ \c_math_toggle_token
+ }
+ }
+% \end{macrocode}
+% The box which will contain the content of the block has now been composed.
+%
+% \bigskip
+% If there were |\rotate| (which raises |\g_@@_rotate_bool|) in the content of
+% the |\Block|, we do a rotation of the box (and we also adjust the
+% baseline the rotated box).
+% \begin{macrocode}
+ \bool_if:NT \g_@@_rotate_bool \@@_rotate_box_of_block:
+% \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 } = \c_one_int
+ {
+ \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 and if that block has no vertical option for the
+% position\footnote{If the block has a key of a vertical position, that means
+% that it has to be put in a vertical space determined by the \emph{others}
+% cells of the row. Therefore there is no point creating space here. Moreover,
+% that would lead to problems when a multi-row block with a position key such as
+% |b| or |B|.}, we take into account the height and the depth of that block for the
+% height and the depth of the row.
+% \begin{macrocode}
+ \str_if_eq:VnT \l_@@_vpos_block_str { c }
+ {
+ \int_compare:nNnT { #1 } = \c_one_int
+ {
+ \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 ,
+% \end{macrocode}
+% Now, we put a key for the vertical alignment.
+% \begin{macrocode}
+ \bool_if:NT \g_@@_rotate_bool
+ {
+ \bool_if:NTF \g_@@_rotate_c_bool
+ { v-center }
+ { \int_compare:nNnT \c@iRow = \l_@@_last_row_int T }
+ }
+
+ }
+ {
+ \box_use_drop:c
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+ }
+ }
+ \bool_set_false:N \g_@@_rotate_c_bool
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new:Npn \@@_adjust_hpos_rotate:
+ {
+ \bool_if:NT \g_@@_rotate_bool
+ {
+ \str_set:Nx \l_@@_hpos_block_str
+ {
+ \bool_if:NTF \g_@@_rotate_c_bool
+ { c }
+ {
+ \str_case:onF \l_@@_vpos_block_str
+ { b l B l t r T r }
+ { \int_compare:nNnTF \c@iRow = \l_@@_last_row_int r l }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% Despite its name the following command rotates the box of the block \emph{but
+% also does vertical adjustement of the baseline of the block}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_box_of_block:
+ {
+ \box_grotate:cn
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+ { 90 }
+ \int_compare:nNnT \c@iRow = \l_@@_last_row_int
+ {
+ \vbox_gset_top:cn
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+ {
+ \skip_vertical:n { 0.8 ex }
+ \box_use:c
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+ }
+ }
+ \bool_if:NT \g_@@_rotate_c_bool
+ {
+ \hbox_gset:cn
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+ {
+ \c_math_toggle_token
+ \vcenter
+ {
+ \box_use:c
+ { g_@@_ block _ box _ \int_use:N \g_@@_block_box_int _ box }
+ }
+ \c_math_toggle_token
+ }
+ }
+ }
+% \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 (cf. |\@@_draw_blocks:| and
+% above all |\@@_Block_v:nnnnnn|).
+%
+% |#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 before the composition of the block
+% and |#5| is the label (=content) of the block.
+% \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_@@_tabular_bool
+ {
+ \group_begin:
+% \end{macrocode}
+% The following command will be no-op when |respect-arraystretch| is in force.
+% \begin{macrocode}
+ \@@_reset_arraystretch:
+ \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}
+ \use:e
+ {
+ \exp_not:N \begin { tabular } [ \l_@@_vpos_block_str ]
+ { @ { } \l_@@_hpos_block_str @ { } }
+ }
+ #5
+ \end { tabular }
+ }
+ \group_end:
+ }
+% \end{macrocode}
+% When we are \emph{not} in an environments |{NiceTabular}| (or similar).
+% \begin{macrocode}
+ {
+ \group_begin:
+% \end{macrocode}
+% The following will be no-op when |respect-arraystretch| is in force.
+% \begin{macrocode}
+ \@@_reset_arraystretch:
+ \exp_not:n
+ {
+ \dim_zero:N \extrarowheight
+ #4
+ \c_math_toggle_token
+ \use:e
+ {
+ \exp_not:N \begin { array } [ \l_@@_vpos_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 ,
+ opacity .tl_set:N = \l_@@_opacity_tl ,
+ opacity .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 } ,
+ 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 ,
+% \end{macrocode}
+% Some keys have not a property |.value_required:n| (or similar) because they
+% are in |FirstPass|.
+% \begin{macrocode}
+ l .code:n = \str_set:Nn \l_@@_hpos_block_str l ,
+ r .code:n = \str_set:Nn \l_@@_hpos_block_str r ,
+ c .code:n = \str_set:Nn \l_@@_hpos_block_str c ,
+ L .code:n = \str_set:Nn \l_@@_hpos_block_str l
+ \bool_set_true:N \l_@@_hpos_of_block_cap_bool ,
+ R .code:n = \str_set:Nn \l_@@_hpos_block_str r
+ \bool_set_true:N \l_@@_hpos_of_block_cap_bool ,
+ C .code:n = \str_set:Nn \l_@@_hpos_block_str c
+ \bool_set_true:N \l_@@_hpos_of_block_cap_bool ,
+ t .code:n = \str_set:Nn \l_@@_vpos_block_str t ,
+ T .code:n = \str_set:Nn \l_@@_vpos_block_str T ,
+ b .code:n = \str_set:Nn \l_@@_vpos_block_str b ,
+ B .code:n = \str_set:Nn \l_@@_vpos_block_str B ,
+ v-center .code:n = \str_set:Nn \l_@@_vpos_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 .code:n =
+ \cs_set_eq:NN \@@_reset_arraystretch: \prg_do_nothing: ,
+ respect-arraystretch .value_forbidden: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
+ {
+ \bool_lazy_and:nnTF
+ \l_@@_preamble_bool
+ {
+ \int_compare_p:n
+ { \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
+% The following command |\@@_Block_v:nnnnnn| will actually draw the block.
+% |#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_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
+ {
+ \bool_lazy_and:nnF \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}
+ \tl_if_empty:NF \l_@@_draw_tl
+ {
+ \bool_lazy_or:nnT \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 } } % #5 are the options
+ { #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_if_empty:NF \l_@@_opacity_tl
+ {
+ \tl_if_head_eq_meaning:nNTF \l_@@_fill_tl [
+ {
+ \tl_set:Nx \l_@@_fill_tl
+ {
+ [ opacity = \l_@@_opacity_tl ,
+ \tl_tail:o \l_@@_fill_tl
+ }
+ }
+ {
+ \tl_set:Nx \l_@@_fill_tl
+ { [ opacity = \l_@@_opacity_tl ] { \l_@@_fill_tl } }
+ }
+ }
+ \tl_gput_right:Nx \g_@@_pre_code_before_tl
+ {
+ \exp_not:N \roundedrectanglecolor
+ \exp_args:No \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:on \l_@@_vpos_block_str { c } }
+ { \str_if_eq_p:on \l_@@_vpos_block_str { T } }
+ { \str_if_eq_p:on \l_@@_vpos_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_if_zero:nT { #2 } { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_r_str }
+% \end{macrocode}
+% If we are in the last column, we must put the block as if it was with the key~|l|.
+% \begin{macrocode}
+ \bool_if:nT \g_@@_last_col_found_bool
+ {
+ \int_compare:nNnT { #2 } = \g_@@_col_total_int
+ { \str_set_eq:NN \l_@@_hpos_block_str \c_@@_l_str }
+ }
+% \end{macrocode}
+% |\l_tmpa_tl| will contain the anchor of the \textsc{pgf} node which will be used.
+% \begin{macrocode}
+ \tl_set:Nx \l_tmpa_tl
+ {
+ \str_case:on \l_@@_vpos_block_str
+ {
+ c {
+ \str_case:on \l_@@_hpos_block_str
+ {
+ c { center }
+ l { west }
+ r { east }
+ }
+
+ }
+ T {
+ \str_case:on \l_@@_hpos_block_str
+ {
+ c { north }
+ l { north~west }
+ r { north~east }
+ }
+
+ }
+ B {
+ \str_case:on \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 = \c_zero_dim
+ }
+ \pgfnode
+ { rectangle }
+ { \l_tmpa_tl }
+ { \box_use_drop:N \l_@@_cell_box } { } { }
+ }
+% \end{macrocode}
+% End of the case when |\l_@@_vpos_block_str| is equal to |c|, |T| or |B|.
+% Now, the other cases.
+% \begin{macrocode}
+ {
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \pgfextracty \l_tmpa_dim
+ {
+ \@@_qpoint:n
+ {
+ row - \str_if_eq:onTF \l_@@_vpos_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:on \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:on \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}
+ \tl_if_eq:NNTF \l_@@_draw_tl \c_@@_default_tl
+ { \CT@arc@ }
+ { \@@_color:o \l_@@_draw_tl }
+ }
+ \pgfsetcornersarced
+ {
+ \pgfpoint
+ { \l_@@_rounded_corners_dim }
+ { \l_@@_rounded_corners_dim }
+ }
+ \@@_cut_on_hyphen:w #2 \q_stop
+ \int_compare:nNnF \l_tmpa_tl > \c@iRow
+ {
+ \int_compare:nNnF \l_tmpb_tl > \c@jCol
+ {
+ \@@_qpoint:n { row - \l_tmpa_tl }
+ \dim_set_eq:NN \l_tmpb_dim \pgf@y
+ \@@_qpoint:n { col - \l_tmpb_tl }
+ \dim_set_eq:NN \l_@@_tmpc_dim \pgf@x
+ \@@_cut_on_hyphen:w #3 \q_stop
+ \int_compare:nNnT \l_tmpa_tl > \c@iRow
+ { \tl_set:No \l_tmpa_tl { \int_use:N \c@iRow } }
+ \int_compare:nNnT \l_tmpb_tl > \c@jCol
+ { \tl_set:No \l_tmpb_tl { \int_use:N \c@jCol } }
+ \@@_qpoint:n { row - \int_eval:n { \l_tmpa_tl + 1 } }
+ \dim_set_eq:NN \l_tmpa_dim \pgf@y
+ \@@_qpoint:n { col - \int_eval:n { \l_tmpb_tl + 1 } }
+ \dim_set_eq:NN \l_@@_tmpd_dim \pgf@x
+ \pgfsetlinewidth { 1.1 \l_@@_line_width_dim }
+ \pgfpathrectanglecorners
+ { \pgfpoint \l_@@_tmpc_dim \l_tmpb_dim }
+ { \pgfpoint \l_@@_tmpd_dim \l_tmpa_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 .code:n =
+ \exp_args:Ne \tl_if_empty:nF { #1 } { \tl_set:Nn \l_@@_draw_tl { #1 } } ,
+ 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:e
+ {
+ \@@_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
+ }
+ }
+ }
+ }
+\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:e
+ {
+ \@@_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
+ }
+ }
+ }
+ }
+% \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:e { \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:e { \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. However, among
+% those keys, you have added in \pkg{nicematrix} a special key |offset| (an
+% offset for the rectangle of the block). That's why we have to extract that key
+% first.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_block_tikz:nnnnn #1 #2 #3 #4 #5
+ {
+ \begin { tikzpicture }
+ \@@_clip_with_rounded_corners:
+ \clist_map_inline:nn { #5 }
+ {
+ \keys_set_known:nnN { NiceMatrix / SpecialOffset } { ##1 } \l_tmpa_tl
+ \use:e { \exp_not:N \path [ \l_tmpa_tl ] }
+ (
+ [
+ xshift = \dim_use:N \l_@@_offset_dim ,
+ yshift = - \dim_use:N \l_@@_offset_dim
+ ]
+ #1 -| #2
+ )
+ rectangle
+ (
+ [
+ xshift = - \dim_use:N \l_@@_offset_dim ,
+ yshift = \dim_use:N \l_@@_offset_dim
+ ]
+ \int_eval:n { #3 + 1 } -| \int_eval:n { #4 + 1 }
+ ) ;
+ }
+ \end { tikzpicture }
+ }
+\cs_generate_variant:Nn \@@_block_tikz:nnnnn { n n n n V }
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+\keys_define:nn { NiceMatrix / SpecialOffset }
+ { offset .dim_set:N = \l_@@_offset_dim }
+% \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 some keys and pass the other keys to the environment
+% |{NiceArrayWithDelims}|.
+% \begin{macrocode}
+\keys_define:nn { NiceMatrix / Auto }
+ {
+ columns-type .tl_set:N = \l_@@_columns_type_tl ,
+ 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 ,
+ rounded-corners .dim_set:N = \l_@@_tab_rounded_corners_dim ,
+ rounded-corners .default:n = 4 pt
+ }
+% \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:
+ \keys_set_known:nnN { NiceMatrix / Auto } { #6 } \l_tmpa_tl
+ \use:e
+ {
+ \exp_not:N \begin { NiceArrayWithDelims } { #1 } { #2 }
+ { * { #4 } { \exp_not:o \l_@@_columns_type_tl } }
+ [ \exp_not:o \l_tmpa_tl ]
+ }
+ \int_if_zero:nT \l_@@_first_row_int
+ {
+ \int_if_zero:nT \l_@@_first_col_int { & }
+ \prg_replicate:nn { #4 - 1 } { & }
+ \int_compare:nNnT \l_@@_last_col_int > { -1 } { & } \\
+ }
+ \prg_replicate:nn { #3 }
+ {
+ \int_if_zero:nT \l_@@_first_col_int { & }
+% \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_if_zero:nT \l_@@_first_col_int { & }
+ \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_true:N \g_@@_delims_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_false:N \g_@@_delims_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 }
+% \end{macrocode}
+% |\g_@@_row_style_tl| contains several instructions of the form:
+%
+% \qquad |\@@_if_row_less_than:nn { number } { instructions }|
+%
+% The command |\@@_if_row_less:nn| is fully expandable and, thus, the
+% instructions will be inserted in the |\g_@@_pre_code_after_tl| only if
+% |\diagbox| is used in a row which is the scope of that chunck of instructions.
+% \begin{macrocode}
+ { \g_@@_row_style_tl \exp_not:n { #1 } }
+ { \g_@@_row_style_tl \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: #5 \@@_math_toggle:
+ \end { minipage }
+ }
+ { }
+ { }
+ \endpgfscope
+ \pgftransformshift { \pgfpoint \l_@@_tmpd_dim \l_tmpa_dim }
+ \pgfnode { rectangle } { north~east }
+ {
+ \begin { minipage } { 20 cm }
+ \raggedleft
+ \@@_math_toggle: #6 \@@_math_toggle:
+ \end { minipage }
+ }
+ { }
+ { }
+ \endpgfpicture
+ }
+% \end{macrocode}
+%
+%
+%
+%
+% \bigskip
+% \section{The keyword \textbackslash CodeAfter}
+%
+%
+%
+% \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:o \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 ,
+ 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 } { . }
+ {
+ \cs_set_nopar:Npn \l_@@_argspec_tl { m m m m O { } E { _ ^ } { { } { } } }
+ \tl_set_rescan:Nno \l_@@_argspec_tl { } \l_@@_argspec_tl
+ \exp_args:NNo \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
+ {
+ \cs_set_nopar:Npn \l_@@_first_i_tl { #1 }
+ \cs_set_nopar:Npn \l_@@_first_j_tl { #2 }
+ \cs_set_nopar:Npn \l_@@_last_i_tl { #3 }
+ \cs_set_nopar:Npn \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 }
+ \int_compare:nNnT \l_@@_first_i_tl = \l_@@_last_i_tl
+ { \cs_set_nopar:Npn \arraystretch { 1 } }
+ \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
+ }
+ }
+ \@@_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 } }
+ \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@:o \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 \c_@@_all_tl
+ { \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 } > \c_zero_int }
+ {
+ \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 \c_@@_all_tl
+ { \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 } > \c_zero_int }
+ {
+ \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:o \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:o \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 }
+ {
+ \vtop
+ {
+ \group_begin:
+ \everycr { }
+ \halign
+ {
+ \hfil ## \hfil \crcr
+ \@@_math_toggle: #1 \@@_math_toggle: \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
+ {
+ \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: #1 \@@_math_toggle: \cr
+ }
+ }
+ \group_end:
+ }
+ { }
+ { }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \section{The command TikzEveryCell}
+%
+% \begin{macrocode}
+\bool_new:N \l_@@_not_empty_bool
+\bool_new:N \l_@@_empty_bool
+
+\keys_define:nn { NiceMatrix / TikzEveryCell }
+ {
+ not-empty .code:n =
+ \bool_lazy_or:nnTF
+ \l_@@_in_code_after_bool
+ \g_@@_recreate_cell_nodes_bool
+ { \bool_set_true:N \l_@@_not_empty_bool }
+ { \@@_error:n { detection~of~empty~cells } } ,
+ not-empty .value_forbidden:n = true ,
+ empty .code:n =
+ \bool_lazy_or:nnTF
+ \l_@@_in_code_after_bool
+ \g_@@_recreate_cell_nodes_bool
+ { \bool_set_true:N \l_@@_empty_bool }
+ { \@@_error:n { detection~of~empty~cells } } ,
+ empty .value_forbidden:n = true ,
+ unknown .code:n = \@@_error:n { Unknown~key~for~TikzEveryCell }
+ }
+
+
+\NewDocumentCommand { \@@_TikzEveryCell } { O { } m }
+ {
+ \IfPackageLoadedTF { tikz }
+ {
+ \group_begin:
+ \keys_set:nn { NiceMatrix / TikzEveryCell } { #1 }
+% \end{macrocode}
+% The inner pair of braces in the following line is mandatory because, the last
+% argument of |\@@_tikz:nnnnn| is \emph{a list of lists} of TikZ keys.
+% \begin{macrocode}
+ \tl_set:Nn \l_tmpa_tl { { #2 } }
+ \seq_map_inline:Nn \g_@@_pos_of_blocks_seq
+ { \@@_for_a_block:nnnnn ##1 }
+ \@@_all_the_cells:
+ \group_end:
+ }
+ { \@@_error:n { TikzEveryCell~without~tikz } }
+ }
+
+\tl_new:N \@@_i_tl
+\tl_new:N \@@_j_tl
+
+\cs_new_protected:Nn \@@_all_the_cells:
+ {
+ \int_step_variable:nNn { \int_use:c { c@iRow } } \@@_i_tl
+ {
+ \int_step_variable:nNn { \int_use:c { c@jCol } } \@@_j_tl
+ {
+ \cs_if_exist:cF { cell - \@@_i_tl - \@@_j_tl }
+ {
+ \exp_args:NNe \seq_if_in:NnF \l_@@_corners_cells_seq
+ { \@@_i_tl - \@@_j_tl }
+ {
+ \bool_set_false:N \l_tmpa_bool
+ \cs_if_exist:cTF
+ { pgf @ sh @ ns @ \@@_env: - \@@_i_tl - \@@_j_tl }
+ {
+ \bool_if:NF \l_@@_empty_bool
+ { \bool_set_true:N \l_tmpa_bool }
+ }
+ {
+ \bool_if:NF \l_@@_not_empty_bool
+ { \bool_set_true:N \l_tmpa_bool }
+ }
+ \bool_if:NT \l_tmpa_bool
+ {
+ \@@_block_tikz:nnnnV
+ \@@_i_tl \@@_j_tl \@@_i_tl \@@_j_tl \l_tmpa_tl
+ }
+ }
+ }
+ }
+ }
+ }
+
+\cs_new_protected:Nn \@@_for_a_block:nnnnn
+ {
+ \bool_if:NF \l_@@_empty_bool
+ {
+ \@@_block_tikz:nnnnV
+ { #1 } { #2 } { #3 } { #4 } \l_tmpa_tl
+ }
+ \@@_mark_cells_of_block:nnnn { #1 } { #2 } { #3 } { #4 }
+ }
+
+\cs_new_protected:Nn \@@_mark_cells_of_block:nnnn
+ {
+ \int_step_inline:nnn { #1 } { #3 }
+ {
+ \int_step_inline:nnn { #2 } { #4 }
+ { \cs_set:cpn { cell - ##1 - ####1 } { } }
+ }
+ }
+% \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 \g_@@_footnotehyper_bool
+% \end{macrocode}
+%
+% \medskip
+% The boolean |\g_@@_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 \g_@@_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~<return>.
+ }
+ {
+ 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 = \g_@@_messages_for_Overleaf_bool ,
+ footnote .bool_set:N = \g_@@_footnote_bool ,
+ footnotehyper .bool_set:N = \g_@@_footnotehyper_bool ,
+ no-test-for-array .bool_set:N = \g_@@_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 \g_@@_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}
+ \IfClassLoadedTF { beamer }
+ { \bool_set_false:N \g_@@_footnote_bool }
+ {
+ \IfPackageLoadedTF { footnotehyper }
+ { \@@_error:n { footnote~with~footnotehyper~package } }
+ { \usepackage { footnote } }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\bool_if:NT \g_@@_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 \g_@@_footnote_bool }
+ {
+ \IfPackageLoadedTF { footnote }
+ { \@@_error:n { footnotehyper~with~footnote~package } }
+ { \usepackage { footnotehyper } }
+ }
+ \bool_set_true:N \g_@@_footnote_bool
+ }
+% \end{macrocode}
+% The flag |\g_@@_footnote_bool| is raised and so, we will only have to test
+% |\g_@@_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 \g_@@_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~<return>. }
+ }
+% \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:NoTF| 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:NoTF \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 } }
+ }
+ }
+ }
+ { \@@_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:oF \g_@@_HVdotsfor_lines_tl
+ { ~Maybe~your~use~of~\token_to_str:N \Hdotsfor\ is~incorrect.}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { hvlines,~rounded-corners~and~corners }
+ {
+ Incompatible~options.\\
+ You~should~not~use~'hvlines',~'rounded-corners'~and~'corners'~at~this~time.\\
+ The~output~will~not~be~reliable.
+ }
+% \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).
+ 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.\\
+ You~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.\\
+ Your~key~'\l_keys_key_str'~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Unknown~key~for~TikzEveryCell }
+ {
+ Unknown~key.\\
+ There~is~only~two~keys~available~here:~
+ 'empty'~and~'not-empty'.\\
+ Your~key~'\l_keys_key_str'~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Unknown~key~for~rotate }
+ {
+ Unknown~key.\\
+ The~only~key~available~here~is~'c'.\\
+ Your~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',~
+ 'horizontal-labels',~
+ '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 { detection~of~empty~cells }
+ {
+ Problem~with~'not-empty'\\
+ For~technical~reasons,~you~must~activate~
+ 'create-cell-nodes'~in~\token_to_str:N \CodeBefore\
+ in~order~to~use~the~key~'\l_keys_key_str'.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { siunitx~not~loaded }
+ {
+ siunitx~not~loaded\\
+ You~can't~use~the~columns~'S'~because~'siunitx'~is~not~loaded.\\
+ That~error~is~fatal.
+ }
+% \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:nnn { width~without~X~columns }
+ {
+ You~have~used~the~key~'width'~but~you~have~put~no~'X'~column.~
+ That~key~will~be~ignored.
+ }
+ {
+ This~message~is~the~message~'width~without~X~columns'~
+ of~the~module~'nicematrix'.~
+ The~experimented~users~can~disable~that~message~with~
+ \token_to_str:N \msg_redirect_name:nnn.\\
+ }
+
+% \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~'#1'~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 \g_@@_messages_for_Overleaf_bool
+ { For~a~list~of~the~names~already~used,~type~H~<return>. }
+ }
+ {
+ 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 { TikzEveryCell~without~tikz }
+ {
+ TikZ~not~loaded.\\
+ You~can't~use~\token_to_str:N \TikzEveryCell\
+ because~you~have~not~loaded~tikz.~
+ This~command~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~\token_to_str:N \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. \\
+ This~block~and~maybe~others~will~be~ignored.
+ }
+% \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~without~tikz }
+ {
+ Tikz~not~loaded.\\
+ You~can't~use~the~key~'tikz'~here~because~Tikz~is~not~
+ loaded.~If~you~go~on,~that~key~will~be~ignored.
+ }
+% \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 { without~color-inside }
+ {
+ If~order~to~use~\token_to_str:N \cellcolor,~\token_to_str:N \rowcolor,~
+ \token_to_str:N \rowcolors\ or~\token_to_str:N \rowlistcolors\
+ outside~\token_to_str:N \CodeBefore,~you~
+ should~have~used~the~key~'color-inside'~in~your~\@@_full_name_env:.\\
+ You~can~go~on~but~you~may~need~more~compilations.
+ }
+% \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,~opacity,~rounded-corners,~r,~
+ respect-arraystretch,~t,~T,~tikz,~transparent~and~vlines.
+ }
+% \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,~
+ light-syntax-expanded,~
+ matrix/columns-type,~
+ no-cell-nodes,~
+ notes~(several~subkeys),~
+ nullify-dots,~
+ pgf-node-code,~
+ renew-dots,~
+ renew-matrix,~
+ respect-arraystretch,~
+ rounded-corners,~
+ 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,~
+ color-inside,~
+ 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,~
+ light-syntax-expanded,~
+ name,~
+ no-cell-nodes,~
+ nullify-dots,~
+ pgf-node-code,~
+ renew-dots,~
+ respect-arraystretch,~
+ right-margin,~
+ rounded-corners,~
+ 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,~
+ color-inside,~
+ 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,~
+ light-syntax-expanded,~
+ name,~
+ no-cell-nodes,~
+ nullify-dots,~
+ pgf-node-code,~
+ r,~
+ renew-dots,~
+ respect-arraystretch,~
+ right-margin,~
+ rounded-corners,~
+ 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,~
+ color-inside,~
+ 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,~
+ light-syntax-expanded,~
+ name,~
+ no-cell-nodes,~
+ 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'.\\
+ \bool_if:NF \g_@@_messages_for_Overleaf_bool
+ { For~a~list~of~the~names~already~used,~type~H~<return>. }
+ }
+ {
+ 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}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { NiceTabularX~without~X }
+ {
+ NiceTabularX~without~X.\\
+ You~should~not~use~{NiceTabularX}~without~X~columns.\\
+ However,~you~can~go~on.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Preamble~forgotten }
+ {
+ Preamble~forgotten.\\
+ You~have~probably~forgotten~the~preamble~of~your~
+ \@@_full_name_env:. \\
+ This~error~is~fatal.
+ }
+% \end{macrocode}
+%
+% \newpage
+% \tableofcontents
+%
+% \endinput
+% Local Variables:
+% TeX-fold-mode: t
+% TeX-fold-preserve-comments: nil
+% fill-column: 80
+% End:
+
+
|