![如何将命令附加到宏而不展开它们](https://linux22.com/image/266199/%E5%A6%82%E4%BD%95%E5%B0%86%E5%91%BD%E4%BB%A4%E9%99%84%E5%8A%A0%E5%88%B0%E5%AE%8F%E8%80%8C%E4%B8%8D%E5%B1%95%E5%BC%80%E5%AE%83%E4%BB%AC.png)
我正在构建一个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
也在 中定义etoolbox
。eTeX
-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