etoolbox 使用宏作为参数

etoolbox 使用宏作为参数

我正在尝试使用 pdflatex 制作一个自动会议日志生成器。我想创建一个包含 n 行的表格,并用逗号分隔的 typein 输入填充它们。我myTable这个答案,如果我直接在文本中写入,它就可以正常工作。 (1)但是如果我使用\def\variable\typein[\variable]{variable}(2),它会失败并出现以下错误。

据我所知,我可能应该\expandafter以某种方式使用某个地方,但我自己无法弄清楚。

\documentclass[a4paper,11pt]{article}

\usepackage{etoolbox}

\def\variable{Person 1/Active/Online/X,Person 2/Active/-/-,Person 3/Intern/Office/X}

\def\addtablerow#1/#2/#3/#4!{\textbf{#1} & #2 & #3 & #4\\}
\newcommand{\myTable}[1]{
    \renewcommand*\do[1]{\addtablerow##1!}
    \begin{tabular}{|p{0.4\textwidth}|p{0.2\textwidth} | p{0.2\textwidth} |        p{0.2\textwidth}|}
        \hline
        Name & Role & Presence & Present \\ \hline
        \docsvlist{#1} \hline
    \end{tabular}
}


\begin{document}
    % 1
    \myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
    % 2
    \myTable{\variable}
\end{document}

完整错误:

\variable !\etb@lst@docsvlist \@nil \etb@lst@q@end ,& \hline \end {ta\ETC.
! File ended while scanning use of \addtablerow.
<inserted text> 
                \par 
<*> test.tex
            
! Emergency stop.
<*> test.tex

答案1

该调用\myTable{\variable}传递一个长度为 1 的列表。您需要访问价值之前\variable完成\myTable其工作。

因此,正如另一个答案所暗示的是正确的,尽管没有必要\expandafter在前面添加\addtablerow

我建议采用一种不同的方法,即使用命名空间的模拟expl3来避免污染代码。\def

如果您想使用先前定义的列表,则宏\printlist将采用。*

如果您需要的所有列表都是这样的,您可以避免这种*变体,更改代码应该很容易。

其工作原理与 非常相似\docsvlist,但有一些优势:例如,逗号分隔符周围的空格会被忽略。这里的\clist_map_inline:nN作用类似于\docsvlist,您无需重新定义,而是\do定义一组两个宏,其中第一个宏与 类似\addtablerow,但必须将其拆分为外部部分和内部部分。

表格前言已经修复,以避免过满:您的表格比文本宽度长,因为您没有考虑列间空间。

\documentclass[a4paper,11pt]{article}

\ExplSyntaxOn

\NewDocumentCommand{\definelist}{mm}
 {
  \clist_clear_new:c { l_fauszt_list_#1_clist }
  \clist_set:cn { l_fauszt_list_#1_clist } { #2 }
 }

\NewDocumentCommand{\printlist}{sm}
 {% the star variant uses a list name
  % otherwise a full list is passed
  \IfBooleanTF{#1}
   {
    \fauszt_list_print:v { l_fauszt_list_#2_clist }
   }
   {
    \fauszt_list_print:n { #2 }
   }
 }

\cs_new_protected:Nn \fauszt_list_print:n
 {
  \begin{tabular}{
    |p{\dimexpr0.4\textwidth-2\tabcolsep}
    |p{\dimexpr0.2\textwidth-2\tabcolsep}
    |p{\dimexpr0.2\textwidth-2\tabcolsep}
    |p{\dimexpr0.2\textwidth-2\tabcolsep}|
  }
  \hline
  Name & Role & Presence & Present \\
  \hline
  \clist_map_function:nN { #1 } \__fauszst_list_print_row:n
  \end{tabular}
 }
\cs_generate_variant:Nn \fauszt_list_print:n { v }

\cs_new_protected:Nn \__fauszst_list_print_row:n
 {
  \__fauszt_list_print_row:w #1 \q_stop
 }
\cs_new_protected:Npn \__fauszt_list_print_row:w #1 / #2 / #3 / #4 \q_stop
 {
  \textbf{#1} & #2 & #3 & #4 \\ \hline
 }

\ExplSyntaxOff

\definelist{variable}{
  Person 1/Active/Online/X,
  Person 2/Active/-/-,
  Person 3/Intern/Office/X
}

\begin{document}

\noindent
\printlist{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}

\bigskip

\noindent
\printlist*{variable}

\end{document}

在此处输入图片描述

可以进行进一步的概括。


为了完整起见,我将证明我的说法,在提出的解决方案中用户237299\expandafter,中的标记\expandafter\addtablerow##1可以被删除,因为它没有任何用处(并且它甚至可能在极端情况下做坏事)。

让我们按照扩展来做。当\variable定义为问题中所述时,调用为

\noindent\expandafter\myTable\expandafter{\variable}

(第一个提出的解决方案),这与调用

\noindent\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}

然后\docsvlist将确定第一项并将其作为括号参数传递给\do,因此循环中的第一个循环将执行

\do{Person 1/Developer/Online/X}

这将成为

\expandafter\addtablerow Person 1/Developer/Online/X!

并且\expandafter显然是无用的。

在第二个解决方案中,调用的是\myTable{\variable},然后主要部分是

\expandafter\docsvlist\expandafter{\variable}

但它只是第一个的变体,其工作原理完全相同。

然后 user237299 声称\expandafter我指的将在呼叫发生时有用\myTable{\variableTwo},其中已经发生

\def\variableTwo{\variable}

不幸的是,事实并非如此。事实上,使用第一个解决方案(但使用第二个解决方案完全相同),

\expandafter\myTable\expandafter{\variableTwo}

即成为

\myTable{\variable}

调用\docsvlist{\variable}。参数没有逗号,因此执行单个循环,调用变为

\expandafter\addtablerow\variable

没什么用,因为我们会得到

\addtablerow Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X!

当然,\def\variableTwo{\variable}在这种情况下,这样做毫无意义。如果想要为 指定别名\variable,也许是为了在保留先前列表的情况下对其进行扩充,则应该执行\let\variableTwo=\variable

答案2

你只需要一些\expandafters。

\documentclass[a4paper,11pt]{article}

\usepackage{etoolbox}

\def\variable{Person 1/Active/Online/X,Person 2/Active/-/-,Person 3/Intern/Office/X}

\def\addtablerow#1/#2/#3/#4!{\textbf{#1} & #2 & #3 & #4\\}
\newcommand{\myTable}[1]{
    \renewcommand*\do[1]{\expandafter\addtablerow##1!}
    \begin{tabular}{|p{0.4\textwidth}|p{0.2\textwidth} | p{0.2\textwidth} |        p{0.2\textwidth}|}
        \hline
        Name & Role & Presence & Present \\ \hline
        \docsvlist{#1} \hline
    \end{tabular}
}


\begin{document}
    % 1
    \noindent\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
    % 2
    \par
    \noindent\expandafter\myTable\expandafter{\variable}
\end{document}

在此处输入图片描述

或者

\documentclass[a4paper,11pt]{article}

\usepackage{etoolbox}

\def\variable{Person 1/Active/Online/X,Person 2/Active/-/-,Person 3/Intern/Office/X}

\def\addtablerow#1/#2/#3/#4!{\textbf{#1} & #2 & #3 & #4\\}
\newcommand{\myTable}[1]{%
    \renewcommand*\do[1]{\expandafter\addtablerow##1!}
    \begin{tabular}{|p{0.4\textwidth}|p{0.2\textwidth} | p{0.2\textwidth} |        p{0.2\textwidth}|}
        \hline
        Name & Role & Presence & Present \\ \hline
        \expandafter\docsvlist\expandafter{#1} \hline
    \end{tabular}
}


\begin{document}
    % 1
    \noindent\myTable{Person 1/Developer/Online/X,Person 2/Developer/-/-,Person 3/Intern/Office/X}
    % 2
    \par
    \noindent\myTable{\variable}
\end{document}

相关内容