2

Is there any editor/IDE that provides a live view of differences (probably using diff) while I am editing a file. The ideal setting would be when I open a file for editing in such a diff-mode, the file is buffered in two independent panes (but put side by side), so that when I edit the contents of one, the differences of the two are highlighted for me.

5
  • 1
    You've already asked about automating Vim's :diffupdate; what's missing from vimdiff for you?! Commented Apr 12, 2013 at 19:40
  • 1
    There are two drawbacks of vimdiff: 1. it cannot buffer the same file independently to allow a diff comparison. Of course, this can be solved by automatically making a temporary copy of the file; 2. Inside vimdiff, inline editing (inserting or deleting) could not trigger diff to recalculate the difference, one has to do it manually by executing :diffupdate. I want this recalculation to be automated when I exit the INSERT mode and enter the NORMAL mode.
    – day
    Commented Apr 12, 2013 at 20:30
  • 1
    +1 the question. because I see finally, the two guys: vim and emacs are sitting together in tags row, and watching us to post answer.
    – Kent
    Commented Apr 12, 2013 at 23:36
  • 1
    @plmday vim you could create au for event InsertEnter/InsertLeave. you can call diffupdate there.
    – Kent
    Commented Apr 12, 2013 at 23:45
  • @Kent, exactly. Actually I have found the perfect solution is to catch the events CursorMoved and CursorMovedI.
    – day
    Commented Apr 13, 2013 at 11:04

1 Answer 1

3

There doesn't seem to be an existing Emacs mode to do exactly what you want, but a cursory googling turned up this and this.

From the second one (with mildly fixed formatting):

(defun diff-buffer-against-file (context)
    "diff the current [edited] buffer and the file of the same name"
    (interactive "P")
    (let (($file buffer-file-name)
          ($tempFile "/tmp/emacs.diff")
          ($tempBuffer "emacs.diff"))
        (delete-other-windows)
        (push-mark (point) t)
        (generate-new-buffer $tempFile)
        (copy-to-buffer $tempBuffer (point-min) (point-max))
        (set-buffer $tempBuffer)
        (write-file $tempFile)
        (shell-command (concat (if context "diff -c " "diff ") $file " " $tempFile))
        (kill-buffer $tempFile)
        (pop-mark)))

(global-set-key "\C-cd" 'diff-buffer-against-file)

The operation looks a bit too intense to bind to a change hook, but there's nothing preventing you from doing so if you're into that sort of thing.

Edit: Stefan points out that diff-buffer-with-file exists, and has the behavior you're looking for (it takes a buffer, and diffs that buffer with its file, showing that output in an unfocused temporary buffer), so you don't even need to define the above. I did try it though, and the naive

(defun diff-current (start end len) (diff-buffer-with-file (current-buffer)))
(add-hook 'after-change-functions 'diff-current)

makes editing too uncomfortable for my tastes. You'll probably want to follow Stefan's suggestion and use a timeout instead of diffing immediately on every change.

2
  • 3
    Emacs already provides diff-buffer-with-file, no need to write it by hand any more. It would probably be OK to add such a function to a timer (it wouldn't be refreshed immediately, but soon).
    – Stefan
    Commented Apr 12, 2013 at 20:50
  • It is nice to see that Emacs also provides a partial solution, which may be hacked as you suggested to a full solution.
    – day
    Commented Apr 13, 2013 at 11:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.