tabularray无法正常展开宏的问题

发布于 2024-08-26 20:22:41

在tblr里面执行逻辑操作的时候遇到了问题:

  1. 如何显示l3变量?使用gset
  2. 计数器失效?

计数器MWE:

image.png

\documentclass[zihao=-4,a4paper,punct=kaiming,oneside]{ctexart}
\usepackage{tabularray}
\UseTblrLibrary{counter}
% % 逻辑页计数器
\newcounter{lfrmc}
\setcounter{lfrmc}{0}
\NewExpandableDocumentCommand{\spl}{}
{%
    \thelfrmc%
    \addtocounter{lfrmc}{1}
}
\NewExpandableDocumentCommand{\lfrmh}{}
{%
    empty&ok&\spl\\
}

\begin{document}
\begin{longtblr}[expand=\expanded]{
    colspec={|X|X|X|}
}
\expanded{\lfrmh}
\expanded{\lfrmh}
\expanded{\lfrmh}
a&b&c\\\hline
\end{longtblr}
最右边一列希望是:0、1、2……递增
\end{document}

image.png

更新对问题(1)的一个解答:

\documentclass[zihao=-4,a4paper,punct=kaiming,oneside]{ctexart}
% \input{pkg.tex}
\usepackage{xeCJK}
\usepackage{xeCJKfntef}
\usepackage{xcolor}
\usepackage{tabularray}
\UseTblrLibrary{booktabs}
\UseTblrLibrary{varwidth}
\UseTblrLibrary{counter}
% \input{tuning.tex}
\ExplSyntaxOn
\tl_new:N \g_ttle_tl
\NewDocumentCommand{\ttle}{o m}
{
    \tl_set:Nx \g_ttle_tl {#2}
}
\NewDocumentCommand{\sttle}{}
{
    \tl_use:N \g_ttle_tl
}
\ExplSyntaxOff

% \input{tblr.tex}
% % 逻辑页计数器
\newcounter{lfrmc}
\setcounter{lfrmc}{0}

\NewExpandableDocumentCommand{\spl}{}
{%
    \thelfrmc%
    \addtocounter{lfrmc}{1}
}
\NewExpandableDocumentCommand{\lfrmh}{}
{%
    empty&{\sttle\\nothing~here!}&\spl\\
}

\begin{document}
\begin{longtblr}[expand=\expanded]{
    colspec={|X|X|X|}
}
\ttle[1]{tblr标题}%
\expanded{\lfrmh}
\expanded{\lfrmh}
1&2&3\\\hline
\end{longtblr}

\ttle[0]{第一个标题}
\sttle

\ttle[1]{第两个标题}
\sttle
\end{document}

image.png


上面是mwe,完整的源代码如下文件:

完整的源代码.zip

在写一个演讲稿模板,已经基本全部写完,但是……

在tblr里面执行逻辑操作的时候遇到了问题

查看更多

关注者
0
被浏览
789
1 个回答
Sagittarius Rover
Sagittarius Rover 2025-02-14
我要成为Typst糕手/(ㄒoㄒ)/~~

考古...

参考自QQ群里Eureka老师给的回答,请看下面的对比。

当然,OP原问题给的代码过长了,提问应该尽量保证代码“最简短”,避免增加阅读障碍。
输出latex3变量和计数器问题显然应该另开两个问题,这样很容易让后来的读者感到混乱迷惑,削弱论坛的信息共享作用。

可以比较下面的例子:

\documentclass{article}
\usepackage{tabularray}
\UseTblrLibrary{counter}
\newcounter{cntA}
\newcounter{cntB}
\NewExpandableDocumentCommand{\cmdA}{}
{%
    \thecntA%
    \addtocounter{cntA}{1}
}
\NewExpandableDocumentCommand{\cmda}{}
{%
   okA&\cmdA\\
}
\newcommand{\cmdB}{%
    \thecntB%
    \addtocounter{cntB}{1}
}
\newcommand*{\cmdb}{%
    okB&\cmdB\\
}
\setlength{\parindent}{0pt}
\begin{document}

\begin{tblr}[expand=\expanded]{colspec={|X|X|}}
    \expanded{\cmda}
    \expanded{\cmda}
    \expanded{\cmda}
\end{tblr}

\bigskip

\begin{tblr}[expand=\cmdb]{colspec={|X|X|}}
    \cmdb
    \cmdb
    \cmdb
\end{tblr}
\end{document}

image.png

tblr以及longtblr环境中,有两种展开方式:

  • 直接使用expand=<expandable token>,将直接展开一次
  • 如果使用expand=\expanded后在tblr内部使用\expanded{<expandable token>}进行完全(exhaustive)展开(e-type展开)

而虽然\newcommand\NewExpandableDocumentCommand定义的命令均可展开,但:

  • \newcommand允许只执行部分展开
  • \NewExpandableDocumentCommand要求只能被完全展开

而同时\addtocounter实际上是TeX原语\advance\value{cnt}+1:

\addtocounter: 
macro:#1#2->\@ifundefined {c@#1}{\@nocounterr {#1}}{\global \advance \csname c@#1\endcsname #2\relax }

这是一种assignment过程,属于不可展开的命令,他们因此不应该被放在\NewExpandableDocumentCommand内部。若如此做,将导致该命令变为不可展开类型。

因此在OP的原问题中,tblr环境将会先搜集其内部的所有命令,然后再执行展开\NewExpandableDocumentCommand定义的\cmd(但此时不可展开)。此时使用\expanded{\cmd}将导致直接进行e-type展开将\thecnt完全展开为初始值0.

因此洞察到\addtocounter不可展开,同时在这一情形下仅需要单步展开,决定了应该使用\newcommand以及\expand=\cmd实现.

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览