Prompt de buffer de interrupção com opção para diferenciar as alterações

8

O save-some-bufferscomando solicita salvar ou ignorar cada arquivo modificado e também fornece uma opção para diferenciar o arquivo modificado no arquivo que está visitando.

Eu gostaria do mesmo comportamento de kill-bufferou kill-this-buffer. Se o buffer for modificado, já existe um prompt de sim / não, mas eu também gostaria da opção de ver as diferenças.

Existe uma maneira interna de fazer isso ou um ponto de extensão apropriado? Ou devo apenas ligar meu próprio comando kill-buffer?

glucas
fonte
Você pode querer examinar defadvice. Isso permitirá que você estenda facilmente o built-in kill-buffer.
Nano7
Usar o conselho 'antes' aqui parece comparável a escrever meu próprio comando, o que eu poderia fazer: apresentaria meu próprio prompt e, se o usuário quiser ir em frente e matar o buffer, acho que posso definir buffer-modified-pe chamar o original kill-bufferpara continuar matando sem outro aviso. Gostaria de saber se existe uma maneira melhor, mas pode dar uma chance.
glucas
Uau. Estou usando save-some-buffershá alguns anos e nunca soube que tem um diffrecurso ... Obrigado!
mbork
@ nanny Acabei usando conselhos para isso depois de tudo - veja minha própria resposta abaixo. Até agora, parece funcionar bem, obrigado.
glucas

Respostas:

6

A grande questão é se você deseja esse comportamento por kill-buffersi só, o que significa não apenas quando você o chama de maneira interativa, mas para todo uso no código Lisp existente, ou se você deseja apenas para uso interativo.

Eu vou assumir o último. Nesse caso, deixe em kill-bufferpaz, defina seu próprio comando que faça o que você deseja e remapeie as chaves que normalmente estão vinculadas kill-bufferao seu comando:

(global-set-key [remap kill-buffer] 'my-kill-buffer)

Para seu my-kill-buffercomando, basta verificar desde o início se o buffer foi modificado e, em caso afirmativo, inicie ediff-o.

Para verificar se foi modificado, use buffer-modified-p.

Para ediffvocê, você provavelmente desejaria pegar o arquivo (ou seja, o buffer como salvo) e diferenciá-lo do atual buffer modificado. Você pode precisar mexer um pouco para fazer isso - não conheço um ediffcomando existente que faça isso.

Mas talvez tudo o que você realmente precise seja algo parecido highlight-changes-mode. Veja o manual do Emacs, nó Highlight Interactively. Em outras palavras, talvez tudo o que você precise é invocar highlight-changes-modese o buffer foi modificado.

Desenhou
fonte
Obrigado @Drew, vou escrever meu próprio comando de matar. Alguns bits úteis: eu posso usar diff-buffer-with-filepara produzir as diferenças. Também parece que eu preciso ligar set-buffer-modified-pse quiser continuar e matar sem ser solicitado novamente a partir da implementação nativa.
glucas
5

Com base nas outras respostas e comentários, aqui está um comando kill personalizado que fornece a opção de diferenciar um buffer modificado com o arquivo que ele está visitando. Eu mapeei isso para, C-x C-kmas também poderia remapear kill-buffercomo sugerido na resposta de @ Drew.

(defun my/kill-this-buffer ()
  (interactive)
  (catch 'quit
    (save-window-excursion
      (let (done)
        (when (and buffer-file-name (buffer-modified-p))
          (while (not done)
            (let ((response (read-char-choice
                             (format "Save file %s? (y, n, d, q) " (buffer-file-name))
                             '(?y ?n ?d ?q))))
              (setq done (cond
                          ((eq response ?q) (throw 'quit nil))
                          ((eq response ?y) (save-buffer) t)
                          ((eq response ?n) (set-buffer-modified-p nil) t)
                          ((eq response ?d) (diff-buffer-with-file) nil))))))
        (kill-buffer (current-buffer))))))

Usando a mesma implementação básica, você também pode aconselhar kill-buffer. Com essa abordagem, você tem a opção de ver diferenças em qualquer lugar que kill-bufferseja chamado - por exemplo, ao eliminar buffers marcados do Ibuffer.

(defun my/kill-buffer (orig-func &optional buffer-or-name)
  (catch 'quit
    (save-window-excursion
      (with-current-buffer buffer-or-name
        (let (done (buf (current-buffer)))
          (when (and buffer-file-name (buffer-modified-p))
            (while (not done)
              (let ((response (read-char-choice
                               (format "Save file %s? (y, n, d, q) " (buffer-file-name buf))
                               '(?y ?n ?d ?q))))
                (setq done (cond
                            ((eq response ?q) (throw 'quit nil))
                            ((eq response ?y) (save-buffer) t)
                            ((eq response ?n) (set-buffer-modified-p nil) t)
                            ((eq response ?d) (diff-buffer-with-file) nil))))))
          (apply orig-func (list (current-buffer))))))))

(advice-add 'kill-buffer :around #'my/kill-buffer)
glucas
fonte
Um problema agora que usei isso um pouco: o loop read-char não permite rolar as diferenças ou executar outras ações. Eu provavelmente preciso usar a abordagem adotada pelo map-y-ou-np.
glucas