Alle Informationen, die Sie benötigen, sind enthalten und C-h f add-function
beschreiben den zugrunde liegenden Mechanismus von advice-add
.
Das neue Hinweissystem ersetzt im Grunde genommen die aktuelle Definition einer Funktion durch die in der Tabelle beschriebene Funktion.
C-h f add-function
Abhängig von Ihrer Wahl des WHERE
Arguments wird nur die Funktion übersichtlicher, um nachzuverfolgen, welches Verhalten in welcher Quelldatei definiert wurde.
Ein Beispiel mit der :around
Option
Der allgemeinste Fall ist die :around
Option, also gebe ich ein Beispiel dafür. (Es ist wahrscheinlich besser, WHERE
wenn möglich dedizierte Parameter zu verwenden, aber Sie können jede andere durch eine entsprechende :around
Funktion ersetzen
.)
Nehmen wir als Beispiel an, Sie möchten bei jedem Aufruf die Verwendung von debuggen find-file
und die print
Argumentliste ändern. Du könntest schreiben
(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)
Mit dieser neuen Implementierung wird alles, was der Rat benötigt, als Argument übergeben. ad-get-args
wird unnötig, da die Argumente als normale Funktionsargumente (für
WHERE
Argumente, für die es Sinn macht) an die Hinweisfunktion übergeben werden. ad-do-it
wird unnötig, da :around
Beratung als Argumente die Funktion und die Argumente erhält, also (ad-do-it)
durch die Form ersetzt wird
(apply old-function arguments)
oder wenn Sie die Argumente benannt haben
(funcall old-function first-arg second-arg)
Das ist sauberer, da keine magischen Formen beteiligt sind. Das Ändern der Argumente erfolgt einfach durch Übergeben geänderter Werte an OLD-FUNCTION
.
Andere WHERE
Werte
Der docstring von add-function
enthält eine Tabelle aller Beratungsstellen (oder "Kombinatoren") und deren Entsprechung und erläutert die Funktionsweise in Form eines lambda
Verhaltens, das der empfohlenen Funktion entspricht:
`: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')
Dabei ist FUNCTION die Hinweisfunktion und OLDFUN die Funktion, in der der Hinweis hinzugefügt wird. Versuchen Sie nicht, alle auf einmal zu verstehen, wählen Sie einfach ein WHERE
Symbol aus, das passend klingt, und versuchen Sie, dieses zu verstehen.
Oder einfach benutzen :around
. Soweit ich
das beurteilen kann, besteht der einzige Vorteil der Verwendung von spezialisierten WHERE
s :around
für alles darin, dass Sie ein bisschen mehr Informationen erhalten, wenn Sie C-h f ADVISED-FUNCTION
nachschlagen , bevor Sie die Dokumentation des Ratschlags lesen. Sofern Sie nicht vorhaben, den Code mit den Ratschlägen zu veröffentlichen, spielt dies wahrscheinlich keine Rolle.
Benannte Beratungsfunktionen
Ich empfehle die Verwendung benannter Funktionen als Hinweis, da dies viele Vorteile bietet (einige davon gelten auch für die Verwendung benannter Funktionen für Hooks):
Es zeigt sich in C-h f find-file
als
:around advice: `my-find-file-advice-print-arguments'
Verknüpfung mit der Definition der Hinweisfunktion, die wie üblich eine Verknüpfung zu der Datei enthält, in der sie definiert wurde. Wenn der Hinweis als lambda
Formular direkt im advice-add
Formular definiert worden wäre, würde der Docstring inline angezeigt (ein Durcheinander für lange Docstrings?) Und nichts würde darauf hinweisen, wo er definiert worden wäre.
Sie können den Hinweis mit entfernen
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Sie können die Definition des Hinweises aktualisieren, ohne advice-add
die alte Version erneut ausführen zu müssen
oder zu riskieren, sie aktiv zu halten (da das Ausführen advice-add
mit einer geänderten Version
lambda
als neuer Hinweis und nicht als Aktualisierung des alten Hinweises anerkannt wird).
Randbemerkung Die #'function
Notation ist im Wesentlichen gleichbedeutend mit
'function
, mit dem Unterschied, dass sie dem Byte-Compiler hilft, Symbole als Funktionsnamen zu identifizieren und somit fehlende Funktionen (z. B. aufgrund von Tippfehlern) zu identifizieren.
M-x report-emacs-bug
. Einige Entwickler bevorzugen manchmal die Entwicklung gegenüber der Dokumentation. ;-) Es ist wichtig, dass sich Emacs selbst dokumentiert.