2

C-x s uses diff to show changes. How can I use ediff instead?

Trey Jackson
  • 73,529
  • 11
  • 197
  • 229
Yoo
  • 17,526
  • 6
  • 41
  • 47

2 Answers2

3

I can see a couple of approaches to doing this. The first is to replace the save-some-buffers-action-alist variable with modified code, which is more straightforward. The second is to advise save-some-buffers and redefine the functions called by those actions, but that's a bit trickier.

I tried it both ways, and I think this is the best option:

;; Use ediff instead of diff in `save-some-buffers'
(eval-after-load "files"
  '(progn
     (setcdr (assq ?d save-some-buffers-action-alist)
             `(,(lambda (buf)
                  (if (null (buffer-file-name buf))
                      (message "Not applicable: no file")
                    (add-hook 'ediff-after-quit-hook-internal
                              'my-save-some-buffers-with-ediff-quit t)
                    (save-excursion
                      (set-buffer buf)
                      (let ((enable-recursive-minibuffers t))
                        (ediff-current-file)
                        (recursive-edit))))
                  ;; Return nil to ask about BUF again.
                  nil)
               ,(purecopy "view changes in this buffer")))

     (defun my-save-some-buffers-with-ediff-quit ()
       "Remove ourselves from the ediff quit hook, and
return to the save-some-buffers minibuffer prompt."
       (remove-hook 'ediff-after-quit-hook-internal
                    'my-save-some-buffers-with-ediff-quit)
       (exit-recursive-edit))))

My attempt at using advice is flawed (it breaks the C-r behaviour which also calls view-buffer, which caused me to reconsider using advice for this purpose), but FWIW:

(defadvice save-some-buffers (around my-save-some-buffers-with-ediff)
  "Use ediff instead of diff."
  (require 'cl)
  (flet ((view-buffer (&rest) nil)
         (diff-buffer-with-file
          (buf)
          (add-hook 'ediff-after-quit-hook-internal
                    'my-save-some-buffers-with-ediff-quit t)
          (save-excursion
            (set-buffer buf)
            (ediff-current-file))))
    (let ((enable-recursive-minibuffers t))
      ad-do-it)))
(ad-activate 'save-some-buffers)

(defun my-save-some-buffers-with-ediff-quit ()
  "Remove ourselves from the ediff quit hook, and
    return to the save-some-buffers minibuffer prompt."
  (remove-hook 'ediff-after-quit-hook-internal
               'my-save-some-buffers-with-ediff-quit)
  (exit-recursive-edit))
phils
  • 71,335
  • 11
  • 153
  • 198
  • I changed my mind, and elected to update the `save-some-buffers-action-alist` directly. I've edited this answer accordingly, and have improved the code so that I am only changing the action associated with the "d" key. – phils Feb 05 '11 at 02:21
  • 1
    p.s. On my windows box with cygwin, the first time I use this I get a "cygwin warning: MS-DOS style path detected" error in an \*ediff-errors\* buffer, but all subsequent uses work as expected. I am presuming I simply have an issue with my cygwin integration to sort out, and that this issue (or anything similar) does not arise in general. – phils Feb 05 '11 at 02:27
  • This answer is great: (1) It answers the question, (2) it elabortes a bit on different solution paths and (3) it has the appropriate, brief, but pretty sophisticated code. And it works! :-) I wish I could make it the accepted answer... – halloleo Sep 04 '13 at 01:10
1

The variable diff-command is customizable, says the documentation. However, remember that it points to an external program, and not an elisp function. ediff is an elisp function that is in ediff.el. You might have to edit diff.el to (require 'ediff) and then tweak here and there in diff.el to see that you break nothing else.

vpit3833
  • 7,817
  • 2
  • 25
  • 25