¿Cómo puedo eliminar un consejo sin nombre?

12

Me estaba divirtiendo agregando algunos consejos a una función:

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

Ay, un error tipográfico. Lo arregló y evaluó el código anterior nuevamente. Pero ahora tengo ambos, el consejo "corregido" y el "roto" en torno a esa función.

¿Cómo me deshago de estos? Dado que advice-removenecesita el objeto de función o el consejo (¿qué está vacío aquí?)

(Obviamente, puedo salir y reiniciar, pero hay otra forma, ¿no?)

Daniel Jour
fuente

Respuestas:

7

También puede llamar advice-removecon la misma expresión lambda, es decir, reemplazar advice-addcon advice-removey eliminar :around, luego C-x C-e.

xuchunyang
fuente
¡Esto funciona! Pensé que no lo haría, supuse que (1) cada vez que evalúas una forma lambda obtienes una nueva función no eqa las anteriores, (2) advice-remove compararía la función que la pasas a los consejos hasta que encuentre uno que es eqpara eliminarlo, (3) incluso si el consejo de eliminación utiliza una prueba diferente, como equal, todavía no funcionaría, porque las diferentes evaluaciones de una forma lambda no se aplicarían equalentre sí. Resulta que (1) es correcto, pero (2) y (3) están equivocados: aconsejar eliminar los usos equaly evaluarlos lambdados veces produce equalresultados.
Omar
Noté que no acepté una respuesta cuando hice la pregunta. Elijo el tuyo porque es la OMI más útil en la situación.
Daniel Jour
11

Hay advice-mapc, que vamos a iterar sobre todos los consejos de alguna función, aplicando una función dada a cada uno. Con él, es fácil eliminar todos los consejos:

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

Esto podría extenderse para eliminar solo los avisos que no tienen una namepropiedad buscando en el segundo propsargumento () (que es una lista) para aquellos que no tienen algo asociado a la clave name.

Daniel Jour
fuente
Si. Y usar un namehace que la eliminación sea más fácil.
Dibujó
1

Aquí hay un código para ayudar a hacer precisamente eso, de forma interactiva.

Esto define dos funciones. La primera función obtiene la lista de todos los consejos sobre un símbolo dado, la segunda función solicita interactivamente un símbolo y un consejo sobre ese símbolo, luego elimina el último del primero. Como todo esto sucede con la finalización, es más fácil (para mí) que copiar pegar la expresión 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
fuente