6

When I run save-buffers-kill-emacs or projectile-kill-buffers I get asked to save changed buffers. But for me a lot of these buffers do not differ from the file on disk. Can I make Emacs diff the buffer and file and only ask if there are differences? It can assume "no" or "yes" if there are no differences ("no" is preferred but I'm not picky).

Emil Vikström
  • 223
  • 1
  • 6
  • I suggest you `M-x report-emacs-bug` and request that this behavior be changed. Be sure to provide a recipe showing how you get into such a state. – Stefan Jun 18 '16 at 18:30
  • 1
    @Stefan I don't think there's a bug here. Open a file, add a line, delete the line, then kill the buffer. Emacs prompts you to save even though the buffer and file are identical. – glucas Jun 19 '16 at 19:26
  • 1
    I didn't say it was a bug either. `report-emacs-bug` is not restricted to bug reports: it's also the place to send feature requests. After all, the sender doesn't always know before hand in which category it should go anyway. – Stefan Jun 20 '16 at 02:34

1 Answers1

4

I've used a function like this for something similar:

(defun current-buffer-matches-file-p ()
  "Return t if the current buffer is identical to its associated file."
  (autoload 'diff-no-select "diff")
  (when buffer-file-name
    (diff-no-select buffer-file-name (current-buffer) nil 'noasync)
    (with-current-buffer "*Diff*"
      (and (search-forward-regexp "^Diff finished \(no differences\)\." (point-max) 'noerror) t))))

In my case I have a command to kill the current buffer that doesn't prompt if the buffer matches the file on disk, using:

  (when (current-buffer-matches-file-p)
    (set-buffer-modified-p nil))

before calling kill-buffer. You could do something similar over the current buffer list and use it to advise the relevant save/exit commands:

(defun maybe-unset-buffer-modified ()
  "Walk the buffer list and clear the modified flag for any
buffer marked modified that is identical to its corresponding
file on disk."
  (interactive)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and buffer-file-name (buffer-modified-p))
        (when (current-buffer-matches-file-p)
          (set-buffer-modified-p nil))))))

You can use advice to call this function before buffers are saved. For example:

(defadvice save-some-buffers (before maybe-mark-unmodified activate)
  (maybe-unset-buffer-modified))
glucas
  • 20,175
  • 1
  • 51
  • 83
  • I am trying to figure out how to trigger these functions. Is `kill-buffer-query-functions` the right place or can I somehow trigger the last function before `save-some-buffers`? – Emil Vikström Jun 17 '16 at 15:02
  • I think `kill-buffer-query-functions` is called too late in this case. You can advise `save-some-buffers`, I've updated the answer accordingly. – glucas Jun 17 '16 at 15:18
  • 1
    For `projectile-kill-buffers` I used this advice: `(advice-add 'projectile-kill-buffers :before #'maybe-unset-buffer-modified)` – Emil Vikström Jun 20 '16 at 15:56