72

I understand that the patchcmd package provides a command \patchcommand that can be used to add material at the beginning and/or end of the replacement text of an existing macro. It works for macros with any number of normal arguments but has limitations for macros with optional arguments.

xpatch was introduced to take care of the above limitations as well as provide some additional functionality.

Now, when I try to comprehend the usage of the above packages by reading the user documentations (patchcmd, xpatch), I get the feeling that they move to implementation details a little too quickly compared to other package documentations. There are not enough explanations or examples.

I also tried to grasp the concepts by reading the relevant portion of TeX FAQ and more or less understood whatever is presented there. However, that is not enough.

So, do you think we can ask for a complete tutorial on the usage of patchcmd and xpatch? Explaining the usage of the relevant commands like \patchcmd, \pretocmd and \apptocmd as well as, \xpatchcmd, \xpretocmd and \xapptocmd with sufficient examples should suffice.

2
  • As clearly stated in the manual title is xpatch an enhancement of the according patch macros from etoolbox, not from patchcommand. See therefore in subsection 3.4 “Patching” (belonging to section 3 “Author Commands”) of etoolbox. But: Of course you can ask, we are on a question & answer site here.
    – Speravir
    Jan 7, 2014 at 3:29
  • @Speravir Yes, that section is a definite help, which I missed somehow. But as you can see some examples would make it easier to comprehend. So, a tutorial is in order.
    – Masroor
    Jan 7, 2014 at 4:08

2 Answers 2

131

First of all, let's note that \patchcommand is a command defined in the package patchcmd that's completely different in nature from the commands provided by etoolbox and generalized by xpatch.

I would consider patchcmd and \patchcommand as obsolete: with etoolbox the complete functionality of \patchcommand can be obtained with \pretocmd and \apptocmd and much more is possible with \patchcmd.

etoolbox

I'll describe \pretocmd, \apptocmd and \patchcmd, after a bit of history. When biblatex was being developed, Philipp Lehmann found himself needing to redefine several commands from the LaTeX kernel, classes or packages in order to make them compatible with the new citation commands. Just to give a flavor, here is some code from biblatex1.sty:

\patchcmd\@footnotetext
   {\@makefntext}
   {\toggletrue{blx@footnote}\@makefntext}
   {\togglefalse{blx@tempa}}
   {}

The command \@footnotetext is called when typesetting a footnote: it does some bookkeeping and then it calls \@mkfntext and biblatex wants to set a toggle to true when doing this job. However, the definition of \@footnotetext is different when footmisc is loaded, so a redefinition would require checking for the loading of this package, leading to code duplication. Since also footmisc uses \@makefntext, with \patchcmd it's possible to use only one code. However, if the patch is unsuccessful (which it can be if scrbook is the document class), another toggle is set so biblatex can take the appropriate action. (Read the package file for more information, this is only an approximate description.)

The main commands are \pretocmd, \apptocmd and \patchcmd; there are also \preto, \gpreto, \appto and \gappto, but they work only for parameterless macros, so they're not really relevant here.

The syntax is simple:

\pretocmd{<command>}{<code>}{<success>}{<failure>}
\apptocmd{<command>}{<code>}{<success>}{<failure>}
\patchcmd{<command>}{<code to replace>}{<code>}{<success>}{<failure>}

For \pretocmd and \apptocmd the <code> is prepended or appended to the macro replacement text. So

\newcommand{\foo}[2]{-#1-#2-}
\apptocmd{\foo}{(#2)}{}{}

would be equivalent to

\newcommand{\foo}[2]{-#1-#2-(#2)}

Nobody would use two commands instead of one, but typically \foo would have been defined by some package and we want to add functionality to it. It's not mandatory to use one of the arguments in <code>, as the example of \@footnotetext shows: this <code> can be anything, so long as it doesn't use parameters not available for the macro: if a macro is defined to have two arguments, it's impossible to make it having three of them with etoolbox's facilities.

For \patchcmd we have an argument more, containing <code to replace>, that represents code to search for in the replacement text of the macro: in the above example, the code to search for is \@makefntext (more precisely the first appearance of it in the macro's replacement text). Such a bit of code will be completely replaced by <code>. So

\newcommand{\foo}[2]{-#1-#2-(#2)}
\patchcmd{\foo}{-#2-}{X}{}{}

would be equivalent to

\newcommand{\foo}[2]{-#1X(#2)}

The <success> and <failure> arguments are mandatory, but they're not that useful unless one is writing packages. Much more useful, during testing, is issuing, before the first patch,

\tracingpatches

that will give informative messages in the log file and on the terminal such as

[debug] tracing \patchcmd on input line 203
[debug] analyzing '\foo'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] ++ macro can be retokenized cleanly
[debug] ++ search pattern found in replacement text
[debug] ++ patching possible
[debug] == retokenizing macro now

or

[debug] tracing \patchcmd on input line 203
[debug] analyzing '\foo'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] ++ macro can be retokenized cleanly
[debug] -- search pattern not found in replacement text

or even

[debug] tracing \patchcmd on input line 203
[debug] analyzing '\foo'
[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

A simple and useful example. The book class adds some vertical space in the lists of tables and figures in order to separate items belonging to different chapters. This is done by the macro \@chapter, for which we find, in book.cls,

\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne
  [...initial code irrelevant for the problem...]
  \addtocontents{lof}{\protect\addvspace{10\p@}}%
  \addtocontents{lot}{\protect\addvspace{10\p@}}%
  [...final code irrelevant for the problem...]
}

If we want to remove that space we can use \patchcmd:

\makeatletter % the macro name contains @
\patchcmd{\@chapter}
  {\addtocontents{lof}{\protect\addvspace{10\p@}}%
   \addtocontents{lot}{\protect\addvspace{10\p@}}}
  {}% remove those tokens
  {}{}% <success> and <failure> code not needed
\makeatother

If we want to add a page break before each section, another simple patch is possible:

\pretocmd{\section}{\clearpage}{}{}

(in this case also \preto could be used).

xpatch

The package xpatch is an extension to the patching commands provided by etoolbox. It provides the commands \xpretocmd, \xapptocmd and \xpatchcmd that can be used as drop-in replacements for the corresponding commands without x; what's the difference, then?

With the commands provided by etoolbox it's difficult to patch commands with optional arguments or declared robust (that is, defined with \DeclareRobustCommand). So if one wants to patch \cite (just to make a silly example), the trick with \patchcmd would be

\expandafter\patchcmd\csname cite \endcsname
  {<code to replace>}
  {<code>}
  {<success>}{<failure>}

Patching a command defined by \newcommand{\foo}[2][baz]{...} (with a first optional argument) would require

 \expandafter\patchcmd\csname\string\foo\endcsname
  {<code to replace>}
  {<code>}
  {<success>}{<failure>}

and similarly for \pretocmd and \apptocmd. With xpatch it's way simpler and no knowledge of the command's internal implementation is needed:

\xpatchcmd{\cite}
  {<code to replace>}
  {<code>}
  {<success>}{<failure>}

 \xpatchcmd{\foo}
  {<code to replace>}
  {<code>}
  {<success>}{<failure>}

will work, as the command \xpatchcmd (or \xpretocmd and \xapptocmd) will take care of what macro to patch.

Moreover xpatch defines a bunch of similar commands for managing biblatex internal functions that are “macro like”, but are used in a different way, for instance with \usebibmacro{name}. For these one can use

\xpretobibmacro \xapptobibmacro \xpatchbibmacro
\xpretobibdriver \xapptobibdriver \xpatchbibdriver
\xpretofieldformat \xapptofieldformat \xpatchfieldformat
\x.....nameformat
\x.....listformat
\x.....indexfieldformat
\x.....indexnameformat
\x.....indexlistformat

There are also

\xshowcmd \xshowbibmacro \xshownameformat \xshowlistformat
\xshowindexfieldformat \xshowindexnameformat \xshowindexlistformat

for seeing on the terminal (and in the log file) the internal implementation, which should always be done when starting a patch, in order to see what the commands do.

Note that xpatch uses \pretocmd, \apptocmd and \patchcmd internally.

regexpatch

The experimental package regexpatch reimplements the \x... commands of xpatch independently of etoolbox and adds also a

\regex...

variant for each one of the commands listed above, together with some more utilities.

Showing commands

The same problems outlined above hold for \show; if you want to know the definition of \cite (to use a command already mentioned), you should do

\expandafter\show\csname cite \endcsname

but with xpatch you have \xshowcmd and \xshowcmd\cite would choose the right command to look at and produce

> \cite =\long macro:
->\@ifnextchar [{\@tempswatrue \@citex }{\@tempswafalse \@citex []}.

whereas \show\cite would only output

> \cite=macro:
->\protect \cite  .

With regexpatch there is also a *-form and \xshowcmd*\cite prints more diagnostics:

*************************************************
* xpatch message
* `\cite' is a control word defined with \DeclareRobustCommand
*************************************************
> \cite =\long macro:
->\@ifnextchar [{\@tempswatrue \@citex }{\@tempswafalse \@citex []}.
3
  • 5
    The answer is a feast for me and will need some time to go through. Wonder why the TeX FAQ mentions patchcmd, ted or etoolbox packages in the same breath without mentioning their relative merits (or demerits).
    – Masroor
    Jan 7, 2014 at 12:51
  • 6
    @MMA the faq is the output of a project started in the 1990s; it's huge and when new packages appear i often don't have time to do more than note the existence of the package. i do have an annotation "+ xpatch, regexpatch for q-patch?" ... one day, perhaps, i'll get around to it, but it's a pretty thankless task, and i'm not exactly a healthy old man. Jan 7, 2014 at 17:06
  • 1
    # is another special character that is difficult to get around when patching macros. Could you provide some more examples of how one would go about that? For example, consider the patch in How to patch a command from leipzig.sty. The macro in question contains #1 and ##1. How would these differ in the search and/or replace clause when using regexpatch?
    – Werner
    Mar 2, 2015 at 6:22
3

Thanks to @egreg's answer, I finally got to an example which demonstrates how to patch and \show a \newcommand, which otherwise has some protection (see Are commands defined by \newcommand[.][.]{.} robust?).

The problem is, when you \show a \newcommand, you just get something like "\@protected@testopt \mycmd \\mycmd {}.", not the "real" internals of the command; if you try to patch this command without precautions, and do again a plain \show, you'll see that your, say, append is actually after the \@protected@testopt - not at the end of the "inner" command definition, so to speak. The answer for both patching and showing of the \newcommand is the use of \expandafters, specifically the one with \space, as @egreg answer shows it. Note that when patching without the \expandafter, \tracingpatches will not give an error - but only with the precaution, will it note "macro can be retokenized cleanly".

Here is an MWE that demonstrates this (the relevant terminal output is pasted inside as %% comments):

\documentclass{book}
\usepackage{etoolbox}

\newcommand\mycmd[2][]{%
  \typeout{inside mycmd...}
}
\show\mycmd
%% > \mycmd=macro:
%% ->\@protected@testopt \mycmd \\mycmd {}.

\tracingpatches
% \apptocmd\mycmd{\typeout{appended line.}}{\typeout{success}}{\typeout{failure}}
%% [debug] tracing \apptocmd on input line 13
%% [debug] analyzing '\mycmd'
%% [debug] ++ control sequence is defined
%% [debug] ++ control sequence is a macro
%% [debug] ++ control sequence is a macro without parameters
%% [debug] == redefining macro now
%% success
% \show\mycmd
%% > \mycmd=macro:
%% ->\@protected@testopt \mycmd \\mycmd {}\typeout {appended line.}.
%% l.24 \show\mycmd

% % https://tex.stackexchange.com/questions/152773/please-tutor-the-usage-of-patchcmd-and-xpatch
% \expandafter\apptocmd\csname mycmd\endcsname{\typeout{appended line.}}{\typeout{success}}{\typeout{failure}}
%% [debug] tracing \apptocmd on input line 13
%% [debug] analyzing '\mycmd'
%% [debug] ++ control sequence is defined
%% [debug] ++ control sequence is a macro
%% [debug] ++ control sequence is a macro without parameters
%% [debug] == redefining macro now
%% success
% \show\mycmd
%% > \mycmd=macro:
%% ->\@protected@testopt \mycmd \\mycmd {}\typeout {appended line.}.
%% l.24 \show\mycmd

\expandafter\apptocmd\csname\string\mycmd\endcsname{\typeout{appended line.}}{\typeout{success}}{\typeout{failure}}
%% [debug] tracing \apptocmd on input line 28
%% [debug] analyzing '\\mycmd'
%% [debug] ++ control sequence is defined
%% [debug] ++ control sequence is a macro
%% [debug] ++ control sequence is a macro with parameters
%% [debug] ++ macro can be retokenized cleanly
%% [debug] == retokenizing macro now
%% success
% \show\mycmd
%% > \mycmd=macro:
%% ->\@protected@testopt \mycmd \\mycmd {}.
%% l.30 \show\mycmd

% this is how to \show a \newcommand macro:
\expandafter\show\csname\string\mycmd\endcsname
%% > \\mycmd=\long macro:
%% [#1]#2->\typeout {inside mycmd...} \typeout {appended line.}.
%% <recently read> \\mycmd

\begin{document}
\end{document}
2
  • 3
    Is this supposed to be an answer? The simplest way to \show a command when xpatch is loaded is to use \xshowcmd.
    – egreg
    Nov 22, 2014 at 15:00
  • Thanks @egreg - I guess this would be an extension of the accepted answer with a simple example, but I didn't feel confident to edit yours to paste it in there, so I wrote it as a separate answer, hope that's ok; cheers!
    – sdaau
    Nov 22, 2014 at 17:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .