diff options
Diffstat (limited to 'macros/latex/contrib/nicematrix/nicematrix-code.dtx')
-rw-r--r-- | macros/latex/contrib/nicematrix/nicematrix-code.dtx | 34755 |
1 files changed, 17406 insertions, 17349 deletions
diff --git a/macros/latex/contrib/nicematrix/nicematrix-code.dtx b/macros/latex/contrib/nicematrix/nicematrix-code.dtx index 79d804eb1c..340d2e0f5e 100644 --- a/macros/latex/contrib/nicematrix/nicematrix-code.dtx +++ b/macros/latex/contrib/nicematrix/nicematrix-code.dtx @@ -1,17349 +1,17406 @@ -% \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:
-
-
+% \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.27b} +\def\myfiledate{2024/04/23} +% +% +%<*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 +% \begin{macrocode} +\RequirePackage { amsmath } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\RequirePackage { array } +% \end{macrocode} +% In the version 2.6a of \pkg{array}, important modifications have been done for +% the Tagging Project. +% \begin{macrocode} +\bool_const:Nn \c_@@_tagging_array_bool { \cs_if_exist_p:N \ar@ialign } +% \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 +% We will delete in the future the following lines which are only a security. +% \begin{macrocode} +\cs_set:Npn \int_if_zero:NT #1 { \int_compare:nNnT #1 = \c_zero_int } +\cs_set:Npn \int_if_zero:NTF #1 { \int_compare:nNnTF #1 = \c_zero_int } +% \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 +% |\hook_gput_code:nnn { begindocument } { . } | 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 April 2024, 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 +% 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 \l_@@_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 an 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. However, since version 2.6a +% (version for the Tagging Project), \pkg{array} uses |\ar@ialign| instead of +% |\ialign|. In that case, of course, you do a saving of |\ar@ialign|. +% \begin{macrocode} +\bool_if:NTF \c_@@_tagging_array_bool + { \cs_set_eq:NN \@@_old_ar@ialign: \ar@ialign } + { \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} +% +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_everycr_i: + { + \bool_if:NT \c_@@_tagging_array_bool + { + \tbl_if_row_was_started:T { \UseTaggingSocket { tbl / row / end } } + \tbl_update_cell_data_for_next_row: + } + \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} +% +% 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} +\cs_new_protected:Npn \@@_some_initialization: + { + \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} +% +% +% \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} + \bool_if:NTF \c_@@_tagging_array_bool + { + \cs_set_nopar:Npn \ar@ialign + { + \tbl_init_cell_data_for_table: + \@@_redefine_everycr: + \tabskip = \c_zero_skip + \@@_some_initialization: +% \end{macrocode} +% +% After its first use, the definition of |\ar@ialign| will revert +% automatically to its default definition. With this programmation, we will +% have, in the cells of the array, a clean version of |\ar@ialign|. +% \begin{macrocode} + \cs_set_eq:NN \ar@ialign \@@_old_ar@ialign: + \halign + } + } +% \end{macrocode} +% The following part will be deleted when we will delete the boolean +% |\c_@@_tagging_array_bool| (when we consider the version 2.6a of \pkg{array} +% is required). +% \begin{macrocode} + { + \cs_set_nopar:Npn \ialign + { + \@@_redefine_everycr: + \tabskip = \c_zero_skip + \@@_some_initialization: + \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. +% A |\hook_gremove_code:nn| will be put in |\@@_after_array:|. +% \begin{macrocode} + \cs_set_eq:NN \multicolumn \@@_multicolumn:nnn + \hook_gput_code:nnn { env / tabular / begin } { nicematrix } + { \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 { nicematrix / 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 { nicematrix / 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 |\strutbox|, 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 +% |{ nicematrix / 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 { nicematrix / 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 { nicematrix / 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: + \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 + \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 } + \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 } + \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: + { +% \end{macrocode} +% There was a |\hook_gput_code:nnn { env / tabular / begin } { nicematrix }| in +% the command |\@@_pre_array_ii:| in order to come back to the standard +% definition of |\multicolumn| (in the tabulars used by the final user in the +% cells of our array of \pkg{nicematrix}) and maybe another linked to +% \pkg{colortbl}. +% \begin{macrocode} + \hook_gremove_code:nn { env / tabular / begin } { nicematrix } + \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: - + } + } + } + { } + \bool_if:NT \c_@@_tagging_array_bool + { \cs_set_eq:NN \ar@ialign \@@_old_ar@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 + \l_@@_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 \l_@@_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 } { nicematrix } + { + \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 } +% \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 } +% \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 following 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 (in the cell of the array). +% \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 + { m } + { \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 , + m .code:n = \str_set:Nn \l_@@_vpos_block_str { c } , + m .value_forbidden:n = true , + v-center .meta:n = m , + 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: + { + \bool_if:NTF \c_@@_tagging_array_bool + { \cs_set_eq:NN \ar@ialign \@@_old_ar@ialign: } + { \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 } } + \tl_gput_right:Nx \g_nicematrix_code_after_tl + { + \@@_stroke_block:nnn +% \end{macrocode} +% |#5| are the options +% \begin{macrocode} + { \exp_not:n { #5 } } + { #1 - #2 } + { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } + } + \seq_gput_right:Nn \g_@@_pos_of_stroken_blocks_seq + { { #1 } { #2 } { #3 } { #4 } } + } +% \end{macrocode} +% +% \begin{macrocode} + \clist_if_empty:NF \l_@@_borders_clist + { + \tl_gput_right:Nx \g_nicematrix_code_after_tl + { + \@@_stroke_borders_block:nnn + { \exp_not:n { #5 } } + { #1 - #2 } + { \int_use:N \l_@@_last_row_int - \int_use:N \l_@@_last_col_int } + } + } +% \end{macrocode} +% +% \begin{macrocode} + \tl_if_empty:NF \l_@@_fill_tl + { + \tl_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 } +% \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~message~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: + + |