Como posso fechar automaticamente os buffers quando o arquivo subjacente é excluído?

9

Deixo o Emacs em execução o dia todo e, muitas vezes, fará muita manipulação do sistema de arquivos em arquivos abertos nos buffers do Emacs. Por exemplo, eu posso mudar para uma ramificação diferente no Git que tenha uma estrutura de diretórios muito diferente.

Infelizmente, isso me deixa com um monte de buffers abertos que o Emacs agora registra como buffers "modificados", referindo-se a arquivos "novos". A menos que eu tenha o cuidado de fechá-los manualmente toda vez que fizer isso, é fácil salvar reflexivamente os buffers, o que resulta em arquivos espúrios e provavelmente duplicados no meu projeto. Não consigo nem fechar o emacs sem responder à pergunta "salvar este buffer" de cada um.

Existe uma maneira de fechar automaticamente os buffers não modificados quando o arquivo subjacente desaparecer? Similar em espírito a um global-auto-revert-modeque também lida quando um arquivo é removido completamente?

levand
fonte
Confira a seção do manual Emacs 38.20 Notificações sobre alterações de arquivo
izkon

Respostas:

6

Eu acho que algo nesse sentido poderia 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)))

A buffer-backed-by-file-pfunção verifica se o arquivo é apoiado por um arquivo - se não, retorna true, caso contrário, retorna se o arquivo de backup existe. Em seguida, pegamos a lista de buffers, filtrando qualquer coisa, exceto aqueles que deveriam ter um arquivo de backup, mas o arquivo não existe, e os matamos.

Requer dash.el para -remove, porque eu estava com preguiça de encontrar um built-in para conseguir a mesma coisa.

Espero que isto ajude!

Algernon
fonte
Você ainda precisa executar esse mapccomando sempre que quiser que os buffers que não são suportados por arquivos sejam excluídos, não é? Portanto, não é totalmente automático. Para a automação completa, você deve ter certeza de que mapcé executado repetidamente por conta própria ou usar algo como inotifypara executá-lo quando um arquivo é realmente excluído.
izkon
Sim, seria necessário executar isso periodicamente, ou em resposta a inotificar eventos ou similares. Eu mesmo, eu o executava periodicamente, a cada minuto ou mais. Não é perfeito, mas é bom o suficiente para a maioria dos casos. (run-with-timer 60 60 (lambda () (mapc 'kill-buffer (-remove 'buffer-backed-by-file-p (buffer-list)))))é o que eu usaria como primeira aproximação.
algernon
11
Implementou isso e funcionou muito bem. Eu usei essa pequena função wrapper para chamá-la, caso alguém precise de algo semelhante: `(defun kill-removed-buffers () (interativo) (let ((to-kill (-remove 'buffer-back-by-file-p (buffer-list)))) (mapc 'kill-buffer to-kill) (mensagem "Killed% s buffers" (comprimento a matar)))) `` Desculpe, mas não consigo formatá-lo corretamente na caixa de comentários .
Levand