我有以下简化的示例:
\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}