如何将 \xpatchcmd 与包含 \@ 的宏一起使用

如何将 \xpatchcmd 与包含 \@ 的宏一起使用

我有以下简化的示例:

\documentclass[a4paper]{report}

\usepackage{xpatch}

\def\foo{Foo}
\def\bar{Bar}

\def\mycommandA{i.e.\ \foo{}}
\def\mycommandB{i.e.\@ \foo{}}

\tracingpatches

\begin{document}

\xpatchcmd{\mycommandA}{\foo}{\bar}{}{}
\xpatchcmd{\mycommandB}{\foo}{\bar}{}{}

\mycommandA

\mycommandB

\end{document}

我希望能够使用\@而不是\,但上面只有修补\mycommandA成功,并且\mycommandB我得到:

[debug] tracing \patchcmd on input line 16
[debug] analyzing '\mycommandB'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] -- macro cannot be retokenized cleanly
[debug] -> the macro may have been defined under a category
[debug]    code regime different from the current one
[debug] -> the replacement text may contain special control
[debug]    sequence tokens formed with \csname...\endcsname;
[debug] -> the replacement text may contain carriage return,
[debug]    newline, or similar characters

有没有办法使用\xpatchcmd它来工作\@

答案1

不幸的是etoolbox(它xpatch是一个用于添加扩展功能的包装器)不允许这样做:因为需要修补的大多数命令都包含@在命令名称中,所以它需要进行大量的处理才能工作。

您可以使用 来完成regexpatch

\documentclass[a4paper]{report}

\usepackage{regexpatch}

\def\foo{Foo}
\def\bar{Bar}

\def\mycommandA{i.e.\ \foo{}}
\def\mycommandB{i.e.\@ \foo{}}

\tracingxpatches

\begin{document}

\xpatchcmd{\mycommandA}{\foo}{\bar}{}{}
\xpatchcmd{\mycommandB}{\foo}{\bar}{}{}

\mycommandA

\mycommandB

\end{document}

新版本regexpatch正在向 CTAN 发送以修复故障。

在此处输入图片描述

相关讯息来自\tracingxpatches

xpatch message
 `\mycommandA' is not especially defined
xpatch message
 Macro`\mycommandA' is patchable
xpatch message
 `\mycommandB' is not especially defined
xpatch message
 Macro`\mycommandB' is patchable

答案2

\mycommandB围绕with的定义\makeatletter...\makeatother就足以完成\xpatchcmd工作。从您的问题来看,不清楚这是否适合您的应用程序,您可能定义或不定义您希望稍后修补的命令。

另外,我用 替换了硬空格\@sptoken,以避免它在修补过程中被吸收。

\documentclass[a4paper]{report}

\usepackage{xpatch}

\def\foo{Foo}
\def\bar{Bar}

\def\mycommandA{i.e.\ \foo{}}
\makeatletter
\def\mycommandB{i.e.\@\@sptoken\foo{}}
\makeatother

\tracingpatches

\begin{document}

\xpatchcmd{\mycommandA}{\foo}{\bar}{}{}
\xpatchcmd{\mycommandB}{\foo}{\bar}{}{}

\mycommandA

\mycommandB

\end{document}

在此处输入图片描述

为了进行比较,如果\@从我的方法中省略掉

\makeatletter
\def\mycommandB{i.e.\@sptoken\foo{}}
\makeatother
\xpatchcmd{\mycommandB}{\foo}{\bar}{}{}

\mycommandB

人们会发现增加的空间是更大的句末间距,而不是单词之间的间距。

另一个演示这些概念的 MWE 如下,其中\mycommandC既不使用\也不使用\@

\documentclass[a4paper]{report}

\usepackage{xpatch}

\def\foo{Foo}
\def\bar{Bar}

\def\mycommandA#1{#1\ \foo{}}
\makeatletter
\def\mycommandB#1{#1\@\@sptoken\foo{}}
\makeatother
\def\mycommandC#1{#1 \foo{}}

\begin{document}

\mycommandA{x.}

\mycommandB{x.}

\mycommandC{x.}

\xpatchcmd{\mycommandA}{\foo}{\bar}{}{}
\xpatchcmd{\mycommandB}{\foo}{\bar}{}{}
\xpatchcmd{\mycommandC}{\foo}{\bar}{}{}

\mycommandA{x.}

\mycommandB{x.}

\mycommandC{x.}
\end{document}

在此处输入图片描述

相关内容