Как я могу удалить неназванный совет?

12

Мне было весело добавить несколько советов к функции:

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

Ой, опечатка. Исправил и снова оценил приведенный выше код. Но теперь у меня есть и «исправленный», и «неправильный» совет по поводу этой функции.

Как мне избавиться от них? Учитывая, что advice-removeнужен либо объект функции, либо совет вокруг (который здесь пуст)?

(Очевидно, я могу просто выйти и перезапустить, но есть другой способ, не так ли?)

Даниэль Жур
источник

Ответы:

7

Вы также можете вызвать advice-removeс тем же лямбда-выражением, то есть заменить advice-addна advice-removeи удалить :around, затем C-x C-e.

xuchunyang
источник
Это работает! Я думал, что это не так, я предполагал, что (1) каждый раз, когда вы оцениваете лямбда-форму, вы получаете новую функцию, а не eqпредыдущую, (2) advice-remove сравнивает функцию, которую вы передаете, с советами, пока не найдет один, который eqк нему и удалите это, (3) даже если advice-remove использует другой тест, типа equal, он все равно не будет работать, потому что разные оценки лямбда-формы не будут equalдруг с другом. Оказывается, (1) правильно, но (2) и (3) неверно: извлекаются рекомендации по удалению equal, и двойная оценка lambdaдает equalрезультаты!
Омар
Заметил, что я не принял ответ, когда задал вопрос. Я выбираю Ваш, потому что это IMO, наиболее полезный в данной ситуации.
Даниэль Жур
11

Есть advice-mapc, что давайте переберем все советы некоторой функции, применяя данную функцию к каждой. С его помощью легко удалить все советы:

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

Это может быть расширено для удаления только тех советов, у которых нет nameсвойства, путем поиска во втором propsаргументе () (который является списком) тех, у которых нет ничего связанного с ключом name.

Даниэль Жур
источник
Да. И использование nameделает удаление легче.
Дрю
1

Вот некоторый код, который поможет сделать это интерактивно.

Это определяет две функции. Первая функция получает список всех советов по данному символу, вторая функция в интерактивном режиме запрашивает символ и совет по этому символу, а затем удаляет последний из первого. Поскольку все это происходит с завершением, это проще (для меня), чем копировать, вставляя лямбда-выражение.

(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
источник