Jak mogę usunąć nienazwaną poradę?

12

Dobrze się bawiłem, dodając kilka rad do funkcji:

(advice-add 'executable-find :around
            (lambda (f &rest args)
              (apply g args)))
               ;;;   ^

Eee, literówka. Naprawiono to i ponownie oceniono powyższy kod. Ale teraz mam zarówno „poprawione”, jak i „zepsute” porady dotyczące tej funkcji.

Jak się ich pozbyć? Biorąc pod uwagę, że advice-removepotrzebujesz albo obiektu funkcji, albo porady wokół (która tutaj jest pusta)?

(Oczywiście mogę po prostu wyjść i uruchomić ponownie, ale jest inny sposób, prawda?)

Daniel Jour
źródło

Odpowiedzi:

7

Można również zadzwonić advice-removez tego samego wyrażenia lambda, czyli zastąpić advice-addz advice-removei usunąć :around, a następnie C-x C-e.

Xuchunyang
źródło
To działa! Myślałem, że tak się nie stanie, zakładałem, że (1) za każdym razem, gdy oceniasz formę lambda, dostajesz nową funkcję, a nie eqpoprzednią, (2) usuń poradę porówna funkcję, którą przekażesz, do porad, aż znajdzie jeden, który jest eqdo tego i usuń to, (3) nawet jeśli polecenie remove-remove zastosuje inny test, na przykład equal, nadal nie zadziała, ponieważ różne oceny formy lambda nie będą się equalnawzajem. Okazuje się, że (1) jest poprawne, ale (2) i (3) są błędne: usuń porady equali zastosuj tę samą ocenę lambdadwukrotnie equal!
Omar
Zauważyłem, że nie zaakceptowałem odpowiedzi, kiedy zadałem pytanie. Wybieram Twoją, ponieważ jest to najbardziej pomocna w tej sytuacji IMO.
Daniel Jour
11

Jest advice-mapcjedna, która pozwala na iterację po wszystkich radach niektórych funkcji, z zastosowaniem każdej funkcji do każdej. Dzięki niemu łatwo jest usunąć wszystkie porady:

(advice-mapc
  (lambda (adv prop)
    (advice-remove 'executable-find adv))
  'executable-find)

Można to rozszerzyć, aby usunąć tylko porady, które nie mają namewłaściwości, szukając propsargumentu second ( ) (który jest listą) dla tych, które nie mają czegoś związanego z kluczem name.

Daniel Jour
źródło
Tak. A korzystanie z nameułatwia usuwanie.
Drew
1

Oto kod, który pomoże to zrobić interaktywnie.

Definiuje dwie funkcje. Pierwsza funkcja pobiera listę wszystkich porad dotyczących danego symbolu, druga funkcja interaktywnie prosi o symbol i poradę na temat tego symbolu, a następnie usuwa tę ostatnią z tego pierwszego. Ponieważ wszystko to dzieje się z ukończeniem, jest to dla mnie łatwiejsze niż skopiowanie wklejenia wyrażenia lambda.

(defun yf/advice-list (symbol)
  (let (result)
    (advice-mapc
     (lambda (ad props)
       (push ad result))
     symbol)
    (nreverse result)))

(defun yf/kill-advice (symbol advice)
  "Kill ADVICE from SYMBOL."
  (interactive (let* ((sym (intern (completing-read "Function: " obarray #'yf/advice-list t)))
                      (advice (let ((advices-and-their-name
                                     (mapcar (lambda (ad) (cons (prin1-to-string ad)
                                                                ad))
                                             (yf/advice-list sym))))
                                (cdr (assoc (completing-read "Remove advice: " advices-and-their-name nil t)
                                            advices-and-their-name)))))
                 (list sym advice)))
  (advice-remove symbol advice))
YoungFrog
źródło