\pretocmd, \apptocmd e \patchcmd non funzionano sui comandi con argomento facoltativo, né sui comandi definiti con \DeclareRobustCommand. Il motivo è un po’ riposto, ma non difficile. Supponiamo di avere
`\newcommand{\pippo}[2][noccioline]{…}
\DeclareRobustCommand{\pluto}[1]{…}
\DeclareRobustCommand{\paperino}[2][313]{…}`
in ordine crescente di difficoltà. 🙂 Indico con \Xcmd una qualsiasi delle funzioni di etoolbox.
Nel primo caso il comando che fa il lavoro vero è “\\pippo”, nel senso che il nome del comando è “\pippo” con la barra rovescia in quanto carattere. Dare \Xcmd{\pippo}{…}{}{} non servirebbe a nulla e infatti etoolbox si rifiuta. Occorre agire sul comando “vero”:
`\expandafter\Xcmd\csname\string\pippo\endcsname{…}{}{}`
funzionerà perfettamente, perché \csname\string\pippo\endcsname costruisce l’esatto nome che ci serve.
Secondo caso. Il comando che fa il lavoro vero è “\pluto “, nel senso che il nome del comando ha uno spazio in fondo che fa parte integrante del nome. Soluzione:
`\expandafter\Xcmd\csname pluto \endcsname{…}{}{}`
perché \csname pluto \endcsname produce il nome corretto.
Terzo caso, cioè la somma dei precedenti: il comando su cui agire è “\\paperino “; qui la situazione è un pochino più complessa, perché
`\csname\string\paperino \endcsname`
non produce il nome corretto: lo spazio dopo “\paperino” è ignorato! Dunque
`\expandafter\Xcmd\csname\string\paperino\space\endcsname{…}{}{}`
Nel tuo caso devi usare
`\expandafter\pretocmd\csname\string\ambiente\endcsname{\textbf{#1, #2}}{}{}`
Codice un po’ più generale
Qui c’è una definizione di \xpatchcmd, \xpretocmd e \xapptocmd che fanno la stessa cosa degli originali, ma si possono applicare a comandi definiti con argomento facoltativo oppure costruiti con \DeclareRobustCommand e anche con \newrobustcmd.
`\documentclass[a4paper]{article}
\usepackage{etoolbox}
\makeatletter
\def\@X@cmd#1#2{%
%% Start from scratch: define \@tempc to expand to the candidate command
\def\@tempc{#2}%
%% Analyze whether #2 is defined via \DeclareRobustCommand; if it is, and
%% the command is called \abc, its \meaning is the string “\protect \abc ”
%% (where spaces are significant)
\edef\@tempa{\expandafter\strip@prefix\meaning#2}%
\edef\@tempb{\string\protect\space\string#2\space\space}%
%% If the two strings are equal, the command was defined by \DeclareRobustCommand
%% and was a control sequence
\ifx\@tempa\@tempb
\message{\string#2 is a LaTeX robust control sequence}%
\expandafter\@robusttempc#2%
\fi
%% In case of \DeclareRobustCommand{\?}{…}, the first level expansion is
%% different: “\x@protect \?\protect \? ”
\edef\@tempb{\string\x@protect\space\string#2\string\protect\space\string#2\space\space}
\ifx\@tempa\@tempb
\message{\string#2 is a LaTeX robust control symbol}%
\expandafter\@xrobusttempc#2%
\fi
%% In any case, \@tempc expands to the candidate for patching; we need one more
%% passage if the command has optional arguments; if it has, its first
%% level expansion is “\@protected@testopt \abc \\abc {}” (where \abc stands for
%% the command chosen before, which might have final spaces). Since it is the
%% expansion of \@tempc we get its first level expansion in two steps.
\edef\@tempa{\expandafter\meaning\@tempc}%
\edef\@tempa{\expandafter\strip@prefix\@tempa}%
\edef\@tempb{\string\@protected@testopt\space\string#2\space\space
\@backslashchar\string#2\space\space\string{\string}}
%% If the two strings in \@tempa and \@tempb are equal, the command has an
%% optional argument and was defined with \newcommand.
\ifx\@tempa\@tempb
\message{\string#2 has an optional argument}%
\expandafter\expandafter\expandafter\@optionaltempc\@tempc
\fi
%% Commands with an optional argument defined with \newrobustcmd have a different
%% first level expansion: “\@testopt \\abc {}”
\edef\@tempb{\string\@testopt\space\@backslashchar\string#2\space\string{\string}}
\ifx\@tempa\@tempb
\message{\string#2 has an optional argument}%
\expandafter\expandafter\expandafter\@eoptionaltempc\@tempc
\fi
%% Finally we do the patch (#1 will be either \patchcmd, \pretocmd or \apptocmd
\expandafter#1\@tempc
}
%% In case of a control sequence defined with \DeclareRobustCommand,
%% the patchable form is the second token in the first level expansion
\def\@robusttempc#1#2{\def\@tempc{#2}}
%% In case of a control symbol defined with \DeclareRobustCommand,
%% the patchable form is the fourth token in the first level expansion
\def\@xrobusttempc#1#2#3#4{\def\@tempc{#4}}
%% In case of a control sequence with an optional argument (traditional
%% LaTeX) the patchable form is the third token in the first level expansion
\def\@optionaltempc#1#2#3#4{\def\@tempc{#3}}
%% In case of a control sequence with an optional argument (\newrobustcmd)
%% the patchable form is the second token in the first level expansion
\def\@eoptionaltempc#1#2#3{\def\@tempc{#2}}
\def\xpatchcmd{\@X@cmd\patchcmd}
\def\xpretocmd{\@X@cmd\pretocmd}
\def\xapptocmd{\@X@cmd\apptocmd}
%% Now we define some test commands
\DeclareRobustCommand{\abc}{abc}
\DeclareRobustCommand{\abcd}[1][]{abcd}
\newrobustcmd{\abcde}[2][]{abcde}
\DeclareRobustCommand\?[1][]{abc?}
\DeclareRobustCommand{\xyz}{abc}
\expandafter\def\expandafter\cheat\expandafter{\xyz}
\tracingpatches
\xpatchcmd\abc{ab}{AB}{}{}
\xpatchcmd\abcd{ab}{AB}{}{}
\xpatchcmd\abcde{ab}{AB}{}{}
\xpatchcmd\?{ab}{AB}{}{}
\xpatchcmd\cheat{ab}{AB}{}{}
\begin{document}
We should get “AB'' instead of “ab'' except for \verb|\cheat|
\verb|\abc|: \abc
\verb|\abcd[x]{y}|: \abcd[x]{y}
\verb|\abcde|: \abcde{xxx}
\verb|\?|: \?
\xapptocmd\?{PIPPO}{}{}
\verb|\?|: \?
\verb|\cheat|: \cheat
\end{document}`
Non l’ho scritto adesso, sia chiaro. 🙂
Ciao
Enrico