¿Cómo puedo cerrar automáticamente los búferes cuando se elimina el archivo subyacente?

9

Dejo Emacs funcionando todo el día, y a menudo haré mucha manipulación del sistema de archivos en los archivos que están abiertos en los buffers de Emacs. Por ejemplo, podría cambiar a una rama diferente en Git que tenga una estructura de directorio muy diferente.

Desafortunadamente, esto me deja con un montón de buffers abiertos que Emacs ahora registra como buffers "modificados" que se refieren a archivos "nuevos". A menos que tenga cuidado de cerrarlos manualmente cada vez que hago esto, es fácil guardar reflexivamente esos búferes que luego resultan en archivos espurios, probablemente duplicados en mi proyecto. Ni siquiera puedo cerrar emacs sin responder la pregunta "guardar este búfer" para cada uno.

¿Hay alguna manera de cerrar automáticamente los búferes no modificados cuando desaparece el archivo subyacente? ¿Similar en espíritu a un global-auto-revert-modeque también maneja cuando un archivo se elimina por completo?

levand
fuente
Consulte la sección 38.20 del
izkon

Respuestas:

6

Creo que algo en este sentido podría funcionar:

(defun buffer-backed-by-file-p (buffer)
  (let ((backing-file (buffer-file-name buffer)))
    (if (buffer-modified-p buffer)
        t
      (if backing-file
          (file-exists-p (buffer-file-name buffer))
        t))))

(mapc 'kill-buffer (-remove 'buffer-backed-by-file-p (buffer-list)))

La buffer-backed-by-file-pfunción verifica si el archivo está respaldado por un archivo; de lo contrario, devuelve verdadero; de lo contrario, devuelve si existe el archivo de respaldo. Luego tomamos la lista de buffers, filtrando todo menos aquellos que deberían tener un archivo de respaldo, pero el archivo no existe, y luego los eliminamos.

Requiere dash.el para -remove, porque era demasiado vago para encontrar un incorporado para lograr lo mismo.

¡Espero que esto ayude!

Algernon
fuente
Sin embargo, todavía debe ejecutar ese mapccomando cada vez que desee que se eliminen los archivos de almacenamiento intermedio no respaldados por archivos, ¿no es así? Entonces no es completamente automático. Para una automatización completa, debe asegurarse de que se mapcejecute repetidamente por sí mismo o usar algo como inotifyejecutarlo por usted cuando un archivo realmente se elimina.
izkon
Sí, uno necesitaría ejecutar esto periódicamente, o en respuesta a eventos de notificación o similares. Yo solo lo ejecutaba periódicamente, cada minuto más o menos. No es perfecto, pero es lo suficientemente bueno para la mayoría de los casos. (run-with-timer 60 60 (lambda () (mapc 'kill-buffer (-remove 'buffer-backed-by-file-p (buffer-list)))))es lo que usaría como primera aproximación.
algernon
1
Implementé esto, y funcionó muy bien. Usé esta pequeña función de contenedor para llamarlo, en caso de que alguien necesite algo similar: `(defun kill-remove-buffers () (interactivo) (let ((to-kill (-remove 'buffer-backup-by-file-p) (lista de búferes)))) (mapc 'kill-buffer to-kill) (mensaje "Killed% s buffers" (length to-kill)))) `Lo siento, no puedo formatearlo correctamente en el cuadro de comentarios .
levand