宏中的列分隔符用于呈现 tabularray 的行

宏中的列分隔符用于呈现 tabularray 的行

我正在尝试以编程方式排版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/82186https://tex.stackexchange.com/a/243627/82186tabularray似乎引入了一些我无法确定的差异(事实上,这些解决方案无法替换tabulartblr

仅使用较短的例子来阐明我需要使用的技术可能就足以解决问题,但我添加了较长的例子,因为那是我需要使用它的情况。

答案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- 有目的的扩展:

expl3.pdf说:

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}

请坚持推荐的命名方案。

在此处输入图片描述

相关内容