18

Consider the following example of a patch using etoolbox and a dummy macro \abc:

enter image description here

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\newcommand{\abc}[2]{#1\ #2}% Magic macro
\begin{document}
\abc{A}{B}

% \patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
\patchcmd{\abc}{#1}{#2}{}{}%
\abc{A}{B}
\end{document}

If I want to maintain good programming practice, I'm encouraged to put \patchcmd in the document preamble (separating structure from content) and only trigger it with a different macro, say \patchabc:

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\newcommand{\abc}[2]{#1\ #2}% Magic macro
\newcommand{\patchabc}{%
  % \patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
  \patchcmd{\abc}{#1}{#2}{}{}%
}
\begin{document}
\abc{A}{B}

\patchabc% Patch \abc
\abc{A}{B}
\end{document}

However, the above does not work since #1 and #2 inside \patchabc is assumed to reference its arguments while \patchabc has none. How can I write a macro that acts like a switch (and is cleaner in terms of the programming) that patches another macro's use of its own arguments?

16

If you add \tracingpatches to the preamble you find the answer in the log:

[debug] tracing \patchcmd on input line 14
[debug] analyzing '\abc'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] -- nested patching command and parameters in patch
[debug] -> the patching command seems to be nested in the
[debug]    argument to some other command
[debug] -> the patch text seems to contain # characters
[debug] -> either avoid nesting or use # characters with
[debug]    category code 12 in the patch text
[debug] -> simply doubling the # characters will not work

And indeed, changing the catcode of # to 12 is working:

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\tracingpatches
\newcommand{\abc}[2]{#1\ #2}% Magic macro
\catcode`\#=12
\newcommand{\patchabc}{%
  % \patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
  \patchcmd{\abc}{#1}{#2}{}{}%
}
\catcode`\#=6
\begin{document}
\abc{A}{B}

\patchabc% Patch \abc
\abc{A}{B}
\end{document}

enter image description here

10

You can use regexpatch:

\documentclass{article}
\usepackage{regexpatch}
\newcommand{\abc}[2]{#1\ #2}% Magic macro
\newcommand{\patchabc}{%
  \regexpatchcmd{\abc}{\cP.1}{\cP\#2}{}{}%
}
\begin{document}
\abc{A}{B}

\patchabc
\abc{A}{B}
\end{document}

The search regular expression \cP.1 means "find any character of type parameter (that is, category code 6) followed by 1", the replace expression \cP\#2 means the same, but the character to substitute will be #, again with category code 6.

If you want to get rid of #1 changing it into #2 wherever it appears in the replacement text of \abc, use

\regexpatchcmd*{\abc}{\cP.1}{\cP\#2}{}{}

However, also an easier \xpatchcmd works:

\documentclass{article}
\usepackage{regexpatch}
\newcommand{\abc}[2]{#1\ #2}% Magic macro
\newcommand{\patchabc}{%
  \xpatchcmd{\abc}{##1}{##2}{}{}%
}
\begin{document}
\abc{A}{B}

\patchabc
\abc{A}{B}
\end{document}

Also here you can use \xpatchcmd* to change all appearances at once.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.