diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/tabularray/tabularray.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/tabularray/tabularray.sty | 640 |
1 files changed, 553 insertions, 87 deletions
diff --git a/Master/texmf-dist/tex/latex/tabularray/tabularray.sty b/Master/texmf-dist/tex/latex/tabularray/tabularray.sty index 4717992539e..2e3fa4eb5d0 100644 --- a/Master/texmf-dist/tex/latex/tabularray/tabularray.sty +++ b/Master/texmf-dist/tex/latex/tabularray/tabularray.sty @@ -12,18 +12,12 @@ \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} -\ProvidesExplPackage{tabularray}{2021-08-01}{2021M} +\ProvidesExplPackage{tabularray}{2021-09-01}{2021N} {Typeset tabulars and arrays with LaTeX3} \RequirePackage{xparse} -\AtBeginDocument - { - \@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{} - \@ifpackageloaded{hyperref}{\hypersetup{pdfborder={0 0 0}}}{} - } - -\ExplSyntaxOn +\AtBeginDocument{\@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}} %% Backport \tl_if_eq:NnTF for old texlive 2020 \cs_if_exist:NF \tl_if_eq:NnTF @@ -1114,11 +1108,18 @@ \tl_new:N \l__tblr_hline_dash_tl % dash style \tl_new:N \l__tblr_hline_fg_tl % dash foreground \tl_new:N \l__tblr_hline_wd_tl % dash width +\tl_new:N \l__tblr_hline_leftpos_tl % left position +\tl_new:N \l__tblr_hline_rightpos_tl % right position +\bool_new:N \l__tblr_hline_endpos_bool % whether set positions only for both ends \NewTableCommand \cline [2] [] { \SetHline [=] {#2} {#1} } \NewTableCommand \hline [1] [] { \SetHline [+] {-} {#1} } +%% Some keys can be set by any hline, such as abovespace and belowspace keys. +%% Using special hline of index 0, you can set these keys without adding any hlines. +\NewTableCommand \SetVspace [1] { \SetHline [0] {-} {#1} } + %% #1: the index of the hline (may be + or =) %% #2: which columns of the hline, separate by commas %% #3: key=value pairs @@ -1132,13 +1133,19 @@ \cs_new_protected:Npn \tblr_set_hline:nnn #1 #2 #3 { \group_begin: - \keys_set_groups:nnn { tblr-hline } { text } {#3} - \tl_if_eq:NnF \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text } + %% We can not use \int_compare:nNnTF here since #1 may be + or = . + %% Also we treat hline of index 0 specially, not adding hline count. + \tl_if_eq:nnTF {#1} {0} + { \keys_set:nn { tblr-hline } {#3} } { - \__tblr_set_hline_num:n {#1} - \tl_clear:N \l__tblr_hline_dash_tl - \keys_set:nn { tblr-hline } { dash = solid, #3 } - \__tblr_set_hline_cmd:n {#2} + \keys_set_groups:nnn { tblr-hline } { text } {#3} + \tl_if_eq:NnF \l__tblr_hline_dash_tl { \exp_not:N \@tblr@text } + { + \__tblr_set_hline_num:n {#1} + \tl_clear:N \l__tblr_hline_dash_tl + \keys_set:nn { tblr-hline } { dash = solid, #3 } + \__tblr_set_hline_cmd:n {#2} + } } \group_end: } @@ -1215,6 +1222,21 @@ wd .code:n = \tl_set:Nn \l__tblr_hline_wd_tl { \dim_eval:n {#1} }, fg .code:n = \tl_set:Nn \l__tblr_hline_fg_tl {#1}, baseline .code:n = \__tblr_hline_set_baseline:n {#1}, + leftpos .code:n = \tl_set:Nx \l__tblr_hline_leftpos_tl {#1}, + rightpos .code:n = \tl_set:Nx \l__tblr_hline_rightpos_tl {#1}, + l .meta:n = { leftpos = #1 }, + l .default:n = { -0.8 }, + r .meta:n = { rightpos = #1 }, + r .default:n = { -0.8 }, + lr .meta:n = { leftpos = #1, rightpos = #1 }, + lr .default:n = { -0.8 }, + endpos .bool_set:N = \l__tblr_hline_endpos_bool, + abovespace .code:n = \__tblr_row_gput_above:ne { belowsep } { \dim_eval:n {#1} }, + belowspace .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} }, + abovespace+ .code:n = \__tblr_row_gadd_dimen_above:ne + { belowsep } { \dim_eval:n {#1} }, + belowspace+ .code:n = \__tblr_row_gadd_dimen:ne + { abovesep } { \dim_eval:n {#1} }, unknown .code:n = \__tblr_hline_unknown_key:V \l_keys_key_str, } @@ -1238,24 +1260,59 @@ \__tblr_get_childs:nx {#1} { \int_use:N \c@colcount } \clist_map_inline:Nn \l_tblr_childs_clist { - \__tblr_spec_gput:nee { hline } - { [\int_use:N \c@rownum][##1](\l__tblr_hline_num_tl) / @dash } - { \l__tblr_hline_dash_tl } + \__tblr_set_hline_option:nnn { ##1 } { @dash } { \l__tblr_hline_dash_tl } \tl_if_empty:NF \l__tblr_hline_wd_tl { - \__tblr_spec_gput:nee { hline } - { [\int_use:N \c@rownum][##1](\l__tblr_hline_num_tl) / wd } - { \l__tblr_hline_wd_tl } + \__tblr_set_hline_option:nnn { ##1 } { wd } { \l__tblr_hline_wd_tl } } \tl_if_empty:NF \l__tblr_hline_fg_tl { - \__tblr_spec_gput:nee { hline } - { [\int_use:N \c@rownum][##1](\l__tblr_hline_num_tl) / fg } - { \l__tblr_hline_fg_tl } + \__tblr_set_hline_option:nnn { ##1 } { fg } { \l__tblr_hline_fg_tl } + } + } + \tl_if_empty:NF \l__tblr_hline_leftpos_tl + { + \bool_if:NTF \l__tblr_hline_endpos_bool + { + \__tblr_set_hline_option:nnn + { \clist_item:Nn \l_tblr_childs_clist {1} } + { leftpos } + { \l__tblr_hline_leftpos_tl } + } + { + \clist_map_inline:Nn \l_tblr_childs_clist + { + \__tblr_set_hline_option:nnn + { ##1 } { leftpos } { \l__tblr_hline_leftpos_tl } + } + } + } + \tl_if_empty:NF \l__tblr_hline_rightpos_tl + { + \bool_if:NTF \l__tblr_hline_endpos_bool + { + \__tblr_set_hline_option:nnn + { \clist_item:Nn \l_tblr_childs_clist {-1} } + { rightpos } + { \l__tblr_hline_rightpos_tl } + } + { + \clist_map_inline:Nn \l_tblr_childs_clist + { + \__tblr_set_hline_option:nnn + { ##1 } { rightpos } { \l__tblr_hline_rightpos_tl } + } } } } +%% #1: column; #2: key; #3: value +\cs_new_protected_nopar:Npn \__tblr_set_hline_option:nnn #1 #2 #3 + { + \__tblr_spec_gput:nee { hline } + { [\int_use:N \c@rownum][#1](\l__tblr_hline_num_tl) / #2 } { #3 } + } + \NewTableCommand \firsthline [1] [] { \SetHline [+] {-} { #1, baseline=below } } \NewTableCommand \lasthline [1] [] { \SetHline [+] {-} { #1, baseline=above } } @@ -1313,6 +1370,8 @@ \tl_new:N \l__tblr_vline_dash_tl % dash style \tl_new:N \l__tblr_vline_fg_tl % dash foreground \tl_new:N \l__tblr_vline_wd_tl % dash width +\tl_new:N \l__tblr_vline_abovepos_tl % above position +\tl_new:N \l__tblr_vline_belowpos_tl % below position \NewTableCommand \rline [2] [] { \SetVline [=] {#2} {#1} } @@ -1413,6 +1472,8 @@ text .groups:n = { text }, wd .code:n = \tl_set:Nn \l__tblr_vline_wd_tl { \dim_eval:n {#1} }, fg .code:n = \tl_set:Nn \l__tblr_vline_fg_tl {#1}, + abovepos .code:n = \tl_set:Nx \l__tblr_vline_abovepos_tl {#1}, + belowpos .code:n = \tl_set:Nx \l__tblr_vline_belowpos_tl {#1}, unknown .code:n = \__tblr_vline_unknown_key:V \l_keys_key_str, } @@ -1451,6 +1512,18 @@ { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / fg } { \l__tblr_vline_fg_tl } } + \tl_if_empty:NF \l__tblr_vline_abovepos_tl + { + \__tblr_spec_gput:nee { vline } + { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / abovepos } + { \l__tblr_vline_abovepos_tl } + } + \tl_if_empty:NF \l__tblr_vline_belowpos_tl + { + \__tblr_spec_gput:nee { vline } + { [##1][\int_use:N \c@colnum](\l__tblr_vline_num_tl) / belowpos } + { \l__tblr_vline_belowpos_tl } + } } } @@ -1549,6 +1622,7 @@ { halign .code:n = \__tblr_cell_gput:nn { halign } {#1}, valign .code:n = \__tblr_cell_gput:nn { valign } {#1}, + j .meta:n = { halign = j }, l .meta:n = { halign = l }, c .meta:n = { halign = c }, r .meta:n = { halign = r }, @@ -1685,6 +1759,23 @@ } } } + %% Make continuous borders for multirow cells + \tl_set:Nx \l__tblr_n_tl + { + \int_max:nn + { + \__tblr_spec_item:ne { vline } { [\int_use:N \c@colnum] / @vline-count } + } + { 1 } + } + \int_step_variable:nnNn + { \c@rownum } { \int_eval:n { \c@rownum + #1 -1 } } \l__tblr_i_tl + { + \__tblr_spec_gput:nee { vline } + { [\l__tblr_i_tl][\int_use:N \c@colnum](\l__tblr_n_tl) / belowpos } {1} + \__tblr_spec_gput:nee { vline } + { [\l__tblr_i_tl][\int_eval:n {\c@colnum + #2}](1) / belowpos } {1} + } } \cs_generate_variant:Nn \__tblr_set_span_spec:nn { VV } @@ -1809,6 +1900,7 @@ { halign .code:n = \__tblr_column_gput_cell:nn { halign } {#1}, valign .code:n = \__tblr_column_gput_cell:nn { valign } {#1}, + j .meta:n = { halign = j }, l .meta:n = { halign = l }, c .meta:n = { halign = c }, r .meta:n = { halign = r }, @@ -1968,6 +2060,7 @@ { halign .code:n = \__tblr_row_gput_cell:nn { halign } {#1}, valign .code:n = \__tblr_row_gput_cell:nn { valign } {#1}, + j .meta:n = { halign = j }, l .meta:n = { halign = l }, c .meta:n = { halign = c }, r .meta:n = { halign = r }, @@ -2004,12 +2097,25 @@ } \cs_generate_variant:Nn \__tblr_row_gput:nn { ne } +\cs_new_protected:Npn \__tblr_row_gput_above:nn #1 #2 + { + \__tblr_data_gput:nenn { row } { \int_eval:n { \c@rownum - 1 } } {#1} {#2} + } +\cs_generate_variant:Nn \__tblr_row_gput_above:nn { ne } + \cs_new_protected:Npn \__tblr_row_gadd_dimen:nn #1 #2 { \__tblr_data_gadd_dimen_value:nenn { row } { \int_use:N \c@rownum } {#1} {#2} } \cs_generate_variant:Nn \__tblr_row_gadd_dimen:nn { ne } +\cs_new_protected:Npn \__tblr_row_gadd_dimen_above:nn #1 #2 + { + \__tblr_data_gadd_dimen_value:nenn { row } + { \int_eval:n { \c@rownum - 1 } } {#1} {#2} + } +\cs_generate_variant:Nn \__tblr_row_gadd_dimen_above:nn { ne } + %% #1: key; #2: value \cs_new_protected:Npn \__tblr_row_gput_cell:nn #1 #2 { @@ -2271,6 +2377,7 @@ \NewColumnRowType { l } { Q[l] } \NewColumnRowType { c } { Q[c] } \NewColumnRowType { r } { Q[r] } +\NewColumnRowType { j } { Q[j] } \NewColumnType { t } [1] { Q[t,wd=#1] } \NewColumnType { p } [1] { Q[p,wd=#1] } @@ -2333,7 +2440,10 @@ } { \str_if_in:cnTF { g_tblr_used_ \g__tblr_column_or_row_tl _types_str } {#1} - { \cs:w tblr_ \g__tblr_column_or_row_tl _type_ #1 \cs_end: } + { + %% Note that #1 may be an active character (see issue #58) + \cs:w tblr_ \g__tblr_column_or_row_tl _type_ \token_to_str:N #1 \cs_end: + } { \msg_error:nnVn { tabularray } { unknown-colrow-type } \g__tblr_column_or_row_tl {#1} @@ -2578,8 +2688,10 @@ { \tl_set:Nn \l_tmpa_tl { ##1 } \__tblr_remove_braces:N \l_tmpa_tl + \__tblr_trim_par_space_tokens:N \l_tmpa_tl \int_incr:N \c@colnum \__tblr_extract_table_commands:N \l_tmpa_tl + \__tblr_trim_par_space_tokens:N \l_tmpa_tl \__tblr_spec_gput:neV { text } { [#1][\int_use:N \c@colnum] } \l_tmpa_tl \__tblr_add_multicolumn_empty_cell: } @@ -2599,6 +2711,15 @@ } } +\regex_const:Nn \c__tblr_trim_left_par_space_regex { ^ \c{par} ? \s * } +\regex_const:Nn \c__tblr_trim_right_space_par_regex { \s * \c{par} ? $ } + +\cs_new_protected:Npn \__tblr_trim_par_space_tokens:N #1 + { + \regex_replace_once:NnN \c__tblr_trim_left_par_space_regex {} #1 + \regex_replace_once:NnN \c__tblr_trim_right_space_par_regex {} #1 + } + %% Add empty cells after the \multicolumn span cell \cs_new_protected:Npn \__tblr_add_multicolumn_empty_cell: { @@ -2627,7 +2748,7 @@ \tl_clear:N \l__tblr_saved_table_commands_before_cell_text_tl \tl_clear:N \l__tblr_saved_cell_text_after_table_commands_tl \int_set:Nn \l__multicolumn_cell_number_int {1} - \exp_last_unbraced:NV \__tblr_extract_table_commands_next:w #1 \q_stop + \exp_last_unbraced:NV \__tblr_extract_table_commands_next:n #1 \q_stop \tl_if_empty:NF \l__tblr_saved_table_commands_before_cell_text_tl { \__tblr_prop_gput:nxV { command } @@ -2637,26 +2758,26 @@ \tl_set_eq:NN #1 \l__tblr_saved_cell_text_after_table_commands_tl } -%% #1 maybe a single token or multiple tokens given in braces -\cs_new_protected:Npn \__tblr_extract_table_commands_next:w #1 +%% #1 maybe a single token or multiple tokens from a pair of braces +\cs_new_protected:Npn \__tblr_extract_table_commands_next:n #1 { - \clist_if_in:NnTF \g__tblr_table_commands_clist { #1 } + \tl_if_single_token:nTF {#1} { - \clist_if_in:NnTF \g__tblr_table_commands_unbrace_next_clist { #1 } - { \bool_set_true:N \l__tblr_table_command_unbrace_next_bool } - { \bool_set_false:N \l__tblr_table_command_unbrace_next_bool } - \token_if_eq_meaning:NNTF #1 \multicolumn - { \__tblr_extract_multicolumn_command:Nn #1 } - { \__tblr_extract_one_table_command:N #1 } - } - { - \tl_if_single_token:nTF {#1} + \clist_if_in:NnTF \g__tblr_table_commands_clist { #1 } + { + \clist_if_in:NnTF \g__tblr_table_commands_unbrace_next_clist { #1 } + { \bool_set_true:N \l__tblr_table_command_unbrace_next_bool } + { \bool_set_false:N \l__tblr_table_command_unbrace_next_bool } + \token_if_eq_meaning:NNTF #1 \multicolumn + { \__tblr_extract_multicolumn_command:Nn #1 } + { \__tblr_extract_one_table_command:N #1 } + } { \token_if_eq_meaning:NNF #1 \q_stop { \__tblr_save_real_cell_text:w #1 } } - { \__tblr_save_real_cell_text:w {#1} } } + { \__tblr_save_real_cell_text:w {#1} } } \cs_new_protected:Npn \__tblr_extract_multicolumn_command:Nn #1 #2 @@ -2701,8 +2822,8 @@ } { \bool_if:NTF \l__tblr_table_command_unbrace_next_bool - { \__tblr_last_unbraced:Nn \__tblr_extract_table_commands_next:w } - { \__tblr_extract_table_commands_next:w } + { \__tblr_last_unbraced:Nn \__tblr_extract_table_commands_next:n } + { \__tblr_extract_table_commands_next:n } } } @@ -2764,6 +2885,7 @@ @vline-count = 0, } +\tl_new:N \l__tblr_inner_spec_measure_tl \tl_new:N \l__tblr_inner_spec_verb_tl \cs_new_protected:Npn \__tblr_init_table_inner_spec: @@ -2812,6 +2934,7 @@ \__tblr_spec_gput:nen { vline } { [\int_eval:n { \c@colcount + 1}] / ##1 } {##2} } + \tl_clear:N \l__tblr_inner_spec_measure_tl \tl_clear:N \l__tblr_inner_spec_verb_tl \keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _inner_tl } } @@ -3091,10 +3214,13 @@ \xleaders \l__tblr_b_tl \vfil } { + %% When using text as vline, we need to omit abovepos and belowpos. + \unskip \hbox_set:Nn \l__tblr_d_box { \l__tblr_b_tl } \box_set_ht:Nn \l__tblr_d_box {#4} \box_set_dp:Nn \l__tblr_d_box {#5} \box_use:N \l__tblr_d_box + \vss } \group_end: } @@ -3317,21 +3443,7 @@ \tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box } } { - \tl_set_eq:NN \l_tmpb_tl \l__tblr_c_tl - \__tblr_insert_braces:N \l_tmpb_tl - \seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpb_tl - \tl_set:Nn \l__tblr_w_tl { 0pt } - \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl - { - \__tblr_remove_braces:N \l_tmpa_tl - \hbox_set:Nn \l_tmpa_box - { - \l__tblr_f_tl - \__tblr_rescan_cell_tokens:N \l_tmpa_tl - } - \tl_set:Nx \l__tblr_w_tl - { \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } } - } + \__tblr_get_cell_size_with_box: } } \tl_put_left:NV \l__tblr_c_tl \l__tblr_f_tl @@ -3339,6 +3451,54 @@ \group_end: } +\cs_new_protected:Npn \__tblr_get_cell_size_with_box: + { + \tl_if_eq:NnTF \l__tblr_inner_spec_measure_tl { vbox } + { \__tblr_get_cell_size_with_vbox: } + { \__tblr_get_cell_size_with_hbox: } + } + +%% Varwidth won't work as expected when \color command occurs in it, +%% and we can not fix this problem with \leavevmode command. +%% See https://tex.stackexchange.com/q/460489. +%% But we need to use \color command for fg option, +%% or users may use it in the middle of the cell text, +%% so we have redefine \color command and disable it before measuring cell. + +\NewDocumentCommand \__tblr_fake_color_command:w { o m } { } + +\cs_new_protected:Npn \__tblr_get_cell_size_with_vbox: + { + \hbox_set:Nn \l_tmpa_box + { + \cs_set_eq:NN \color \__tblr_fake_color_command:w + \begin{varwidth}{\paperwidth} + \l__tblr_f_tl + \__tblr_rescan_cell_tokens:N \l__tblr_c_tl + \end{varwidth} + } + \tl_set:Nx \l__tblr_w_tl { \box_wd:N \l_tmpa_box } + } + +\cs_new_protected:Npn \__tblr_get_cell_size_with_hbox: + { + \tl_set_eq:NN \l_tmpb_tl \l__tblr_c_tl + \__tblr_insert_braces:N \l_tmpb_tl + \seq_set_split:NnV \l_tmpa_seq { \\ } \l_tmpb_tl + \tl_set:Nn \l__tblr_w_tl { 0pt } + \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl + { + \__tblr_remove_braces:N \l_tmpa_tl + \hbox_set:Nn \l_tmpa_box + { + \l__tblr_f_tl + \__tblr_rescan_cell_tokens:N \l_tmpa_tl + } + \tl_set:Nx \l__tblr_w_tl + { \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } } + } + } + %% #1: cell text; #2: box width \cs_new_protected:Npn \__tblr_get_vcell_and_sizes:NN #1 #2 { @@ -3401,13 +3561,18 @@ \box_use:N \l__tblr_strut_dp_box } +%% When using verb option, there is an end-of-line character at the end. +%% This character causes extra horizontal space at the end when "measure=hbox", +%% or causes extra vertical space at the end with "measure=vbox". +%% Therefore we have to use an \empty to remove it. +%% See https://tex.stackexchange.com/q/213659 \cs_new_protected:Npn \__tblr_rescan_cell_tokens:N #1 { \tl_if_empty:NTF \l__tblr_inner_spec_verb_tl { #1 } { \regex_replace_all:nnN { . } { \c{string} \0 } #1 - \tl_set:Nx #1 { #1 } + \tl_set:Nx #1 { #1 \noexpand \empty } \exp_args:NV \tex_scantokens:D #1 } } @@ -3657,7 +3822,8 @@ } %% If all columns have negative coefficients and small natural widths, -%% \l__column_coefficient_prop will be empty after one or more rounds +%% \l__column_coefficient_prop will be empty after one or more rounds. +%% We reset @row-height, etc for \linewidth graphics in X columns (issue #80) \cs_new_protected:Npn \__tblr_adjust_extendable_column_width: { \bool_while_do:nn @@ -3672,6 +3838,14 @@ \__tblr_data_gput:nnne { column } {##1} { width } {##2} \__tblr_data_gput:nnnn { column } {##1} { @col-width } { 0pt } } + \int_step_inline:nn { \c@rowcount } + { + \__tblr_data_gput:nnnn { row } {##1} { @row-height } { 0pt } + \__tblr_data_gput:nnnn { row } {##1} { @row-head } { 0pt } + \__tblr_data_gput:nnnn { row } {##1} { @row-foot } { 0pt } + \__tblr_data_gput:nnnn { row } {##1} { @row-upper } { 0pt } + \__tblr_data_gput:nnnn { row } {##1} { @row-lower } { 0pt } + } \__tblr_calculate_cell_sizes: } @@ -4154,8 +4328,8 @@ %% Cell is spanned from col #1 to col #2, #3 is the return dim \cs_new_protected:Npn \__tblr_calc_span_widths:nnN #1 #2 #3 { - \dim_zero:N #3 - \int_step_inline:nnn { #1 } { #2 } + \dim_set:Nn #3 { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#1] } } + \int_step_inline:nnn { #1 + 1 } { #2 } { \tl_set:Nx \l_tmpa_tl { \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] } } @@ -4535,6 +4709,17 @@ \par } } +\DefTblrTemplate { caption } { simple } + { + \UseTblrAlign { caption } + \UseTblrIndent { caption } + \UseTblrHang { caption } + \leavevmode + \UseTblrTemplate { caption-tag } { default } + \UseTblrTemplate { caption-sep } { default } + \UseTblrTemplate { caption-text } { default } + \par + } \SetTblrTemplate { caption } { normal } \DefTblrTemplate { capcont } { empty } { } @@ -4592,6 +4777,19 @@ \par } } +\DefTblrTemplate { capcont } { simple } + { + \UseTblrAlign { caption } + \UseTblrIndent { caption } + \UseTblrHang { caption } + \leavevmode + \UseTblrTemplate { caption-tag } { default } + \UseTblrTemplate { caption-sep } { default } + \UseTblrTemplate { caption-text } { default } + \space + \UseTblrTemplate { conthead-text } { default } + \par + } \SetTblrTemplate { capcont} { normal } %%% -------------------------------------------------------- @@ -4627,8 +4825,19 @@ { #2 } } +\DefTblrTemplate { note-border } { empty } + { + \hypersetup { pdfborder = { 0 ~ 0 ~ 0 } } + } +\DefTblrTemplate { note-border } { normal } + { + \hypersetup { pdfborder = { 0 ~ 0 ~ 1 } } + } +\SetTblrTemplate { note-border } { empty } + \NewDocumentCommand \TblrNote { m } { + \cs_if_exist:NT \hypersetup { \ExpTblrTemplate { note-border }{ default } } \__tblr_hyper_link:nn {#1} { \textsuperscript { \sffamily \UseTblrFont { note-tag } #1 } } } @@ -5005,9 +5214,10 @@ { \skip_vertical:n { \__tblr_spec_item:nn { outer } { presep } } } \LogTblrTracing { page } \nointerlineskip - \mode_leave_vertical: + \mode_leave_vertical: % enter horizontal mode to update \pagetotal \LogTblrTracing { page } \hrule height ~ 0pt + \nobreak % prevent page break after \hrule (see issue #42) \LogTblrTracing { page } \int_set:Nn \l__tblr_table_page_int {1} \__tblr_build_head_foot: @@ -5024,16 +5234,25 @@ \l_tmpa_dim \l__tblr_page_break_curr_bool \__tblr_check_table_page_break:NNN \l__tblr_remain_height_dim \l_tmpa_dim \l__tblr_page_break_prev_bool + \__tblr_do_if_tracing:nn { page } { \int_log:N \l__tblr_curr_i_int } \bool_if:NTF \l__tblr_page_break_prev_bool { - \__tblr_do_if_tracing:nn { page } { \int_log:N \l__tblr_curr_i_int } - \int_compare:nNnF - { \l__tblr_prev_i_int - \l__tblr_long_from_int } < {0} + \int_compare:nNnTF + { \l__tblr_long_from_int } > { \l__tblr_prev_i_int } + { + % See issue #42: if longtblr starts at the bottom of a page, + % \pagetotal maybe exceed \pagegoal after adding presep, + % or after adding rowhead or rowfoot of the table. + % In these cases, we will not typeset table in this page, + % but rather do some negative \vskip and execute \newpage. + \skip_vertical:n { \pagegoal - \pagetotal } + } { \__tblr_build_page_table:nnx {#1} { \int_use:N \l__tblr_long_from_int } { \int_use:N \l__tblr_prev_i_int } \int_incr:N \l__tblr_table_page_int + \int_set:Nn \l__tblr_long_from_int { \l__tblr_prev_i_int + 1 } } \newpage \hbox{}\kern-\topskip\nobreak @@ -5041,7 +5260,6 @@ \LogTblrTracing { page } \dim_set:Nn \l__tblr_remain_height_dim { \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim - \l_tmpa_dim } - \int_set:Nn \l__tblr_long_from_int { \l__tblr_prev_i_int + 1 } } { \bool_if:NTF \l__tblr_page_break_curr_bool @@ -5073,7 +5291,10 @@ \__tblr_build_page_table:nnn {#1} { \int_use:N \l__tblr_long_from_int } { \int_use:N \l__tblr_long_to_int } \skip_vertical:n { \__tblr_spec_item:nn { outer } { postsep } } - \hrule height ~ 0pt + % In the past we used "\hrule height ~ 0pt" to get strict postsep, + % but the postsep was not discarded when page breaks, see issue #39. + % Therefore we use \nointerlineskip here. + \nointerlineskip } \cs_generate_variant:Nn \__tblr_build_long_table:n { e } @@ -5225,10 +5446,16 @@ \bool_new:N \l__tblr_build_last_hline_bool \bool_set_true:N \l__tblr_build_first_hline_bool \bool_set_true:N \l__tblr_build_last_hline_bool +\box_new:N \l__tblr_table_hlines_box +\box_new:N \l__tblr_hline_box +\box_new:N \l__tblr_row_box %% #1: row from; #2: row to +%% To fix disappeared hlines with colorful tables in Adobe Reader (see #76), +%% we collect all hlines and draw them at the end of the table. \cs_new_protected:Npn \__tblr_build_one_table:nn #1 #2 { + \box_clear:N \l__tblr_table_hlines_box \vbox_set:Nn \l__tblr_table_box { \int_step_variable:nnNn {#1} {#2} \l__tblr_i_tl @@ -5236,18 +5463,50 @@ \bool_lazy_or:nnT { \int_compare_p:nNn { \l__tblr_i_tl } > {#1} } { \bool_if_p:N \l__tblr_build_first_hline_bool } - { \hbox:n { \__tblr_build_hline:V \l__tblr_i_tl } } + { \__tblr_put_one_hline:n { \__tblr_build_hline:V \l__tblr_i_tl } } \hrule height ~ 0pt % remove lineskip between hlines and rows - \hbox:n { \__tblr_build_row:N \l__tblr_i_tl } + \__tblr_put_one_row:n { \__tblr_build_row:N \l__tblr_i_tl } \hrule height ~ 0pt } \bool_if:NT \l__tblr_build_last_hline_bool - { \hbox:n { \__tblr_build_hline:n { \int_eval:n {#2 + 1} } } } + { + \__tblr_put_one_hline:n + { \__tblr_build_hline:n { \int_eval:n {#2 + 1} } } + } + \skip_vertical:n + { + - \box_ht:N \l__tblr_table_hlines_box + - \box_dp:N \l__tblr_table_hlines_box + } + \box_use:N \l__tblr_table_hlines_box } \bool_set_true:N \l__tblr_build_first_hline_bool \bool_set_true:N \l__tblr_build_last_hline_bool } +\cs_new_protected:Npn \__tblr_put_one_hline:n #1 + { + \hbox_set:Nn \l__tblr_hline_box {#1} + \skip_vertical:n { \box_ht:N \l__tblr_hline_box + \box_dp:N \l__tblr_hline_box } + \vbox_set:Nn \l__tblr_table_hlines_box + { + \vbox_unpack:N \l__tblr_table_hlines_box + \box_use:N \l__tblr_hline_box + } + } + +\cs_new_protected:Npn \__tblr_put_one_row:n #1 + { + \hbox_set:Nn \l__tblr_row_box {#1} + \vbox_set:Nn \l__tblr_table_hlines_box + { + \vbox_unpack:N \l__tblr_table_hlines_box + \skip_vertical:n + { \box_ht:N \l__tblr_row_box + \box_dp:N \l__tblr_row_box } + } + \box_use:N \l__tblr_row_box + } + %% #1: hline number \cs_new_protected:Npn \__tblr_build_one_hline:n #1 { @@ -5411,10 +5670,13 @@ \hrule height ~ 0pt % remove lineskip \hbox_set_to_wd:Nnn \l__tblr_b_box { \l__tblr_col_o_wd_dim } { + \__tblr_get_hline_left_right_skips:nnn {#1} {#2} {##1} + \skip_horizontal:N \l__tblr_hline_leftskip_dim \tl_set:Nx \l__tblr_f_tl { \__tblr_spec_item:ne { hline } { [#1][#2](##1) / fg } } \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} } \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1} + \skip_horizontal:N \l__tblr_hline_rightskip_dim } \box_set_ht:Nn \l__tblr_b_box { \l__tblr_h_tl } \box_set_dp:Nn \l__tblr_b_box { 0pt } @@ -5448,12 +5710,69 @@ } } +\dim_new:N \l__tblr_hline_leftskip_dim +\dim_new:N \l__tblr_hline_rightskip_dim + +%% Calculate left and right skips from leftpos and rightpos specifications +%% #1: row number; #2: column number; #3: hline index; +\cs_new_protected:Npn \__tblr_get_hline_left_right_skips:nnn #1 #2 #3 + { + \tl_set:Nx \l__tblr_hline_leftpos_tl + { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / leftpos } } + \tl_if_empty:NT \l__tblr_hline_leftpos_tl + { \tl_set:Nn \l__tblr_hline_leftpos_tl {1} } % default position + \tl_set:Nx \l__tblr_hline_rightpos_tl + { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / rightpos } } + \tl_if_empty:NT \l__tblr_hline_rightpos_tl + { \tl_set:Nn \l__tblr_hline_rightpos_tl {1} } % default position + \fp_compare:nNnT { \l__tblr_hline_leftpos_tl } < {1} + { + \dim_set:Nn \l_tmpa_dim + { \__tblr_spec_item:ne { vline } { [#2] / @vline-width } } + \dim_set:Nn \l_tmpb_dim + { \__tblr_data_item:nen { column } {#2} { leftsep } } + \fp_compare:nNnTF { \l__tblr_hline_leftpos_tl } < {0} + { + \dim_set:Nn \l__tblr_hline_leftskip_dim + { \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpb_dim } + } + { + \dim_set:Nn \l__tblr_hline_leftskip_dim + { \l_tmpa_dim - \l__tblr_hline_leftpos_tl \l_tmpa_dim } + } + } + \fp_compare:nNnT { \l__tblr_hline_rightpos_tl } < {1} + { + \dim_set:Nn \l_tmpa_dim + { + \__tblr_spec_item:ne { vline } + { [\int_eval:n { #2 + 1 }] / @vline-width } + } + \dim_set:Nn \l_tmpb_dim + { \__tblr_data_item:nen { column } {#2} { rightsep } } + \fp_compare:nNnTF { \l__tblr_hline_rightpos_tl } < {0} + { + \dim_set:Nn \l__tblr_hline_rightskip_dim + { \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpb_dim } + } + { + \dim_set:Nn \l__tblr_hline_rightskip_dim + { \l_tmpa_dim - \l__tblr_hline_rightpos_tl \l_tmpa_dim } + } + } + } + \dim_new:N \l__tblr_row_ht_dim \dim_new:N \l__tblr_row_dp_dim \dim_new:N \l__tblr_row_abovesep_dim \dim_new:N \l__tblr_row_belowsep_dim +\box_new:N \l__tblr_row_vlines_box +\box_new:N \l__tblr_vline_box +\box_new:N \l__tblr_cell_box %% Build current row, #1: row number +%% To fix disappeared vlines with colorful tables in Adobe Reader (see #76), +%% we collect all vlines and draw them at the end of the row. \cs_new_protected:Npn \__tblr_build_row:N #1 { \int_set:Nn \c@rownum {#1} @@ -5462,12 +5781,21 @@ \l__tblr_row_ht_dim \l__tblr_row_dp_dim \l__tblr_row_abovesep_dim \l__tblr_row_belowsep_dim \vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim ~ depth ~ \l__tblr_row_dp_dim + \hbox_set:Nn \l__tblr_row_vlines_box + { + \vrule width ~ 0pt ~ height ~ \l__tblr_row_ht_dim + ~ depth ~ \l__tblr_row_dp_dim + } \int_step_variable:nNn { \c@colcount } \l__tblr_j_tl { - \__tblr_build_vline_segment:nn {#1} { \l__tblr_j_tl } - \__tblr_build_cell:NN #1 \l__tblr_j_tl + \__tblr_put_one_vline:n + { \__tblr_build_vline_segment:nn {#1} { \l__tblr_j_tl } } + \__tblr_put_one_cell:n { \__tblr_build_cell:NN #1 \l__tblr_j_tl } } - \__tblr_build_vline_segment:nn {#1} { \int_eval:n {\c@colcount + 1} } + \__tblr_put_one_vline:n + { \__tblr_build_vline_segment:nn {#1} { \int_eval:n {\c@colcount + 1} } } + \skip_horizontal:n { - \box_wd:N \l__tblr_row_vlines_box } + \box_use:N \l__tblr_row_vlines_box } %% Read from table specifications and calculate inner height/depth of the row @@ -5500,6 +5828,28 @@ } \cs_generate_variant:Nn \__tblr_get_row_inner_height_depth:nNNNN { V } +\cs_new_protected:Npn \__tblr_put_one_vline:n #1 + { + \hbox_set:Nn \l__tblr_vline_box {#1} + \skip_horizontal:n { \box_wd:N \l__tblr_vline_box } + \hbox_set:Nn \l__tblr_row_vlines_box + { + \hbox_unpack:N \l__tblr_row_vlines_box + \box_use:N \l__tblr_vline_box + } + } + +\cs_new_protected:Npn \__tblr_put_one_cell:n #1 + { + \hbox_set:Nn \l__tblr_cell_box {#1} + \hbox_set:Nn \l__tblr_row_vlines_box + { + \hbox_unpack:N \l__tblr_row_vlines_box + \skip_horizontal:n { \box_wd:N \l__tblr_cell_box } + } + \box_use:N \l__tblr_cell_box + } + %% #1: row number, #2: column number \cs_new_protected:Npn \__tblr_build_vline_segment:nn #1 #2 { @@ -5530,12 +5880,6 @@ { \tl_set:Nx \l__tblr_s_tl { \__tblr_prop_item:ne { inner } { rulesep } } - \tl_set:Nx \l__tblr_b_tl - { - \__tblr_spec_item:ne { hline } - { [\int_eval:n{#1 + 1}](1) / @hline-height } - } - \tl_if_empty:NT \l__tblr_b_tl { \tl_set:Nn \l__tblr_b_tl { 0pt } } \hbox_set:Nn \l__tblr_a_box { \int_step_inline:nn { \l__tblr_n_tl } @@ -5548,10 +5892,12 @@ \tl_set:Nx \l__tblr_f_tl { \__tblr_spec_item:ne { vline } { [#1][#2](##1) / fg } } \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} } + \__tblr_get_vline_above_below_skips:nnn {#1} {#2} {##1} + \skip_vertical:N \l__tblr_vline_aboveskip_dim \__tblr_get_vline_segment_child:nnnxx {#1} {#2} {##1} { \dim_eval:n { \l__tblr_row_ht_dim } } - { \dim_eval:n { \l__tblr_row_dp_dim + \l__tblr_b_tl } } - \skip_vertical:n { - \l__tblr_b_tl } + { \dim_eval:n { \l__tblr_row_dp_dim } } + \skip_vertical:N \l__tblr_vline_belowskip_dim } \box_set_wd:Nn \l__tblr_b_box { \l__tblr_w_tl } \box_use:N \l__tblr_b_box @@ -5565,6 +5911,68 @@ \box_use:N \l__tblr_c_box } +\dim_new:N \l__tblr_vline_aboveskip_dim +\dim_new:N \l__tblr_vline_belowskip_dim + +%% Calculate above and below skips from abovepos and belowpos specifications +%% #1: row number; #2: column number; #3: vline index; +\cs_new_protected:Npn \__tblr_get_vline_above_below_skips:nnn #1 #2 #3 + { + \tl_set:Nx \l__tblr_vline_abovepos_tl + { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / abovepos } } + \tl_if_empty:NT \l__tblr_vline_abovepos_tl + { + \tl_set:Nn \l__tblr_vline_abovepos_tl {0} % default position + } + \tl_set:Nx \l__tblr_vline_belowpos_tl + { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / belowpos } } + \tl_if_empty:NT \l__tblr_vline_belowpos_tl + { + \tl_set:Nn \l__tblr_vline_belowpos_tl {0} % default position + } + \fp_compare:nNnF { \l__tblr_vline_abovepos_tl } = {0} + { + \dim_set:Nn \l_tmpa_dim + { \__tblr_spec_item:ne { hline } { [#1] / @hline-height } } + \fp_compare:nNnTF { \l__tblr_vline_abovepos_tl } < {0} + { + \dim_set:Nn \l__tblr_vline_aboveskip_dim + { - \l__tblr_vline_abovepos_tl \l__tblr_row_abovesep_dim } + } + { + \dim_set:Nn \l__tblr_vline_aboveskip_dim + { - \l__tblr_vline_abovepos_tl \l_tmpa_dim } + } + } + %% To join two vline segment above and below a cline, + %% we choose to extend every vline downwards a little (#55). + \fp_compare:nNnTF { \l__tblr_vline_belowpos_tl } = {0} + { + \dim_set:Nn \l__tblr_vline_belowskip_dim + { + - \__tblr_spec_item:ne { hline } + { [\int_eval:n { #1 + 1 }](1) / @hline-height } + + 0pt + } + } + { + \dim_set:Nn \l_tmpa_dim + { + \__tblr_spec_item:ne { hline } + { [\int_eval:n { #1 + 1 }] / @hline-height } + } + \fp_compare:nNnTF { \l__tblr_vline_belowpos_tl } < {0} + { + \dim_set:Nn \l__tblr_vline_belowskip_dim + { - \l__tblr_vline_belowpos_tl \l__tblr_row_belowsep_dim } + } + { + \dim_set:Nn \l__tblr_vline_belowskip_dim + { - \l__tblr_vline_belowpos_tl \l_tmpa_dim } + } + } + } + \tl_new:N \l__tblr_cell_rowspan_tl \tl_new:N \l__tblr_cell_colspan_tl \dim_new:N \l__tblr_cell_wd_dim @@ -5609,9 +6017,13 @@ { \hbox_set_to_wd:Nnn \l__tblr_a_box { \l__tblr_cell_wd_dim } { - \tl_if_eq:NnF \g__tblr_cell_halign_tl {l} { \hfil } - \__tblr_get_cell_text:nn {#1} {#2} - \tl_if_eq:NnF \g__tblr_cell_halign_tl {r} { \hfil } + \tl_if_eq:NnTF \g__tblr_cell_halign_tl {j} + { \__tblr_get_cell_text:nn {#1} {#2} } + { + \tl_if_eq:NnF \g__tblr_cell_halign_tl {l} { \hfil } + \__tblr_get_cell_text:nn {#1} {#2} + \tl_if_eq:NnF \g__tblr_cell_halign_tl {r} { \hfil } + } } \vbox_set_to_ht:Nnn \l__tblr_b_box { \l__tblr_cell_ht_dim } { @@ -6043,10 +6455,56 @@ \NewTblrLibrary { booktabs } { - \NewTableCommand \toprule [1] [] { \hline [0.08em, ##1] } - \NewTableCommand \midrule [1] [] { \hline [0.05em, ##1] } - \NewTableCommand \bottomrule [1] [] { \hline [0.08em, ##1] } - \NewTableCommand \cmidrule [2] [] { \cline [0.03em, ##1] { ##2 } } + % We only use dimensions \aboverulesep and \belowrulesep in booktabs package + \RequirePackage { booktabs } + \newcommand \tblr@booktabs@hline [1] [] { \hline [##1] } + \newcommand \tblr@booktabs@oldhline [1] [] { + \hline [abovespace = \aboverulesep, belowspace = \belowrulesep, ##1] + } + \newcommand \tblr@booktabs@cline [2] [] { \cline [##1] {##2} } + \newcommand \tblr@booktabs@oldcline [2] [] { + \cline [abovespace = \aboverulesep, belowspace = \belowrulesep, ##1] {##2} + } + \newcommand \tblr@booktabs@cline@more [2] [] { \SetHline [+] {##2} {##1} } + \newcommand \tblr@booktabs@oldcline@more [2] [] { + \SetHline [+] {##2} { + abovespace = \aboverulesep, belowspace = \belowrulesep, ##1 + } + } + \NewTableCommand \toprule [1] [] { + \tblr@booktabs@hline [wd=\heavyrulewidth, ##1] + } + \NewTableCommand \midrule [1] [] { + \tblr@booktabs@hline [wd=\lightrulewidth, ##1] + } + \NewTableCommand \bottomrule [1] [] { + \tblr@booktabs@hline [wd=\heavyrulewidth, ##1] + } + \NewTableCommand \cmidrule [2] [] { + \tblr@booktabs@cline [wd=\cmidrulewidth, endpos, ##1] {##2} + } + \NewTableCommand \cmidrulemore [2] [] { + \tblr@booktabs@cline@more [wd=\cmidrulewidth, endpos, ##1] {##2} + } + \newcommand \tblr@booktabs@change@more [1] { \cmidrulemore } + \NewTableCommand \morecmidrules { + \peek_meaning:NTF \cmidrule { \tblr@booktabs@change@more } { \relax } + } + \NewTblrEnviron { booktabs } + \SetTblrInner [ booktabs ] { rowsep = 0pt } + \RequirePackage { etoolbox } + \AtBeginEnvironment { booktabs } + { + \let \tblr@booktabs@hline = \tblr@booktabs@oldhline + \let \tblr@booktabs@cline = \tblr@booktabs@oldcline + \let \tblr@booktabs@cline@more = \tblr@booktabs@oldcline@more + } + \NewTableCommand \specialrule [3] + { \hline [##1, abovespace = ##2, belowspace = ##3] } + \NewTableCommand \addrowspace [1] [\defaultaddspace] + { \SetVspace { abovespace+ = (##1) / 2, belowspace+ = (##1) / 2 } } + \NewTableCommand \addlinespace [1] [\defaultaddspace] + { \SetVspace { abovespace+ = (##1) / 2, belowspace+ = (##1) / 2 } } } %% Library diagbox and command \diagbox @@ -6136,4 +6594,12 @@ } } -\ExplSyntaxOff +%% Library varwidth and measure option + +\NewTblrLibrary { varwidth } + { + \RequirePackage { varwidth } + \clist_gput_left:Nn \g__tblr_table_known_keys_clist { measure } + \keys_define:nn { tblr } { measure .tl_set:N = \l__tblr_inner_spec_measure_tl } + } + |