3

I have a file that contains important information and I often have to make small changes in this file. Every once in a while I accidentally change something in this file and then save it without noticing that something is missing. What I'd like to have is that Emacs automatically shows me a diff between the buffer content and the content of the file on disk and asks me if I really want to save it. Is there an existing solution for this?

I found highlight-changes-mode but that's not what I want. I shows changes compared to when the mode was enabled not compared to the file on disk. In large files, it is also difficult to spot the changes even when they are marked red with highlight-changes-mode.

tmalsburg
  • 2,540
  • 1
  • 14
  • 29

1 Answers1

2

What about something like this?

#+BEGIN_SRC emacs-lisp
(defun my-diff ()
  (let ((temp-file (make-temp-file "gpgdiff-"))
    (contents (buffer-string))
    (current-file (buffer-file-name)))
    (with-temp-file temp-file
      (insert contents))
    (diff current-file temp-file))

  (unless (y-or-n-p "Save buffer?")
    (keyboard-quit)))

(add-hook 'before-save-hook 'my-diff t t) 
#+END_SRC

I guess you should probably put the last line in as a local variable, e.g.

# Local Variables:
# eval: (add-hook (quote before-save-hook) (quote my-diff) t t)
# End:
John Kitchin
  • 11,555
  • 1
  • 19
  • 41
  • Thank you, John. This is pretty close. Two problems though: 1.) If there are functions on the hook after my-diff, they won't be executed. 2.) It doesn't work when the file has a .gpg ending and is thus encrypted (`diff-buffer-with-file` doesn't support encrypted files.) I thought about using ediff but that apparently can only do buffer-buffer or file-file diffs. Hm ... – tmalsburg Sep 26 '16 at 12:45
  • 1
    Why not create a temp buffer holding the on-disk version of the file as well as the working version, and diff against that buffer? – JCC Sep 26 '16 at 13:04
  • By that I mean, before save open a copy of the current, on-disk version in a new buffer and diff them against one another. – JCC Sep 26 '16 at 13:56
  • I modified the solution to address part of the first comment. I am not sure what you should do about gpg, you need to incorporate un-encrypting into that function. – John Kitchin Sep 26 '16 at 15:21
  • @JackCC, I tried that but diff can only compare two files not two buffers. I could create a temporary file as in John's updated code but then I have a file on disk that contains the unencrypted data. I considered using ediff instead because it can compare two buffers, but it is interactive. Hm ... – tmalsburg Sep 27 '16 at 09:42
  • You can call interactive commands programmatically. Just use `call-interactively`. Is the problem that it prompts the user for inputs? If so, there are a couple of ways around that. – JCC Sep 27 '16 at 11:54
  • @tmalsburg have you found solution with gpg files? – slk500 Sep 22 '20 at 09:27