# biblatex: Is it possible to patch macros created with \newbibmacro?

This question led to a new feature in a package:
xpatch

The etoolbox package provides various tools that "are useful to hook into or modify existing code" (etoolbox manual, section 3.4). The most important one is the \patchcmd command with the syntax

\patchcmd[<prefix>]{<command>}{<search>}{<replace>}{<success>}{<failure>}


which "extracts the replacement text of a <command>, replaces [the first occurence of] <search> with <replace>, and reassembles the <command>". Other useful macros are, e.g., \apptocmd and \pretocmd which will append resp. prepend code to the replacement text of a command.


Is it possible to define a \patchbibmacro command that extracts and modifies the replacement text of macros created with \newbibmacro the same way \patchcmd does for macros created with \newcommand?

-

\makeatletter
\def\act@on@bibmacro#1#2{%
\expandafter#1\csname abx@macro@\detokenize{#2}\endcsname}
\def\patchbibmacro{\act@on@bibmacro\patchcmd}
\def\pretobibmacro{\act@on@bibmacro\pretocmd}
\def\apptobibmacro{\act@on@bibmacro\apptocmd}
\def\showbibmacro{\act@on@bibmacro\show}
\makeatother


Now you have available

\patchbibmacro \pretobibmacro \apptobibmacro \showbibmacro


Explanation:

\newbibmacro{foo}[1]{-#1-} actually executes

\expandafter\newcommand\csname abx@macro@\detokenize{foo}\endcsname[1]{-#1-}


(I omit some gory details, but this is almost the truth).

This, of course, won't work for macros with optional arguments, but here's how:

\makeatletter
\def\act@on@bibmacroopt#1#2{%
\expandafter#1\csname\expandafter\string\csname abx@macro@\detokenize{#2}\endcsname\endcsname}
\def\patchbibmacroopt{\act@on@bibmacroopt\patchcmd}
\def\pretobibmacroopt{\act@on@bibmacroopt\pretocmd}
\def\apptobibmacroopt{\act@on@bibmacroopt\apptocmd}
\def\showbibmacroopt{\act@on@bibmacroopt\show}
\makeatother


With \patchbibmacroopt you can define biblatex macros defined for instance by

\newbibmacro{baz}[2][x]{-#1-#2-}


One has to remember that with \newcommand{\baz}[2][x]{-#1-#2-} the macro doing the real work is

\\baz


that, of course, has to be accessed with

\csname\string\baz\endcsname


## Easier solution

The question led to adding some features to the xpatch package, which now has

\xpatchbibmacro
\xpretobibmacro
\xapptobibmacro


which work out of the box even with bibmacros defined having an optional argument; the syntax is the same as the one for \patchcmd, \pretocmd and \apptocmd:

\xpatchbibmacro{<name>}{<search>}{<replace>}{<success>}{<failure>}
\xpretobibmacro{<name>}{<code to prepend>}{<success>}{<failure>}
\xapptobibmacro{<name>}{<code to append>}{<success>}{<failure>}


So, if foo has been defined with \newbibmacro{foo}[1]{-#1-} one can say, for instance,

\xpatchbibmacro{foo}{-}{+}{}{}


to change the first - into +.

-
Is there any case where using the opt variants is inadvisable? If not, why not use just these variants (and rename them)? –  lockstep Jan 10 '12 at 22:46
For macros defined without optional arguments (\newbibmacro{foo}[1]{...}), you mustn't use the "opt" variant. It would be possible to catch this automatically, but it's complicated and I don't think it's worth a try. However, you can look for xpatchcmd on the site for an automatic solution that could be ported to this case. –  egreg Jan 10 '12 at 22:51
Indeed - I just noticed that my "one size fits all" idea won't work. –  lockstep Jan 10 '12 at 22:55
Look here: tex.stackexchange.com/a/24377/4427 :) –  egreg Jan 10 '12 at 23:27
@lockstep I've just uploaded the xpatch package that incorporates code for this kind of patching. –  egreg Jan 12 '12 at 21:54