Comment modifier une commande existante ?#

La réponse dépend ici de la complexité de la modification (ou du patch) que vous souhaitez appliquer à cette commande.

1.  Pour les « cas simples »#

Par « cas simples » sont désignés ici les modifications visant à placer du code avant ou après l’intégralité du code de la commande à modifier.

1.1.  Avec les commandes de base#

Supposons que nous voulons définir une version d’une commande qui réalise une action avant que ne s’exécute sa version originale. Nous écrirons alors naturellement :

\renewcommand{\truc}{\machin\truc}

Cependant, cela ne fonctionnerait pas : un appel à \truc exécuterait \machin, puis appellerait à nouveau \truc avec sa nouvelle définition… qui appelerait \machin puis `\truc``et ainsi de suite. Il s’agit d’une boucle récursive infinie qui épuiserait rapidement la mémoire de

Heureusement, la commande primitive \let vient ici à notre secours ; elle nous permet de prendre un « instantané » de la définition actuelle d’une commande, que nous pouvons ensuite utiliser dans la redéfinition de la commande. Ainsi la commande suivante effectue le correctif requis, en toute sécurité.

\let\AncienTruc\truc
\renewcommand{\truc}{\machin\AncienTruc}

L’ajout de commandes à la fin d’une commande fonctionne de la même manière.

Si \truc prend des arguments, il faut les transmettre :

\let\AncienTruc\truc
\renewcommand{\truc}[2]{\machin\AncienTruc{#1}{#2}}}

1.2.  Avec l’extension letltxmacro#

Le problème vu ci-dessus se complique si \truc prend un argument optionnel. La structure de la commande est si complexe que la commande \let ne conserve pas les détails nécessaires. Dans ce cas, nous avons besoin de l’extension letltxmacro qui connaît toutes sortes de commandes et sait comment les reproduire. Supposons que nous ayons une commande définie comme :

\newcommand{\truc}[1][\defaut]{...}

Elle présente un argument optionnel (remplacé par \defaut s’il n’est pas présent) ainsi qu’un argument simple. Dans ce cas, nous la copions en utilisant

\LetLtxMacro{\AncienTruc}{\truc}

Puis nous répétons la technique décrite ci-dessus :

\renewcommand{\truc}[1][\nouveau]%
             {\machin\AncienTruc[{#1}]{#2}}

Nous voyons ici que, pour des raisons fastidieuses de correspondance d’arguments, il est nécessaire de fournir des accolades autour de l’argument optionnel transmis.

1.3.  Avec l’extension patchcmd#

L’extension patchcmd peut traiter le cas simple mais limite l’ensemble des commandes que vous pouvez modifier ; vous ne pouvez modifier aucune commande qui a un argument optionnel, bien qu’il traite le cas des commandes définies avec \DeclareRobustCommand. L’extension définit une commande \patchcommand qui prend trois arguments : la commande à modifier, du code à placer au début de sa définition, et du code à placer à la fin de sa définition. En voici un exemple :

\def\b{b}
\patchcmd\b{a}{c}

Cet exemple va nous créer une nouvelle version de \b définie commee abc.

2.  Pour les « cas complexes »#

Par « cas complexes » sont désignés ici les modifications visant à modifier le code même de la commande.

2.1.  Avec les commandes de base#

On peut ici utiliser la commande \CheckCommand. Celle-ci compare une commande existante avec la définition que vous lui donnez, et émet un avertissement si les deux ne correspondent pas. Elle s’utilise pour notre besoin de la manière suivante :

\CheckCommand{\truc}{⟨défintion originale⟩}

\renewcommand{\truc}{⟨nouvelle définition⟩}

Cette technique est évidemment plus laborieuse car elle vous fait citer tout le code original de la commande pour en vérifier qu’il est tel que vous l’attendez (puis donner l’intégralité de votre version alternative du code de la commande). Cependant, si la commande originale provient d’une source susceptible d’être modifiée par une autre personne, elle vous avertit au moins que votre correctif est susceptible de mal tourner.

2.2.  Avec l’extension ted#

L’extenion ted est un « éditeur de liste de tokens » fournissant une commande \substitute qui corrige le contenu d’une commande, en plaçant son résultat dans une liste de tokens, ou (avec la forme \Substitute*) en utilisant son résultat pour (re)définir une commande. L’exemple suivant définit une commande simple, puis modifie sa définition :

\newcommand{\mafonte}%
    {\Large\sffamily\selectfont}
\Substitute*[\renewcommand{\mafonte}]{\mafonte}%
    {\Large\sffamily}{\huge\itshape}

La définition de la commande est maintenant :

\huge\itshape\selectfont

L’extension propose également une commande ShowTokens, qui affiche le contenu de son argument, un token par ligne, avec des détails sur le catcode du token, etc. Cette commande est recommandée comme outil de débogage.

2.3.  Avec l’extension etoolbox#

L’extension etoolbox (qui fournit à l’utilisateur un accès aux facilités de programmation de ) fournit une commande \patchcmd très similaire à \Substitute, sauf qu’elle ne remplace qu’une seule instance du ou des tokens dans son modèle de recherche. Comme toutes les commandes ne peuvent pas être corrigées de cette manière, \patchcmd prend des arguments supplémentaires pour les cas de succès et d”échec. L’extension fournit également des commandes qui ajoutent du code avant (\pretocmd) ou ajoutent après (apptocmd) une définition d’une commande. Toutes les commandes ne peuvent pas être modifiées de cette manière ; l’extension fournit une commande \ifpatchable qui vérifie les pré-requis et qui vérifie que le corps de la commande cible inclut bien le code supplémentaire que vous proposez d’utiliser (la commande \ifpatchable* omet le test sur la chaîne de correctifs).

2.4.  Avec l’extension regexpatch#

L’extension regexpatch traite des cas inaccessibles avec etoolbox. Elle utilise l’extension gérant les expressions régulières l3regex de pour trouver le code que vous souhaitez corriger. Cette extension connaît également la notion de commandes robustes et biblatex.

2.5.  Avec l’extension patch#

Enfin, citons également une extension (à peu près) utilisable mais pas vraiment recommandable : patch. Celle-ci vous offre un mécanisme ingénieux (et difficile à comprendre) et se présente sous la forme d’un fichier de commandes documenté à l’ancienne, qui ne peut plus être traité pour produire de la documentation formatée Heureusement, ce fichier (patch.doc) contient le code et sa documentation. En gros, on donne à la commande un ensemble d’instructions analogues aux substitutions sed, et elle régénère la commande ainsi modifiée. À moins que vous ne puissiez faire votre travail autrement, patch est à éviter.