![在 RTL 上下文中,tblr 表格中的移位 hlines](https://linux22.com/image/459966/%E5%9C%A8%20RTL%20%E4%B8%8A%E4%B8%8B%E6%96%87%E4%B8%AD%EF%BC%8Ctblr%20%E8%A1%A8%E6%A0%BC%E4%B8%AD%E7%9A%84%E7%A7%BB%E4%BD%8D%20hlines.png)
我正在尝试tabularray
通过添加(lualatex 引擎)在 RTL 上下文中测试包提供的 tblr 表格\textdir TRT
,除了本例中显示的这个问题之外,一切看起来都很好
\documentclass{article}
\usepackage{tabularray}
\textdir TRT
\begin{document}
\begin{tblr}{|c|}
\hline
one\\
\hline
\end{tblr}
\end{document}
输出看起来不错,但如果放大,可以看到以下缺陷(水平线穿过表格左侧)
对于双 v 线,缺陷变得更大,h 线向左移动更多
\documentclass{article}
\usepackage{tabularray}
\textdir TRT
\begin{document}
a%
\begin{tblr}{|c||}
\hline
one\\
\hline
\end{tblr}%
b
\end{document}
评论
表格必须在 RTL 上下文中,不能包含在 LTR 组中,因此第二列必须位于第一列的左侧。
答案1
问题来自于\mathdir
,tblr
使用\vcenter
类似标准表格环境的命令,所以基本上我们在表格开头处于数学模式,并且 mathdir 是 TLT,我们需要在从右到左的上下文中将其更改为 TRT 以便进行表格处理。
需要在表格单元格内恢复数学方向(RTL 上下文中的数学方向始终是 LTR),这可以通过以下方式完成\SetTblrInner{cells={preto={\mathdir TLT}}}
(感谢@UdiFogiel)
\documentclass{article}
\usepackage{tabularray}
\setlength\parindent{0pt}
\AddToHook{env/tblr/begin}{%
\ifnum\textdirection=0\else \mathdir TRT\fi
}
\SetTblrInner{cells={preto={\mathdir TLT}}}
\begin{document}
Hello\par
\begin{tblr}{|c||c|||}
\hline
one & two \\
\hline
\end{tblr}
\textdir TRT
Hello\par
\begin{tblr}{|c||c|||}
\hline
one & two $ax+b$\\
\hline
\end{tblr}
$ax+b$
\end{document}
答案2
我找不到问题的根源,但您可能会满足于将表格括在 LTR 组中并反转单元格的水平顺序(在内部,不以反向方式输入它们,并且单元格本身仍然是 RTL)。
\documentclass{article}
\usepackage{tabularray}
\ExplSyntaxOn
\makeatletter
\bool_new:N \__tblr_RTL_bool
\cs_set_protected:Npn \__tblr_split_one_line:nn #1 #2
{
\seq_set_split:Nnn \l_tmpa_seq { & } { #2 }
\bool_if:NTF \__tblr_RTL_bool
{
\seq_reverse:N \l_tmpa_seq
}
{ }
\int_set:Nn \c@rownum {#1}
\int_zero:N \c@colnum
\seq_map_inline:Nn \l_tmpa_seq
{
\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
\bool_if:NTF \__tblr_RTL_bool
{
\tl_if_empty:NTF \l_tmpa_tl { } {\tl_put_left:Nn \l_tmpa_tl { \textdir TRT } }
}
{ }
\__tblr_trim_par_space_tokens:N \l_tmpa_tl
\__tblr_spec_gput:neV { text } { [#1][\int_use:N \c@colnum] } \l_tmpa_tl
}
\bool_lazy_all:nTF
{
{ \int_compare_p:nNn {#1} = {\c@rowcount} }
{ \int_compare_p:nNn {\c@colnum} = {1} }
{ \tl_if_empty_p:N \l_tmpa_tl }
}
{ \int_decr:N \c@rowcount }
{
\__tblr_prop_gput:nnx
{row} { [#1] / cell-number } { \int_use:N \c@colnum }
\int_compare:nT { \c@colnum > \c@colcount }
{
\int_set_eq:NN \c@colcount \c@colnum
}
}
}
\cs_set_protected:Npn \__tblr_environ_code:nnnn #1 #2 #3 #4
{
\group_align_safe_begin:
\int_gincr:N \g__tblr_table_count_int
\tl_set:Nn \l__tblr_env_name_tl {#1}
\mode_if_math:TF
{ \bool_set_true:N \l__tblr_math_mode_bool }
{ \bool_set_false:N \l__tblr_math_mode_bool }
\str_if_eq:eeTF { TRT } { \lua_now:n { tex.print(tex.textdir) } }
{
\bool_set_true:N \__tblr_RTL_bool
\textdir TLT
}
{ }
\__tblr_builder:nnn {#2} {#3} {#4}
\group_align_safe_end:
}
\makeatother
\ExplSyntaxOff
\pagedir TRT \bodydir TRT \pardir TRT \textdir TRT
\begin{document}
\begin{tblr}{|c|c|}
\hline
one & two\\
\hline
\end{tblr}
\begin{tblr}{|c|c||}
\hline
one & two\\
\hline
\end{tblr}%
\end{document}
使用上述代码,与内部规范相关的所有水平坐标都将被反转,例如在第二个表格中,双垂直线位于右侧而不是左侧。我相信它也可以修复,但我发现这种行为更方便。
评论
leftpos
我认为问题与、rightpos
和abovepos
内部规范键有关belowpos
,看看它们如何影响您给出的示例
\documentclass{article}
\usepackage{tabularray}
\textdir TRT
\begin{document}
\begin{tblr}{hlines={rightpos=0},vlines={abovepos=1}}
one\\
\end{tblr}
a%
\begin{tblr}{colspec={|c||},hlines={rightpos=0},vlines={abovepos=1}}
one\\
\end{tblr}%
b
\end{document}
\end{document}
也许该功能\__tblr_get_hline_left_right_skips:nnn
是造成此问题的原因。
编辑
我想在 Salim Bou 的出色解决方案中添加一些内容。我们可以修补命令\__tblr_environ_code:nnnn
来测试文本方向,而不是使用钩子,这样我们就不需要\ifnum\textdirection=0\else \mathdir TRT\fi
为每个通过定义的环境钩住测试\NewTblrEnviron
。可以使用
\ExplSyntaxOn
\cs_set_protected:Npn \__tblr_environ_code:nnnn #1 #2 #3 #4
{
\ifnum\textdirection=0\else \mathdir TRT\fi % <<< new
\group_align_safe_begin:
\int_gincr:N \g__tblr_table_count_int
\tl_set:Nn \l__tblr_env_name_tl {#1}
\mode_if_math:TF
{ \bool_set_true:N \l__tblr_math_mode_bool }
{ \bool_set_false:N \l__tblr_math_mode_bool }
\__tblr_builder:nnn {#2} {#3} {#4}
\group_align_safe_end:
}
\ExplSyntaxOff
另一个观察结果是,具有外部属性的 Tblrlong
没有使用数学模式,如下面的代码所示:
\documentclass{article}
\usepackage{tabularray}
\begin{document}
\pagedir TRT \bodydir TRT
Hello\par
\begin{longtblr}{|c||c|||}
\hline
one & two $ax+b$\\
\hline
\end{longtblr}
\end{document}
但它需要\pagedir
以RTL 排版\bodydir
。TRT
最后要注意的是,\SetTblrInner[tblr,longtblr]{cells={cmd={\mathdir TLT}}}
如果单元格扭曲了多个括号,则使用将失败,例如下表中方程的方向是错误的
\documentclass{article}
\usepackage{tabularray}
\AddToHook{env/tblr/begin}{%
\ifnum\textdirection=0\else \mathdir TRT\fi
}
\SetTblrInner{cells={cmd={\mathdir TLT}}}
\begin{document}
\textdir TRT
Hello\par
\begin{tblr}{|c||c|||}
\hline
one & {{{two $ax+b$}}}\\
\hline
\end{tblr}
$ax+b$
\end{document}
因此,使用可能会更好\SetTblrInner{cells={preto={\mathdir TLT}}}
,或者我们可以再次修补,这样我们就不必将内部规范添加到\NewTblrEnviron
使用以下内容定义的每个环境中
\ExplSyntaxOn
\makeatletter
\cs_set_protected:Npn \__tblr_split_one_line:nn #1 #2
{
\seq_set_split:Nnn \l_tmpa_seq { & } { #2 }
\int_set:Nn \c@rownum {#1}
\int_zero:N \c@colnum
\seq_map_inline:Nn \l_tmpa_seq
{
\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
\tl_if_empty:NF \l_tmpa_tl {\tl_put_left:Nn \l_tmpa_tl { \mathdir TLT } } % <<< new
\__tblr_spec_gput:neV { text } { [#1][\int_use:N \c@colnum] } \l_tmpa_tl
}
%% Decrease row count by 1 if the last row has only one empty cell text
%% We need to do it here since the > or < column type may add text to cells
\bool_lazy_all:nTF
{
{ \int_compare_p:nNn {#1} = {\c@rowcount} }
{ \int_compare_p:nNn {\c@colnum} = {1} }
{ \tl_if_empty_p:N \l_tmpa_tl }
}
{ \int_decr:N \c@rowcount }
{
\__tblr_prop_gput:nnx
{row} { [#1] / cell-number } { \int_use:N \c@colnum }
\int_compare:nT { \c@colnum > \c@colcount }
{
\int_set_eq:NN \c@colcount \c@colnum
}
}
}
\makeatother
\ExplSyntaxOff