Toutes les informations dont vous avez besoin sont incluses C-h f add-function
et 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' :around
option
Le cas le plus général est l' :around
option, donc je donne un exemple pour cela. (Il est probablement préférable d'utiliser des WHERE
paramètres dédiés lorsque cela est possible, mais vous pouvez les remplacer les uns les autres par une :around
fonction équivalente
).
À titre d'exemple, disons que vous souhaitez déboguer une certaine utilisation de find-file
et souhaitez afficher print
sa 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-args
devient inutile, car les arguments sont passés à la fonction de conseil en tant qu'arguments de la fonction normale (pour les
WHERE
arguments pour lesquels cela a du sens). ad-do-it
devient inutile car les :around
conseils 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 WHERE
valeurs
La docstring de add-function
contient 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 WHERE
symbole qui vous convient et essayez de le comprendre.
Ou utilisez simplement :around
. Pour autant que je sache, le seul avantage d'utiliser des WHERE
s spécialisés :around
pour 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-file
tant 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 lambda
formulaire 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-add
ou risquer de garder l'ancienne version active (car l'exécution
advice-add
avec une modification lambda
sera reconnue comme un nouvel avis, pas comme une mise à jour de l'ancienne).
Remarque latérale La #'function
notation 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.