预先添加和附加代码或修补命令的明确方法?

预先添加和附加代码或修补命令的明确方法?

考虑以下示例:我们有一个命令\mycmd,在某些包中定义为:

\DeclareRobustCommand{\mycmd}{%
    <original source code>
}

我们想要修补此命令,即在前置和附加代码的意义上。这些可能包含任何内容,包括\if \else包装原始代码的构造。直接的当然,这样做的方法是最初以这种方式定义命令。如果命令已经存在,我们可以先使用etoolbox's删除它来修补它\undef

\undef{\mycmd}
\DeclareRobustCommand{\mycmd}{%
    <pre code>
    <original source code>
    <post code>
}

我的问题:

看来etoolbox的设施(\appto\apptocmd等等)并非在所有情况下都能发挥作用。

有没有什么方法可以实现这种修补,而不必逐字复制粘贴原始源代码(但在所有情况下都具有 100%相同的行为)?

这是一个后续问题重新定义 \- 的安全方法仅适用于数学模式

答案1

简短的回答:没有“明确的方法”。

如何(以及是否可能)修补(或添加或附加)命令取决于它的定义方式(\def\newcommand\DeclareRobustCommand\NewDocumentCommand)、是否接受参数、命令的内容是什么,以及什么您想要修补该命令。


无参数的宏:最简单的情况是命令不带参数。在这种情况下,宏(用expl3术语来说)是一个“标记列表”,您可以展开宏并对其内容执行任何操作。该标记列表中的所有内容(不出所料)都是标记,因此您可以遍历它、查询其内容、随意添加和删除标记。在这种情况下,添加前缀和后缀很简单(请参阅\g@addto@macroin的定义latex.ltx),再次修补中间内容的难度取决于您要替换的内容。

带参数的宏:更棘手的情况是宏带有参数。在这种情况下,您不能简单地展开它,因为展开时它会尝试获取参数,而这里没有这些参数(如果您这样做,则会丢失定义中的宏参数,这可能是您不想要的)。

在这种情况下,您必须使用适当的修补命令(如etoolbox's \patchcmd)。修补过程包括将整个定义转换为字符串(使用\meaning),将 与 分离<parameter text><replacement text>进行替换,然后重新扫描字符串并使用 重新进行定义\scantokens,希望在此过程中不会出错(请参阅对此的解释这里)。

修补的问题在于\scantokens部分,它假设一种单一的 catcode 机制,而根据宏的定义方式,情况并非如此。以 LaTeX 2ε 的\rem@pt宏为例。如果你这样做,\meaning\rem@pt你会得到\rem@pt=macro:#1.#2pt->#1\ifnum #2>\z@ .#2\fi(假设你只想用 替换:这似乎很容易)。修补这个的问题在于,在 中,和是 catcode-12 标记,而中的和必须是 catcode-11,这样你才能真正进行定义。.除非(这并非不可能,但你必须小心)否则将拒绝在这里做任何事情。有些情况下,这完全是不可能的(尝试在 01-10-2019 之前的 LaTeX 中将任何内容修补到 的定义中)。,#1.#2ptptpt\rem@pt\patchcmd\patchcmd\end

如何定义(以及可选参数):假设该宏具有良好的 catcode 机制,并且您可以使用 对其进行修补。\patchcmd当您定义\newcommand\foo[1][]{a#1b}实际的的定义\foo不是在 中\foo,而是在 中\\foo(名称中有两个反斜杠),因此您必须修补后者。这种情况相当简单:加载xpatch并使用\xpatchcmd(或\xpretocmd\xapptocmd)代替。xpatch将为您思考并找出它需要修补\\foo(并将使用)。如果命令是用 定义的,那么也不会有帮助(这些etoolbox命令\patchcmdxparsexpatch进行修补,但他们无意这样做,因此xpatch甚至不尝试支持这一点)。

您要修补的内容:您在问题中提到了不平衡的\if... \fi,但这实际上不是问题。不平衡的条件在其他条件中是有问题的,而在修补时则不是这种情况。这里的问题是不平衡的{... },因为修补宏假设括号是平衡的。根据您想要执行的操作,您可以解决问题(查看这里这只是一个例子,但实际上这是根据具体情况而定的。

l3regex救援:最接近“确定”的修补方法是使用l3regex(和regexpatch)。该regexpatch包使用 LaTeX3 正则表达式引擎 ( l3regex) 来匹配和替换在不同 catcode 设置下设置的标记,以便您可以修补更棘手的内容。使用将在 的定义中\regexpatchcmd\command{<search-regex>}{<replace-regex>}{<true code>}{<false code>}查找 ,并将替换为。该包与 相同,负责处理强大的命令和带有可选参数的命令。看看<search-regex>\command<replace-regex>xpatchl3regexregexpatch正则表达式和修补命令的语法文档。

相关内容