Setting up Ediff
17 Jan 2015Once you make Ediff bearable, it becomes wonderful. At least this was my experience. It's a very good tool, but some of the defaults look very poor to me.
Customizing the customize
First of all, I'll list a macro that I've started to use for setting custom variables:
(defmacro csetq (variable value)
`(funcall (or (get ',variable 'custom-set)
'set-default)
',variable ,value))
This macro I've put together myself after searching though the code
base and not finding something similar; custom-set-variables
comes
close to what I want, or maybe custom-initialize-changed
. Basically
all I want is a setq
that is aware of the custom-set
property of a
variable. If you know such a macro, please let me know.
Changing some Ediff options
Now, that I've explained the custom setter (by the way, using
custom-set-variables
is absolutely equivalent to csetq
), here are
my changes:
Don't use the weird setup with the control panel in a separate frame. I can manage windows in Emacs much better than my desktop (Unity or Gnome Shell) can manage the Emacs frames.
(csetq ediff-window-setup-function 'ediff-setup-windows-plain)
Split the windows horizontally instead of vertically. This way, it's much easier to follow the changes.
(csetq ediff-split-window-function 'split-window-horizontally)
Ignore white space. I don't write a lot of Python, so I don't care about the white space in the diffs. At the same time, I re-format any LISP code that I edit to my liking, and I want to see only the important changes in the diff, and not the whitespace nonsense.
(csetq ediff-diff-options "-w")
Changing some Ediff key bindings
This is just the standard stuff that I like to do for each mode that does not self-insert: assign j to move down, and k to move up.
(defun ora-ediff-hook ()
(ediff-setup-keymap)
(define-key ediff-mode-map "j" 'ediff-next-difference)
(define-key ediff-mode-map "k" 'ediff-previous-difference))
(add-hook 'ediff-mode-hook 'ora-ediff-hook)
Restoring the windows after Ediff quits
When you quit an Ediff session with q, it just leaves the two diff windows around, instead of restoring the window configuration from when Ediff was started. Here's the (slightly hacky) code to restore the old window configuration:
(winner-mode)
(add-hook 'ediff-after-quit-hook-internal 'winner-undo)
List of ways that I use to invoke Ediff
from magit
In 80% of the cases, I call Ediff with e (magit-ediff
) from
magit-status-mode
. This gives me a better overview of the changes,
especially when I want to revert stuff with either a
(ediff-copy-A-to-B
) or b (ediff-copy-B-to-A
). Probably
with a, since magit seems
to consistently put the @{index}
file into the A
diff window, and
the current file into the B
window.
So if I'm looking at a diff (to which I navigated with
j/k), I can revert it with a. At this
point, the diff region in the current file will become equal to that
of the index file. But it will not be saved yet. If I want to save the
current file in the B
window, I can do it with wb
(ediff-save-buffer
). After a revert, it's also useful to call
!(ediff-update-diffs
), which will remove the zero-length
diffs and update the diff-count in the mode-line.
other methods
ediff-buffers
will diff two (different) buffers. If you happen to have only two windows open with the appropriate buffers, you get them as defaults and can choose them quickly with RET RET.ediff-files
is similar, but works on files instead. I like to just mark the appropriate files indired
with m, then they also get auto-selected byediff-files
.ediff-current-file
is useful to see the unsaved changes to the current file. I rarely use it, since I have a compulsion to save every file every chance I get. There is little hope to recover from this addiction, unless someone implements an analogue of guru-mode that annoys you when you try to save a file. Actually, it's not a bad idea - C-x C-s:
Oleh, you have saved this file
40 times
in the last hour; the last save was0 minutes 34 seconds ago
; since then, you've changed27 bytes
of information. Are you sure you want to save[y/N]
?