如何将命令附加到宏而不展开它们

如何将命令附加到宏而不展开它们

我正在构建一个expenses包。目的是能够编写

\expense{someone}{something}{something a bit longer}{10}{GBP}
\expense{someone else }{something else}{something a bit longer}{11}{EUR}
\makeexpensetable

为此,我启动了一个内部\allexpenses

\def\allexpenses{}

然后每个\expense命令附加一个\writeexpense定义为的命令

\newcommand{\writeexpense}[5]{%
    #1 & #2 & #4 \\ %
}

因此最终\makeexpensetable命令将简单地开始一个表格,然后有一行\allexpenses包含所有行并结束该表格。

我当前的\expense命令是

\newcommand{\expense}[5]{%
    \edef\allexpenses{\allexpenses%
        \writeexpense{#1}{#2}{#3}{#4}{#5}%
    }%
}

但是,由于\writeexpense命令的存在,TeX 会抛出错误。我该如何阻止该命令扩展?我猜答案与命令的正确使用有关\noexpand,但我无法弄清楚。

答案1

替代的、@无解决方案:

\usepackage{etoolbox}
\appto\allexpenses{\writeexpense{#1}{#2}{#3}{#4}{#5}}

还有一两个包裹-free 解决方案,但它们实际上是在重新发明\appto轮子。问题是它以递归方式扩展其内容,而您只希望扩展\edef初始内容\allexpenses一次。事实上,这不是你想要的\noexpand,而是:\unexpanded

\edef\allexpenses{%
  \expandafter\unexpanded\expandafter{\allexpenses}%
  \unexpanded{\writeexpense{#1}{#2}{#3}{#4}{#5}}%
}

这会导致\allexpenses被扩展一次,变成它所包含的内容,然后这些内容将受到保护,以免进一步扩展。第一行相当于\expandonce\allexpenses,其中\expandonce也在 中定义etoolboxeTeX-free 解决方案是为此使用令牌寄存器:

\toks0=\expandafter{\allexpenses \writeexpense{#1}{#2}{#3}{#4}{#5}}
\edef\allexpenses{\the\toks0}

标记寄存器是原始的\expandonce,但由于它们的分配不是完全可扩展的,它们并不总是适合这个基于 eTeX 的宏。

答案2

\g@addto@macro\allexpenses{\writeexpense{#1}{#2}{#3}{#4}{#5}}
在包文件中或之间使用\makeatletter \makeatother

相关内容