我想定义一种自己的索引,它收集某些信息和一个计数器值 - 在下面的小示例中,命令\addstuff
可能会将计数器的值作为其第一个参数,将描述作为其第二个参数。第一个条目也可能是文本本身,甚至是空的。
我想收集所有这些值文本条目并在最后创建一个输出。在下面的示例中,描述始终反映出我希望计数器值在该条目中是什么。
\documentclass[a4paper]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\newcommand{\collect}{}
\newcounter{mycounter}\setcounter{mycounter}{1}
\makeatletter
\newcommand{\addstuff}[2]{\g@addto@macro\collect{#1 & #2\\}}
\makeatother
\newcommand{\generateOutput}{%
Output of collection\par%
\begin{tabular}{rl}\collect\end{tabular}%
}
\begin{document}
\addstuff{normal}{Entry}
\addstuff{\themycounter}{save the 1 it should have here}
\refstepcounter{mycounter} %incement -> 2
\addstuff{\arabic{mycounter}}{<-save the 2 of the counter}
\refstepcounter{mycounter} %incement -> 3
% Print all saved data
\generateOutput
\end{document}
所以我的问题是,如何评估第一个参数以获取当前计数器的实际值\addstuff
?因为在此代码中,我保存在集合中的两行最终分别具有值3
而不是1
或2
。
答案1
LaTeX 中完全扩展的一个问题是,有些命令是“危险的”;因此需要采用两遍方法。在命令中,\addstuff
您希望第一个参数被扩展到最大可能,而第二个参数则“按原样”采用。
\makeatletter
\newcommand{\addstuff}[2]{%
\protected@edef\@tempa{#1}%
\expandafter\g@addto@macro\expandafter\collect\expandafter{%
\@tempa & #2 \\}}
\makeatother
如果扩张的论点不是第一个,情况会更加复杂。另一种方法可能是
\makeatletter
\newcommand{\addstuff}[2]{%
\protected@edef\@tempa{#1 & \unexpanded{#2} \noexpand\\}
\expandafter\g@addto@macro\expandafter\collect\expandafter{\@tempa}}
\makeatother
其中哪些可以扩展,哪些不可以扩展,这一点更加清晰。
如果对第一个参数中允许的内容有更多的控制,即没有任何内容需要“保护”,则可以一步完成:
\makeatletter
\newcommand{\addstuff}[2]{%
\begingroup\edef\x{\endgroup
\noexpand\g@addto@macro\noexpand\collect
{#1 & \unexpanded{#2} \noexpand\\}}\x}
\makeatother
但如果按照这个定义,看似无辜的事情\addstuff{\bfseries special}{stuff}
就会惨遭失败。
答案2
使用令牌寄存器,使生活更加轻松。
\documentclass[a4paper]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\newtoks\tabtoks
\newcommand\addstuff[2]{%
\begingroup\edef\x{\endgroup
\noexpand\tabtoks{\the\tabtoks
#1 & \noexpand#2 \noexpand\\}}\x}
\newcommand*\resettabtoks{\tabtoks{}}
\newcounter{mycounter}
\setcounter{mycounter}{1}
\newcommand\generateOutput{%
Output of collection\par%
\begin{tabular}{ll}\the\tabtoks\end{tabular}}
\begin{document}
\resettabtoks
\addstuff{normal}{Entry}
\addstuff{\themycounter}{save the 1 it should have here}
\refstepcounter{mycounter} %incement -> 2
\addstuff{\themycounter}{<-save the 2 of the counter}
\refstepcounter{mycounter} %incement -> 3
\addstuff{\noexpand\bfseries foo}{a test}
\addstuff{\themycounter}{is three}
\generateOutput
\end{document}