Key bindings are one of first things a new Emacs user will experiment with. The default key bindings don’t follow recent OS conventions and may seem complicated and hard to remember; so when you discover how easy it is to change them, it may be hard to resist customizing everything. This is of course one of the great things about Emacs: you can and should configure it for your needs.
I’ve dabbled with key bindings over the years1 but have settled on using default bindings for most things. Here are some notable exceptions2.
Replacing defaults with DWIM commands
There are only so many keys available. If you can find one command that does the job of two or three others, based on context, it can free up some keys – and be one less thing to remember. In Emacs circles such commands are often referred to as DWIM (Do What I Mean) commands.
An easy place to start are the case commands. Emacs has separate commands for capitalize-word
and capitalize-region
, but it also provides capitalize-dwim
that can do either depending on whether you have a region selected:
(bind-keys
([remap capitalize-word] . capitalize-dwim)
([remap upcase-word] . upcase-dwim)
([remap downcase-word] . downcase-dwim))
Another DWIM command (for me at least): when I hit C-x k
to kill a buffer, I always mean the current one:
(bind-key [remap kill-buffer] 'kill-this-buffer)
There are also some DWIM commands that cycle through possible outcomes rather than trying to guess what you want. This can be very convenient – I usually want the first result, and when I want a variation I don’t have to remember what the other command is:
(bind-key [remap just-one-space] 'cycle-spacing)
Easier key combinations
Some of the default bindings are just hard to type. I use emacsclient
to interact with Emacs running as a server, so the server-edit
command comes up fairly often in my workflow. The default binding is C-x #
, which is fairly straightforward but does require switching modifiers to get that #
. A quick fix is to just replace Shift
with Control
:
(bind-key "C-x C-3" server-edit)
Avoiding prefix keys for common actions
There are some actions in Emacs that are so common that a binding with a prefix (such as C-x o
) feels like overhead. In recent versions Emacs has introduced repeat-mode
and provided a repeatable binding that simplifies this sort of thing: you can type C-x o o o
to switch windows multiple times, without needing the C-x
prefix every time. This is a great improvement; but in practice I’m usually just working with two windows and don’t need the repeat.
I’ve adopted M-o
for other-window
. It’s convenient and not bound by default. I’ve also adopted M-i
for the related action of switching buffers in the current window. Emacs has a built-in function for what I want here, but it isn’t bound to anything. (M-i
defaults to tab-to-tab-stop
, which is something I have never used.) This pair of bindings makes getting to the window and buffer I want fast and easy:
(bind-keys*
:filter (not (minibufferp))
("M-o" . other-window)
("M-i" . mode-line-other-buffer))
A couple of notes on this one:
-
I’m using
bind-keys*
to makes these global bindings that override any mode-specific bindings. Your mileage may vary, but so far I’ve found having these globally consistent more useful then any mode-specific behavior (which I can always rebind anyway). -
The one exception to the previous point is the minibuffer. Switching buffers makes no sense in the minibuffer; and I don’t often use
other-window
to switch in and out of the minibuffer, so I can always fall back toC-x o
in that situation. There are packages that provide useful minibuffer behavior on these keys by default, so I’ve added a filter here.
One more other-window tweak
I like the ace-link package, which lets you quickly jump to links in a buffer by highlighting available links with a jump target. By default ace-link
binds o
for this.
The new Emacs repeat behavior can get in the way of that. Let’s say you open a help buffer, e.g. C-h f
to get help for some command. You see a useful link so you want to switch windows and then jump to the link:
-
C-x o
(orM-o
with my bindings) gets you to the help window. -
o
should triggerace-link
to jump to the link… but instead it takes you back to the window you just left.
There are various ways to address this, but I’ve built the habit of using M-o o
to do this sort of thing. It’s a very simple key sequence that gets me where I want quickly.
With M-o
for other-window
I don’t really benefit from its repeat behavior, so let’s drop that as part of configuring ace-link
. Easy enough:
(use-package ace-link
:init
(ace-link-setup-default)
;; Allow for `M-o o' to switch window and jump to link
(unbind-key "o" other-window-repeat-map))
-
One customization I stuck with for a long time was binding
M-1
,M-2
, etc. to the window split commands that default toC-x 1
,C-x 2
, and so on. Havingdigit-argument
bound to bothM-
andC-
prefixes seemed like a waste! I eventually realized the convenience of passing a numeric argument to a command without having to switch modifiers. It’s much faster to typeC-3 C-k
to delete three lines andM-3 M-f
to go forward three words than to mix modifiers.. ↩︎ -
I am using the
bind-key
package in these examples, which is built in to Emacs 29.1 and available as an optional package for earlier versions. For a definitive explanation of key bindings, check out the excellent article Mastering Key Bindings in Emacs. ↩︎