[Tex/LaTex] How to patch with \xpretocmd and \xapptocmd a command by applying to it a macro with argument

argumentsetoolboxmacrospatchingxpatch

Suppose I'd like to patch a very complicated macro, say \autocite. For this, xpatch package is my friend. If the patch consists in applying a modal command which doesn't take arguments, such as \bfseries, \xpretocmd is also my friend:

\documentclass{article}
\usepackage{xpatch}
\usepackage[backend=biber]{biblatex}%
%
\addbibresource{biblatex-examples.bib}
%
% \autocite's patch
\xpretocmd{\autocite}%
{\bfseries}%
{\message{^^Jxpretocmd OK^^J^^J}}%
{\message{^^Jxpretocmd not OK^^J^^J}}
%
\begin{document}
\autocite{cicero}
\printbibliography
\end{document}

Now, suppose the patch consists in applying a macro which does take an argument, such as \textbf: I want \autocite... to become \textf{\autocite...}, whatever are the star/optional/mandatory arguments in .... For this, I can't use \textf{ and } as ⟨prepend⟩ and ⟨append⟩ in:

\xpretocmd{⟨command⟩}{⟨prepend⟩}{⟨success⟩}{⟨failure⟩}
\xapptocmd{⟨command⟩}{⟨append⟩}{⟨success⟩}{⟨failure⟩}

because of unbalanced braces. If { and } are replaced by \bgroup and \egroup:

\documentclass{article}
\usepackage{xpatch}
\usepackage[backend=biber]{biblatex}%
%
\addbibresource{biblatex-examples.bib}
%
% \autocite's patch
\xpretocmd{\autocite}%
{\textbf\bgroup}%
{\message{^^Jxpretocmd OK^^J^^J}}%
{\message{^^Jxpretocmd not OK^^J^^J}}
\xapptocmd{\autocite}
{\egroup}%
{\message{^^Jxapptocmd OK^^J^^J}}%
{\message{^^Jxapptocmd not OK^^J^^J}}
%
\begin{document}
\autocite{cicero}
\printbibliography
\end{document}

it doesn't work neither as \egroup is considered as the \autocite's argument.

Hence my question: how to patch with \xpretocmd and \xapptocmd a command by applying to it a macro with argument?

Edit. I placed a great deal of hope in the following trick, relying on \BODY command from environ package, but it fails as well…

\documentclass{article}
\usepackage{xpatch}
\usepackage{environ}
\usepackage[backend=biber]{biblatex}%
%
\addbibresource{biblatex-examples.bib}
%
\NewEnviron{boldify}{%
  \textbf{\BODY}%
}
% \autocite's patch
\xpretocmd{\autocite}%
{\boldify}%
{\message{^^Jxpretocmd OK^^J^^J}}%
{\message{^^Jxpretocmd not OK^^J^^J}}
\xapptocmd{\autocite}
{\endboldify}%
{\message{^^Jxapptocmd OK^^J^^J}}%
{\message{^^Jxapptocmd not OK^^J^^J}}
%
\begin{document}
\autocite{cicero}
\printbibliography
\end{document}

Best Answer

Let's look at the definition of \autocite:

> \autocite=\protected macro:
->\blx@citecmdinit \@ifstar {\blx@citepunct {\blx@acitei@inline *}} {\blx@citepunct {\blx@acitei@inline {}}}.

This means that the macro looks for * and then passes control to another macro. It's simply not possible to make what you want by just patching \autocite.

Sorry.

You may instead redefine \autocite using xparse so that you pass the full set of arguments and *-variants, adding \textbf around the whole thing.

The user level syntax of \autocite is

\autocite*[<prenote>][<postnote>]{<key>}

so a reimplementation with xparse could be

\usepackage{xparse}

\let\BLautocite\autocite
\RenewDocumentCommand{\autocite}{soom}{%
 \textbf{%
  \IfNoValueTF{#2}% no notes
   {\IfBooleanTF{#1}{\BLautocite*{#4}}{\BLautocite{#4}}
   {% else
    \IFNoValue{#3}% only optional argument is postnote
     {\IfBooleanTF{#1}{\BLautocite*[#2]{#4}}{\BLautocite[#2]{#4}}}
     {\IfBooleanTF{#1}{\BLautocite*[#2][#3]{#4}}{\BLautocite[#2][#3]{#4}}}%
   }%
 }%
}

You should do similarly for \Autocite.

Of course, something like this would be impossible for \autocites, where the number of arguments is variable.

More likely, you should add \begingroup\bfseries and a matching \endgroup where the actual typesetting takes place. This of course requires going deep in analyzing the working of biblatex.

Related Question