我找到了如何重复使用命令名称。
但是我如何才能多次重复使用一个命令,每次都使用以前的定义?如果我只是尝试类似
\newcommand{\aaa}{a}
\let\oldaaa\aaa
\renewcommand{\aaa}{\oldaaa b} % now \aaa is ab
\let\oldaaa\aaa
\renewcommand{\aaa}{\oldaaa c} % now \aaa should be abc
我明白了TeX 容量超出错误。
这是一个非常简单的例子。当我尝试编写一个可以完成类似任务的命令时,问题出现了,即在重复调用时连接其参数;因此,理想情况下,每次重复的代码都应该相似。
答案1
请记住,(La)TeX 是一种宏编程语言,它有一个称为“扩展”的奇怪东西。例如,如果
\newcommand{\aaa}{a}
然后\aaa
扩展到a
。换句话说,a
是 的“替换文本” \aaa
。在 的定义中
\let\oldaaa\aaa
\renewcommand{\aaa}{\oldaaa b} % now \aaa is ab
您正在将 的定义复制\aaa
到 中\oldaaa
(实际上类似于\def\oldaaa{<whatever \aaa is>}
,但是不是与 相同\def\oldaaa{\aaa}
),随后将 重新定义为\aaa
。\oldaaa b
在扩张- 当你写 时\aaa
,这将被 替换\oldaaa b
,并且由于你\let\oldaaa\aaa
,这将被 替换\aaa b
,这是循环的。以下是分步展示:
\newcommand{\aaa}{a}
\let\oldaaa\aaa
\renewcommand{\aaa}{\oldaaa b}
> \aaa
> \oldaaa b % Expansion of \aaa
> \aaa b % Expansion of \oldaaa
> \oldaaa b b % Expansion of \aaa
> \aaa b b % Expansion of \oldaaa
> \oldaaa b b b % Expansion of \aaa
> ...
我认为您想要的是扩展重新定义时的内容,如下所示:
\newcommand{\aaa}{a}
\expandafter\renewcommand\expandafter\aaa\expandafter{\aaa b} % now \aaa is ab
\expandafter\renewcommand\expandafter\aaa\expandafter{\aaa c} % now \aaa should be abc
请注意,由于替换文本\aaa
是扩展在进行分配之前,因此无需使用额外的宏,例如\oldaaa
。这也仅在重新定义的内容本身可扩展时才有效。
答案2
你可以避免\expandafter
使用etoolbox
包。这需要您的 TeX 可执行文件包含 e-TeX 扩展,但这很有可能是您的安装中的默认扩展。
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\newcommand{\aaa}{a}
\show\aaa
\apptocmd{\aaa}{b}{\message{aaa successfully patched}}{\message{aaa not successfully patched}}
\show\aaa
\apptocmd{\aaa}{c}{\message{aaa successfully patched}}{\message{aaa not successfully patched}}
\show\aaa
\end{document}
的参数\apptocmd
是宏名称、要添加到定义中的内容,然后是成功或失败时要执行的操作。我使用最后一个参数只是为了向控制台/日志文件报告修补成功或失败。 \show
将暂停编译并将宏的当前值写入控制台。每次都必须按 Enter 键才能继续。结果是:
...
> \aaa=\long macro:
->a.
l.6 \show\aaa
? [ENTER]
aaa successfully patched
> \aaa=macro:
->ab.
l.8 \show\aaa
? [ENTER]
aaa successfully patched
> \aaa=macro:
->abc.
l.10 \show\aaa
? [ENTER]
(./aaa.aux) )
No pages of output.
...