Como posso remover um conselho sem nome?

12

Eu estava me divertindo adicionando alguns conselhos a uma função:

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

Ai, um erro de digitação. Corrigido e avaliado o código acima novamente. Mas agora tenho os conselhos "corrigido" e "quebrado" em torno dessa função.

Como faço para me livrar deles? Dado que advice-removeprecisa do objeto de função ou do conselho ao redor (que está vazio aqui)?

(Obviamente, posso simplesmente sair e reiniciar, mas há outra maneira, não é?)

Daniel Jour
fonte

Respostas:

7

Você também pode chamar advice-removecom a mesma expressão lambda, ou seja, substituir advice-addpor advice-removee excluir :around, então C-x C-e.

xuchunyang
fonte
Isso funciona! Eu pensei que não, assumi que (1) toda vez que você avalia uma forma lambda, recebe uma nova função que não eqa anterior, (2) aconselha-remove compara a função que você a transmite aos conselhos até encontrar aquele que é eqa ele e o remove, (3) mesmo que o conselho-remova usasse um teste diferente, por exemplo equal, ele ainda não funcionaria, porque avaliações diferentes de uma forma lambda não funcionariam equaluma à outra. Acontece que (1) está correto, mas (2) e (3) estão errados: aconselhar - remover usos equale avaliar o mesmo lambdaduas vezes produz equalresultados!
Omar
Notei que não aceitei uma resposta quando fiz a pergunta. Eu escolho o seu porque é o IMO mais útil na situação.
Daniel Jour
11

advice-mapc, que vamos iterar sobre todos os conselhos de alguma função, aplicando uma determinada função a cada uma. Com isso, é fácil remover todos os avisos:

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

Isso pode ser estendido para remover apenas avisos que não possuem uma namepropriedade, procurando no segundo propsargumento () (que é uma lista) para aqueles que não têm algo associado à chave name.

Daniel Jour
fonte
Sim. E usar um namefacilita a remoção.
Drew
1

Aqui está um código para ajudar a fazer exatamente isso, de forma interativa.

Isso define duas funções. A primeira função obtém a lista de todos os conselhos sobre um determinado símbolo, a segunda função solicita interativamente um símbolo e um conselho sobre esse símbolo e remove o último do primeiro. Como tudo isso acontece com a conclusão, é mais fácil (para mim) do que copiar e colar a expressão 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
fonte