Toutes les informations dont vous avez besoin sont incluses C-h f add-functionet décrivent le mécanisme sous-jacent de advice-add.
Le nouveau système de conseil agit essentiellement comme le remplacement de la définition actuelle d'une fonction par la fonction décrite dans le tableau dans
C-h f add-function, selon votre choix d' WHERE
argument, uniquement plus propre pour le suivi du comportement défini dans quel fichier source.
Un exemple avec l' :aroundoption
Le cas le plus général est l' :aroundoption, donc je donne un exemple pour cela. (Il est probablement préférable d'utiliser des WHEREparamètres dédiés lorsque cela est possible, mais vous pouvez les remplacer les uns les autres par une :aroundfonction équivalente
).
À titre d'exemple, disons que vous souhaitez déboguer une certaine utilisation de find-file
et souhaitez afficher printsa liste d'arguments à chaque appel. Tu pourrais écrire
(defun my-find-file-advice-print-arguments (old-function &rest arguments)
"Print the argument list every time the advised function is called."
(print arguments)
(apply old-function arguments))
(advice-add #'find-file :around #'my-find-file-advice-print-arguments)
Avec cette nouvelle implémentation, tout ce dont les conseils ont besoin est passé en argument. ad-get-argsdevient inutile, car les arguments sont passés à la fonction de conseil en tant qu'arguments de la fonction normale (pour les
WHEREarguments pour lesquels cela a du sens). ad-do-itdevient inutile car les :aroundconseils reçoivent comme arguments la fonction et les arguments, donc (ad-do-it)est remplacé par le formulaire
(apply old-function arguments)
ou quand vous avez nommé les arguments
(funcall old-function first-arg second-arg)
ce qui est plus propre car il n'y a pas de formes magiques impliquées. La modification des arguments se produit simplement en passant des valeurs modifiées à OLD-FUNCTION.
Autres WHEREvaleurs
La docstring de add-functioncontient un tableau de tous les lieux de conseil (ou "combinateurs"), et à quoi ils sont équivalents, et explique la fonctionnalité en termes d' lambdaéquivalent de comportement à la fonction conseillée:
`:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
`:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
`:around' (lambda (&rest r) (apply FUNCTION OLDFUN r))
`:override' (lambda (&rest r) (apply FUNCTION r))
`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
`:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r)))
`:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
`:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r)))
`:filter-args' (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))
(cited from `C-h f add-function')
où FUNCTION est la fonction de conseil et OLDFUN la fonction où le conseil est ajouté. N'essayez pas de les comprendre tous en même temps, sélectionnez simplement un WHEREsymbole qui vous convient et essayez de le comprendre.
Ou utilisez simplement :around. Pour autant que je sache, le seul avantage d'utiliser des WHEREs spécialisés :aroundpour tout est que vous obtenez un peu plus d'informations en recherchant C-h f ADVISED-FUNCTION
avant de lire la docstring des conseils. Sauf si vous prévoyez de publier le code contenant les conseils, cela n'a probablement pas d'importance.
Fonctions de conseil nommées
Je recommande d'utiliser des fonctions nommées comme conseil car il offre de nombreux avantages (certains d'entre eux s'appliquent également à l'utilisation de fonctions nommées pour les hooks):
Il apparaît en C-h f find-filetant que
:around advice: `my-find-file-advice-print-arguments'
lien vers la définition de la fonction de conseil, qui contient comme d'habitude un lien vers le fichier où elle a été définie. Si l'avis avait été défini comme un lambdaformulaire directement dans le advice-add
formulaire, la docstring serait affichée en ligne (un gâchis pour les longues docstring?) Et rien n'indiquerait où il a été défini.
Vous pouvez supprimer le conseil avec
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Vous pouvez mettre à jour la définition de l'avis sans relancer
advice-addou risquer de garder l'ancienne version active (car l'exécution
advice-addavec une modification lambdasera reconnue comme un nouvel avis, pas comme une mise à jour de l'ancienne).
Remarque latérale La #'functionnotation est fondamentalement équivalente à
'function, sauf qu'elle aide le compilateur d'octets à identifier les symboles en tant que noms de fonction et donc à identifier les fonctions manquantes (par exemple en raison de fautes de frappe).
M-x report-emacs-bug. Certains développeurs préfèrent parfois développer plutôt que documenter. ;-) Il est important que Emacs se documente lui-même.