Do Ediff as I mean
— Kaushal Modi- Updated
modi/ediff-dwim
to the latest revision in my config.
In almost all of my ediff
use cases, I would have windows open
side-by-side in a frame, and then I would want to do a diff between
the two using ediff-buffers
.
But emacs doesn’t know that I obviously want to diff those two
side-by-side buffers! So it always asks me to select the buffers to be
diffed. The same problem is when using ediff-files
too.
So I came up with the following helper function to pick the correct
ediff
command.
(defun modi/ediff-dwim ()
"Do ediff as I mean.
If a region is active, call `ediff-regions-wordwise'.
Else if the frame has 2 windows with identical major modes,
- Do `ediff-files' if the buffers are associated to files and the buffers
have not been modified.
- Do `ediff-buffers' otherwise.
Else if the current is a file buffer with a VC backend, call `vc-ediff'
Else call `ediff-buffers'."
(interactive)
(let* ((num-win (safe-length (window-list)))
(bufa (get-buffer (buffer-name)))
(filea (buffer-file-name bufa))
(modea (with-current-buffer bufa major-mode))
bufb fileb modeb)
(save-excursion
(other-window 1)
(setq bufb (get-buffer (buffer-name)))
(setq fileb (buffer-file-name bufb))
(setq modeb (with-current-buffer bufb major-mode)))
(cond
;; If a region is selected
((region-active-p)
(call-interactively #'ediff-regions-wordwise))
;; Else if 2 windows with same major modes
((and (= 2 num-win)
(eq modea modeb))
(if ;; If either of the buffers is not associated to a file,
;; or if either of the buffers is modified
(or (null filea)
(null fileb)
(buffer-modified-p bufa)
(buffer-modified-p bufb))
(progn
(message "Running (ediff-buffers \"%s\" \"%s\") .." bufa bufb)
(ediff-buffers bufa bufb))
(progn
(message "Running (ediff-files \"%s\" \"%s\") .." filea fileb)
(ediff-files filea fileb))))
;; Else if file in current buffer has a vc backend
((and filea
(vc-registered filea))
(call-interactively #'vc-ediff))
;; Else call `ediff-buffers'
(t
(call-interactively #'ediff-buffers)))))
Find this function in my emacs config.
My favorite ediff
settings are:
;; No separate frame for ediff control buffer
(setq ediff-window-setup-function #'ediff-setup-windows-plain)
;; Split windows horizontally in ediff (instead of vertically)
(setq ediff-split-window-function #'split-window-horizontally)