tabularray icon indicating copy to clipboard operation
tabularray copied to clipboard

Access measuring phase?

Open cgnieder opened this issue 3 years ago • 9 comments

Many table packages (e.g. tabularx, tabu, ltxtable) have measuring phases which detect column widths etc before actually typesetting the table. Sometimes other packages need to be able to access this phase because their macros change their outcome between first and subsequent typesetting (think of acronyms of the acro or acronym packages and see https://github.com/cgnieder/acro/blob/master/code/acro.patch.code.tex as an example).

The tabu package has \tabuDisableCommands for accessing the measuring phase, \TX@trial can be patched for tabularx, etc.

Is there an official way to do the same for tabularray?

cgnieder avatar Jan 15 '22 12:01 cgnieder

At this time, there are no hooks within tabularray tables. I will add them some day. As the first step, please provide a minimal nonworking example here.

lvjr avatar Jan 15 '22 13:01 lvjr

There is not really a not working example. As author of acro I'd like to have an interface to tabularray so I could add \acswitchoff if needed during the measuring phase. You can see why this is necessary here:

\documentclass{article}
\usepackage{acro}
\usepackage{tabularray}

\DeclareAcronym{ma}{
  short = MA ,
  long  = my acronym
}

\begin{document}

\begin{tblr}{XcX}
  a & MA & b
\end{tblr}

\begin{tblr}{XcX}
  a & \ac{ma} & b
\end{tblr}

\acresetall

\begin{tblr}{XcX}
  a & \acswitchoff\ac{ma} & b
\end{tblr}

\end{document}

cgnieder avatar Jan 15 '22 14:01 cgnieder

Currently, the code is a little messy. We use function \__tblr_make_vcell_text to typeset the cell once. And we even don't know whether it is the last time when we are typesetting the cell. Therefore I need to do some refactoring first.

\__tblr__builder
   \__tblr_calc_cell_and_line_sizes
      \__tblr_calculate_line_sizes
      \__tblr_calculate_cell_sizes
         \__tblr_get_cell_text
            \__tblr_get_vcell_and_sizes
               \__tblr_make_vcell_text
               \__tblr_make_vcell_text
      \__tblr_compute_extensible_column_widths 
         \__tblr_calculate_cell_sizes (only for X columns)
            \__tblr_get_cell_text
               \__tblr_get_vcell_and_sizes
                  \__tblr_make_vcell_text
                  \__tblr_make_vcell_text
      \__tblr_adjust_sizes_for_span_cells 
         \__tblr_calculate_cell_sizes (only for multicolumn cells)
            \__tblr_get_cell_text
               \__tblr_get_vcell_and_sizes
                  \__tblr_make_vcell_text
                  \__tblr_make_vcell_text
   \__tblr_build_whole
      \__tblr_get_cell_text
         \__tblr_get_vcell_and_sizes
            \__tblr_make_vcell_text
            \__tblr_make_vcell_text

lvjr avatar Jan 16 '22 12:01 lvjr

@cgnieder Since tabularray package is quite different from tabularx and tabu, I am afraid you have to do similar things as counter library does. That is to say, you have to add two functions for saving and restoring usage status for all acronyms, respectively. Then you could do the patch:

\apptocmd \__tblr_save_counters:n { \__acro_save_usage_status_all:n {#1} } {} {}
\pretocmd \__tblr_restore_counters:n { \__acro_restore_usage_status_all:n {#1} } {} {}

The above two functions will accept table or cell as parameters, and save/restore usage status to/from different places.

lvjr avatar Feb 13 '22 02:02 lvjr

Well, this looks like the right track. This code

\ExplSyntaxOn
\NewTblrLibrary {acro}
  { \cs_set_protected:Npn \__tblr_save_counters:n ##1 { \acro_switch_off: } }
\ExplSyntaxOff
\UseTblrLibrary {acro}

get's the above example to work.

If there was an official hook right before (or after) each \__tblr_save_counters:n then I could provide code in acro. Right now

  • \__tblr_save_counters:n is a private command and
  • using \pretocmd with it is bound to fail in cases because the counter library changes the definition again so execution order matters (also it's mixing interfaces):
\ExplSyntaxOn
\NewTblrLibrary {acro}
  { \pretocmd \__tblr_save_counters:n { \acro_switch_off: } {} { \fail } }
\ExplSyntaxOff
\UseTblrLibrary {acro}
\UseTblrLibrary {counter}

Could you just provide \l_tblr_before_measurement_tl (or similar) inserted at all places where \__tblr_save_counters:n is placed? Then I could just do

\tl_put_right:Nn \l_tblr_before_measurement_tl { \acro_switch_off: }

in acro.

cgnieder avatar Feb 24 '22 19:02 cgnieder

I am sorry, but simply using \acswitchoff will make wrong results if you use a acronym multiple times in tblr.

\documentclass{article}

\usepackage{acro}
\usepackage{tabularray}

\DeclareAcronym{ma}{
  short = MA ,
  long  = my acronym
}

\ExplSyntaxOn
\cs_set_protected:Npn \__tblr_save_counters:n #1 { \acro_switch_off: }
\ExplSyntaxOff

\begin{document}
  
\begin{tblr}{hlines,vlines}
  \ac{ma} & \ac{ma}
\end{tblr}

\end{document}

image

You have to create two new functions as described in my previous comment.

lvjr avatar Feb 25 '22 02:02 lvjr

Thanks to pull request #265, now \__tblr_make_vcell_text is called once when typesetting a cell, therefore we can easily recognize measuring state.

lvjr avatar Jan 23 '23 02:01 lvjr

@cgnieder I have added \lTblrMeasuringBool to tabularray and the following example produces correct result:

\documentclass{article}

\usepackage{tabularx}
\usepackage{tabularray}

\usepackage{acro}
\DeclareAcronym{ma}{
  short = MA ,
  long  = my acronym
}

\newcommand\myac[1]{\IfBooleanT\lTblrMeasuringBool{\acswitchoff}\ac{#1}}

\begin{document}

\section{tabularx}

\acresetall

\begin{tabularx}{\linewidth}{|X|X|X|}
\hline
  \ac{ma} & \ac{ma} & \ac{ma} \\
\hline
\end{tabularx}

\section{tabularray}

\acresetall

\begin{tblr}{colspec={XXX},hlines,vlines}
  \myac{ma} & \myac{ma} & \myac{ma} \\
\end{tblr}

\end{document}

image

lvjr avatar Jan 23 '23 02:01 lvjr

Although

Thanks to pull request #265, now \__tblr_make_vcell_text is called once when typesetting a cell,

the content of a cell would still be boxed at most twice if column width is not specified, see code lines 3700 and 3704 below.

https://github.com/lvjr/tabularray/blob/690e67ee175ff7601d0144c84f9a7e9c67573e0b/tabularray.sty#L3694-L3713

The attempt in https://github.com/lvjr/tabularray/issues/179#issuecomment-1399695943

\newcommand\myac[1]{\IfBooleanT\lTblrMeasuringBool{\acswitchoff}\ac{#1}}
[...]
\acresetall

\begin{tblr}{colspec={XXX},hlines,vlines}
  \myac{ma} & \myac{ma} & \myac{ma} \\
\end{tblr}

worked because column widths were set by colspec={XXX}. Without colspec={XXX}, that example failed. In general cases, using \lTblrMeasuringBool only is not sufficient to ensure executing some code once per cell.

Hence tabularray either needs another boolean or needs to adjust the position where \lTblrMeasuringBool is set true. But I'm afraid none will help acro have a solution simpler than https://github.com/lvjr/tabularray/issues/179#issuecomment-1037692123.

muzimuzhi avatar Oct 07 '23 07:10 muzimuzhi