lvjr / tabularray

Typeset tabulars and arrays with LaTeX3
https://ctan.org/pkg/tabularray
247 stars 22 forks source link

Proper usage of `cmd` on columns #439

Closed mikkelee closed 8 months ago

mikkelee commented 9 months ago

First off, excellent package!

I'm working on a package that can display and perform arithmetic with older non-decimal unit systems. Since I often use tabular data, I've been experimenting with a tblr column type.

I have two questions:

I set up the column like so, with a call that amounts to \NewColumnType {U}[2] { Q[r, font={\ndu_tblr_configure_column:nn{##1}{##2}}, cmd=\ndu_tblr_cell:n] }: https://github.com/mikkelee/latex-units/blob/dev/expl3/latex/non-decimal-units.sty#L640-L700

Below is a small example that can be tested with the dev/expl3 branch of my package: https://github.com/mikkelee/latex-units/blob/dev/expl3/latex

\documentclass{article}

\usepackage
    [danish]
    {non-decimal-units}

\usepackage{tabularray}
\UseTblrLibrary{booktabs}

\nduKeys {
    treat zero as nil,
    replace nil with=---,
    tabularray column type=U,
}

\begin{document}

\begin{tblr}{r U{danish rigsdaler}{add to variable=test} U{danish hartkorn}{cell width=2em}}
    \toprule
    & HEADER & HEADER \\
    \midrule
    a & 1.2.3 & 1.2 \\
    b & 100.0.0 & 0.1 \\
    c & .1. & 0.0 \\
    \bottomrule
    & RESULT & SKIP \\
\end{tblr}

\end{document}
Screenshot 2023-10-06 at 14 51 58

(6 mk/mark = 1 rdl/rigsdaler, so the true result 3 becomes multiplied by 4 = 12 mark, which is converted into 2 rigsdaler on top of the already quadrupled 101)

Cheers!

muzimuzhi commented 9 months ago
  • The formatting works fine, but I'm currently abusing the font key to set up some of my own keys based on the column config, as I can only pass one parameter (the cell contents) through to cmd.

The total effects of options cmd, font, preto and appto are

<font> \selectfont <cmd> { <preto> <cell-content> <appto> }

Here <cmd> can be any token list that optionally takes a mandatory argument. Hence you can use

\keys_define:nn { non-decimal-units }
{
    tabularray~column~type      .code           = {
            \NewColumnType {#1}[2] { Q[r, cmd=\ndu_tblr_cell:nnn {##1} {##2}] }
        } ,
}

and then use \ndu_tblr_configure_column:nn {#1} {#2} inside new \ndu_tblr_cell:nnn.

  • The arithmetic fails (result is exactly 4 times too big) because it appears cmd is called 4 times per cell: twice for each cell ordered by (row, column), and then that loop runs once again.

Yes each cell is typeset multiple times. For your specific config, the exact number is 4.

tabularray provided expl3 bool \lTblrMeasuringBool to expose the measuring and building phases, but unfortunately, even in building phase (when \lTblrMeasuringBool is false) each cell may be typeset once or twice, depending on whether the corresponding column width is set. See #179.

A general scheme is shown in https://github.com/lvjr/tabularray/issues/179#issuecomment-1037692123. Because whether doing math (\nduMath) in non RESULT cells doesn't affect the content of current cell itself (unlike the acro example in #179), special workarounds exist. For example, If the total number of ndu tabularray columns (and cells) in a document is relatively small, one can construct a distinct control sequence per table per cell to mark if math is done for it, hence make sure math is done only once per cell.

My attempt (also pushed to my fork, see https://github.com/mikkelee/latex-units/compare/dev/expl3...muzimuzhi:latex-non-decimal-units:arithmatic-in-tblr)

Update: I'm deleting my branch arithmatic-in-tblr since the patch is now part of the upstream repo, see https://github.com/mikkelee/latex-units/compare/b214f187...1501145c.

git patch

```diff From 7fc24fc9020fc9a0ea5e1867f6e5466eaaf40885 Mon Sep 17 00:00:00 2001 From: Yukai Chou Date: Sat, 7 Oct 2023 17:13:54 +0800 Subject: [PATCH 1/2] refactor(tblr): no abuse of `font` option --- latex/non-decimal-units.sty | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/latex/non-decimal-units.sty b/latex/non-decimal-units.sty index e822650..4f555a7 100644 --- a/latex/non-decimal-units.sty +++ b/latex/non-decimal-units.sty @@ -648,7 +648,7 @@ \keys_define:nn { non-decimal-units } { tabularray~column~type .code = { - \NewColumnType {#1}[2] { Q[r, font={\ndu_tblr_configure_column:nn{##1}{##2}}, cmd=\ndu_tblr_cell:n] } + \NewColumnType {#1}[2] { Q[r, cmd=\ndu_tblr_cell:nnn {##1} {##2}] } } , } @@ -673,9 +673,10 @@ \tl_const:Nn \c__ndu_RESULT_tl { RESULT } \tl_const:Nn \c__ndu_SKIP_tl { SKIP } -\cs_new_protected:Nn \ndu_tblr_cell:n +\cs_new_protected:Nn \ndu_tblr_cell:nnn { - \tl_set:Nn \l_tmpa_tl {#1} + \ndu_tblr_configure_column:nn {#1} {#2} + \tl_set:Nn \l_tmpa_tl {#3} \tl_case:NnF \l_tmpa_tl { \c__ndu_HEADER_tl { \nduHeader @@ -695,7 +696,7 @@ % format value if no special token was hit \nduValue { \tl_use:N \l__ndu_tblr_column_type_tl } - { #1 } + { #3 } } } -- 2.42.0 From 1501145cd6d4fb6551174162ec72fe23bef3d1e6 Mon Sep 17 00:00:00 2001 From: Yukai Chou Date: Sat, 7 Oct 2023 17:15:48 +0800 Subject: [PATCH 2/2] fix(tblr): do math only once per cell Not ideal, but working. --- latex/non-decimal-units.sty | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/latex/non-decimal-units.sty b/latex/non-decimal-units.sty index 4f555a7..9dac5d5 100644 --- a/latex/non-decimal-units.sty +++ b/latex/non-decimal-units.sty @@ -694,12 +694,27 @@ } { % format value if no special token was hit + % do math only once per tblr cell + % Will https://github.com/lvjr/tabularray/issues/179 introduce + % elenganter solution? + \cs_if_exist:cTF { \ndu__tblr_cell_get_csname: } + % or use a specific bool, e.g., \ndu__do_math_bool + { \tl_clear:N \l_ndu_current_variable_tl } + { \cs_gset:cpn { \ndu__tblr_cell_get_csname: } {} } \nduValue { \tl_use:N \l__ndu_tblr_column_type_tl } { #3 } } } +% a csname distinct per tblr table, per cell +\cs_new:Npn \ndu__tblr_cell_get_csname: + { + ndu__tblr_ \int_use:N \g__tblr_table_count_int + _cell_ \int_use:N \c@rownum _ \int_use:N \c@colnum + : + } + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Setup % -- 2.42.0 ```

PS: I used \<module>__<description>:<arg-spec> to represent private functions (two _ after <module>, not just one), as texdoc expl3, sec. 3.2.1 "Separating private and public material" suggested. You may find texdoc l3styleguide also helpful.

mikkelee commented 9 months ago

Oh wow! That is an incredible answer, that you so much. I've merged it locally and will get back tomorrow or monday (not at home right now, parents' old imac :))

mikkelee commented 8 months ago

I'm back. Everything works perfectly, so I will likely be publishing the next version of my package on CTAN in the coming week. Thanks again! I'm adding a short thank you in the documentation :-)

mikkelee commented 8 months ago

For future reference, the update was published: https://ctan.org/ctan-ann/id/mailman.3270.1697052309.3764.ctan-ann@ctan.org

No worries about deleting the branch