![宏中的列分隔符用于呈现 tabularray 的行](https://linux22.com/image/436523/%E5%AE%8F%E4%B8%AD%E7%9A%84%E5%88%97%E5%88%86%E9%9A%94%E7%AC%A6%E7%94%A8%E4%BA%8E%E5%91%88%E7%8E%B0%20tabularray%20%E7%9A%84%E8%A1%8C.png)
我正在尝试以编程方式排版tblr
表格内的行(来自tabularray
),但无法解决Misplaced alignment tab character &
错误。
这个最小的例子重现了我的确切情况,包括我正在执行的宏调用的结构:
\documentclass{article}
\usepackage{xparse,tabularray}
\begin{document}
\ExplSyntaxOn
\seq_new:N \entries_seq
\NewDocumentCommand { \entry } { m m m } {
\seq_put_right:Nn \entries_seq { { #1 } { #2 } { #3 } }
}
\cs_new:Nn \make_row:nnn {
% NOTE: this macro will also contain some complex logic for rendering the cells content
#1 & #2 & #3 \\
}
\NewDocumentEnvironment { mytblr } {} {} {
\begin{tblr}{lll}
A & B & C \\
\seq_map_inline:Nn \entries_seq { \make_row:nnn ##1 }
X & Y & Z \\
\end{tblr}
}
\ExplSyntaxOff
\begin{mytblr}
\entry{1}{2}{3}
\entry{4}{5}{6}
\end{mytblr}
\end{document}
这个最小的例子仅仅重现了错误,忽略了我代码的当前组织:
\documentclass{article}
\usepackage{tabularray}
\begin{document}
\ExplSyntaxOn
\cs_new:Nn \make_test_row: {
1 & 2 & 3 \\
}
\begin{tblr}{lll}
\make_test_row:
\end{tblr}
\ExplSyntaxOff
\end{document}
我知道https://tex.stackexchange.com/a/338918/82186和https://tex.stackexchange.com/a/243627/82186但tabularray
似乎引入了一些我无法确定的差异(事实上,这些解决方案无法替换tabular
)tblr
。
仅使用较短的例子来阐明我需要使用的技术可能就足以解决问题,但我添加了较长的例子,因为那是我需要使用它的情况。
答案1
[在您的示例中,您没有遵循命名控制序列的所有 expl3 约定。
在我的编码示例中,我重命名了事物以符合约定。]
在您的示例中,\entry
-macro 用于累积序列变量中的事物。您在mytblr
-environment 中使用它。在该环境的末尾,存储在变量中的东西将嵌套在 -environment 中。如果-environment 包含除对 -macro 的调用之外的其他内容tblr
,您没有指定所需的行为。mytblr
\entry
例如,你没有指定所需的输出
\begin{mytblr}
\entry{1}{2}{3}%
A&B&C\\
\entry{4}{5}{6}%
\end{mytblr}
其中A&B&C\\
不会变成序列变量的元素,因此尝试排版会立即在环境之外进行tblr
。
由于您没有指定这一点,我假设您的mytblr
-environment 实例仅包含对的调用\entry
,而不包含其他任何内容。
tblr
包的环境表格数组需要扩大其身体。
因此,尽管据说使用 expl3-stuff 您不需要关心扩展问题,但您必须确保将内容传递到tblr
扩展环境中。
\entries_seq
在以下情况下使用序列变量界面3.pdf我没有找到任何可扩展函数记录,用于将函数调用映射到序列变量的项目,这样您可以一次性获得整个函数调用序列,而无需进一步的扩展技巧。
\map{{A}{B}{C}}{\thing}
(在扩展上下文中,屈服\thing{A}\map{{B}{C}}{\thing}
和
\map{{A}{B}{C}}{\thing}
一次性屈服之间的区别\thing{A}\thing{B}\thing{C}
很重要。
似乎使用 expl3-mapping-functions 你会得到类似进一步的东西。
你可能还需要应对控制扩展的级别\thing
。)
您可以解决这个问题,例如,通过将序列变量的内容映射\l__MyModule_entries_seq
到标记列表变量\l__MyModule_entries_tl
,从而将其添加\__MyModule_MakeRow:nnn
到序列的每个元素前面并扩展该命令。
映射后,\use_ii_i:nn
您可以通过将 token-list-variable 的内容\l__MyModule_entries_tl
与 tokens进行交换\begin{tblr}{lll} A & B & C \\
。
\documentclass{article}
\usepackage{xparse,tabularray}
\ExplSyntaxOn
% Probably you can use one of the scratch-variables \l_tmpa_seq / \l_tmpb_seq instead:
\seq_new:N \l__MyModule_entries_seq
% Probably you can use one of the scratch-variables \l_tmpa_tl / \l_tmpb_tl instead:
\tl_new:N \l__MyModule_entries_tl
\NewDocumentCommand { \entry } { m m m } {
\seq_put_right:Nn \l__MyModule_entries_seq { { #1 } { #2 } { #3 } }
}
\cs_new:Nn \__MyModule_MakeRow:nnn {
% NOTE: this macro will also contain some complex logic for rendering the cells content
#1 & #2 & #3 \\
}
% \cs_new:Nn \use_ii_i:nn { #2 #1 }
\NewDocumentEnvironment { mytblr } {} {\seq_clear:N \l__MyModule_entries_seq} {
\tl_clear:N \l__MyModule_entries_tl
\seq_map_inline:Nn \l__MyModule_entries_seq { \tl_put_right:No \l__MyModule_entries_tl {\__MyModule_MakeRow:nnn ##1} }
\exp_args:NV \use_ii_i:nn { \l__MyModule_entries_tl }
{ \begin{tblr}{lll}
A & B & C \\ }
X & Y & Z \\
\end{tblr}
}
\ExplSyntaxOff
\begin{document}
\begin{mytblr}%
\entry{1}{2}{3}%
\entry{4}{5}{6}%
\end{mytblr}
\end{document}
实际上,这没有必要那么复杂。你可以不使用序列变量,而只使用标记列表变量:
\documentclass{article}
\usepackage{xparse,tabularray}
\ExplSyntaxOn
% Probably you can use one of the scratch-variables \l_tmpa_tl / \l_tmpb_tl instead:
\tl_new:N \l__MyModule_entries_tl
\NewDocumentCommand { \entry } { m m m } {
\tl_put_right:No \l__MyModule_entries_tl {\__MyModule_MakeRow:nnn { #1 } { #2 } { #3 } }
}
\cs_new:Nn \__MyModule_MakeRow:nnn {
% NOTE: this macro will also contain some complex logic for rendering the cells content
#1 & #2 & #3 \\
}
% \cs_new:Nn \use_ii_i:nn { #2 #1 }
\NewDocumentEnvironment { mytblr } {} {\tl_clear:N \l__MyModule_entries_tl} {
\exp_args:NV \use_ii_i:nn { \l__MyModule_entries_tl }
{ \begin{tblr}{lll}
A & B & C \\ }
X & Y & Z \\
\end{tblr}
}
\ExplSyntaxOff
\begin{document}
\begin{mytblr}%
\entry{1}{2}{3}%
\entry{4}{5}{6}%
\end{mytblr}
\end{document}
我刚刚意识到:在 expl3 版本中\seq_map_tokens:Nn
引入了 2019-08-30。
使用此功能您可以仅使用序列变量,而不需要标记列表变量:
\documentclass{article}
\RequirePackage{xparse}
\usepackage{tabularray}
\ExplSyntaxOn
% Probably you can use one of the scratch-variables \l_tmpa_seq / \l_tmpb_seq instead:
\seq_new:N \l__MyModule_entries_seq
\cs_new:Nn \MyModule_JoinArgsAndCallExpNot:Nnnn {
% #1 some \exp_args...-command to be applied to #2#4#3
% #2 tokens to prepend to element of sequence
% #3 tokens to append to element of sequence
% #4 element of sequence
#1 \exp_not:n {#2#4#3}
}
\NewDocumentCommand { \entry } { m m m } {
\seq_put_right:Nn \l__MyModule_entries_seq { { #1 } { #2 } { #3 } }
}
\cs_new:Nn \__MyModule_MakeRow:nnn {
% NOTE: this macro will also contain some complex logic for rendering the cells content
#1 & #2 & #3 \\
}
% \cs_new:Nn \use_ii_i:nn { #2 #1 }
\NewDocumentEnvironment { mytblr } {} {\seq_clear:N \l__MyModule_entries_seq} {
\exp_args:Nx \use_ii_i:nn {
\seq_map_tokens:Nn \l__MyModule_entries_seq { \MyModule_JoinArgsAndCallExpNot:Nnnn \exp_args:No {\__MyModule_MakeRow:nnn} {} }
}{ \begin{tblr}{lll}
A & B & C \\ }
X & Y & Z \\
\end{tblr}
}
\ExplSyntaxOff
\begin{document}
\begin{mytblr}%
\entry{1}{2}{3}%
\entry{4}{5}{6}%
\end{mytblr}
\end{document}
在上面这个例子中,我使用了o- 有目的的扩展:
o单级扩展标记或带括号的标记列表。
这意味着参数被扩展一级,如\expandafter
,并且扩展作为带括号的标记列表传递给函数。请注意,如果原始参数是带括号的标记列表,则仅扩展该列表中的第一个标记。一般来说,使用五应该优先使用o用于简单变量检索
所有这些示例的输出为:
这些例子只是一个起点。
所需的修改取决于您的评论的含义\make_row:nnn
:
% 注意:此宏还将包含一些用于呈现单元格内容的复杂逻辑
在任何情况下,处理和扩展事物的链必须以这样一种方式进行:在序列后面传递的标记列表变量的内容由使用\begin{tblr}{lll} A & B & C \\
环境主体根据需要扩展的标记序列组成tblr
。
答案2
您想使用可扩展映射,所以\seq_map_function:NN
。
\documentclass{article}
%\usepackage{xparse} % not needed with LaTeX 2020-10-01 or later
\usepackage{tabularray}
\ExplSyntaxOn
\seq_new:N \pb_mytblr_entries_seq
\NewDocumentCommand { \entry } { m m m }
{
\seq_put_right:Nn \pb_mytblr_entries_seq { { #1 } { #2 } { #3 } }
}
\cs_new:Nn \pb_mytblr_make_row:n
{
\pb_mytblr_make_row:nnn #1
}
\cs_new:Nn \pb_mytblr_make_row:nnn
{
% NOTE: this macro will also contain some complex logic for rendering the cells content
#1 & #2 & #3 \\
}
\NewDocumentEnvironment { mytblr } {}
{
% do nothing at the beginning
}
{
\use:e
{
\exp_not:N \begin{tblr}{lll}
A & B & C \\
\seq_map_function:NN \pb_mytblr_entries_seq \pb_mytblr_make_row:n
X & Y & Z \\
\exp_not:N \end{tblr}
}
}
\ExplSyntaxOff
\begin{document}
\begin{mytblr}
\entry{1}{2}{3}
\entry{4}{5}{6}
\end{mytblr}
\end{document}
请坚持推荐的命名方案。