IJKL-based movement (and deletion!) keybindings for Emacs
This is a description of my own variation on ErgoEmacs-style key
bindings for Emacs. Xah Lee’s writings on the inefficiency and poor
ergonomics of Emacs’ standard key bindings stuck in my mind from the
first time I read them and permanently changed how I think about
keyboard shortcuts. The single biggest idea is that the Alt
key is a
more ergonomic modifier to use than Ctrl
, because you can hit it or
hold down with your thumb by curling it under the other fingers.
However, I could never go all the way with ErgoEmacs; it was too big a change for me to swallow. Instead, I started with IJKL-based cursor movement and added things little by little, interfering as little as possible with commonly-used Emacs bindings, so my muscle memory will still work.
Here is what I have converged on as of now. These keybindings apply
solely to keys on the right-hand side of the (qwerty) keyboard with the
Alt
key (called the Meta key in Emacs) held down. They can be
adopted incrementally until you get used to them, which is exactly
what I did myself and how they’re presented here. I’ll describe each
related subset of bindings, giving my justification, and also a heads-up
about which of the default Emacs keybindings they overwrite, if any.
As of writing this post, I’m using Emacs 28.2. I don’t think there’s anything strongly version-specific about what we’re doing here.
Prelude: pageup and pagedown
The Emacs default pageup and pagedown keys are Alt-v
and Ctrl-v
respectively, which are quite awkward to hit and have no logical or
spatial relation to any other movement keys.
So, for I don’t remember how long, I’ve using Alt-p
and Alt-n
for pageup
and pagedown. Those keys are thankfully unbound in vanilla Emacs, so
it’s no problem at all to set them. Here’s the code you can put in your
.emacs:
(global-set-key (kbd "M-n") 'scroll-up) ; AKA pagedown
(global-set-key (kbd "M-p") 'scroll-down) ; AKA pageup
These make sense to emacs users because they correspond to the
single-character up and down movement keys, Ctrl-p
and Ctrl-n
. They
also follow our overarching principle of being reachable from the right
hand. Finally, they also make some spatial sense, because the p
key,
which moves upward in the buffer, is on the top row of the qwerty
layout, and n
is on the bottom row.
The core bindings: single-chararacter and word movement
It’s well known that using the IJKL keys as an inverted-t cursor group allows the right hand to remain on the home row. ErgoEmacs itself uses IJKL movement, so these bindings are identical to ErgoEmacs:
(global-set-key (kbd "M-i") 'previous-line)
(global-set-key (kbd "M-j") 'left-char)
(global-set-key (kbd "M-k") 'next-line)
(global-set-key (kbd "M-l") 'right-char)
As an aside, I’ve considered making Emacs keybindings using WASD, because that’s what most 3D games use (because the right hand is for the mouse), and also I am left-handed, but I decided against it because: 1) it requires messing up too many essential default keybindings, and 2) It requires shifting your hand over from the home-row position. I guess using ESDF would be the solution to #2, but I think that would be too confusingly similar to WASD.
Of course, as all the text editing ninjas know, moving by a single character at a time should be a rare occurrence. The keybindings for jumping left and right by whole words are no less important. Here we again use the same bindings as ErgoEmacs:
(global-set-key (kbd "M-u") 'backward-word)
(global-set-key (kbd "M-o") 'forward-word)
These are to the right of left of the i
key, so spatially they make
sense. Some laptop keyboards have pageup/pagedown or home/end navigation
keys in the same relative location to the cursor keys.
The default Emacs binding for M-u
is <upcase-word>
, which I never
used. I used to have Alt-o
bound to <other-buffer>
, but now I use
Alt-,
and Alt-.
to rotate around buffers in a frame. So there’s a
bonus hint for you about bindings for non-cursor movement. Cheers.
Stretching farther
Some of the most important movement functions are moving to the
beginning or end of the current line, <home>
and <end>
respectively.
Every Emacser probably has the default bindings for these, Ctrl-a
and
Ctrl-e
, burned into their muscle memory. But if we’re committed to
this new right-hand movement scheme, we need new bindings. Letting go
of everything to press Ctrl-a
or Ctrl-e
while moving around with
Alt
-IJKL kind of defeats the purpose of the whole enterprise.
Here’s where the new ideas start to come in. ErgoEmacs uses Alt-h
to
go to the beginning of the line. It makes sense spatially, because
hitting it involves reaching further to the left of the left movement
key (j
), and it makes the cursor take a larger jump to the left.
What ErgoEmacs doesn’t do is map the corresponding key on the right to
<end>
. But I do. So here are my <home>
and <end>
bindings:
(global-set-key (kbd "M-h") 'move-beginning-of-line)
(global-set-key (kbd "M-;") 'move-end-of-line) ; overwrites comment-dwim
These interfere with some more commonly-used keybindings. The default
Emacs keybinding for Alt-h
is mark-paragraph
, which actually sounds
quite handy but I had never used it before. Prior to adopting these
bindings, I had Alt-h
bound to backward-kill-word
, corresponding to
the Readline binding of Ctrl-h
to backspace (Emacs’ default binding of
Ctrl-h
to <help>
makes no sense to me.) We’re going to rebind both
those deletion functions in just a bit.
Alt-;
is normally bound to <comment-dwim>
, which probably a lot of
people use, and that’s why ErgoEmacs doesn’t overwrite it. But somehow
it never got ingrained for me.
If you occasionally edit an XML file (like your OpenBox window manager
configuration file), Emacs’ nxml-mode rebinds Alt-h
, so I need this in my
config:
(define-key nxml-mode-map (kbd "M-h") 'move-beginning-of-line) ; was mark-paragraph
Editing (deletion) with Shift
Here’s the grand finale! This is probably the biggest departure from
commonly-used bindings. If you hold down Shift
along with Alt
, the
left and right movement keys become the corresponding deletion keys:
(global-set-key (kbd "M-O") 'kill-word)
(global-set-key (kbd "M-U") 'backward-kill-word)
(global-set-key (kbd "M-L") 'delete-char)
(global-set-key (kbd "M-J") 'delete-backward-char)
(global-set-key (kbd "M-:") 'kill-line) ; overwrites eval-expression (elisp)
There’s no built-in interactive function for deleting backwards from the point to the beginning of the line, so we need to grab one from https://www.emacswiki.org:
(defun backward-kill-line (arg)
"Kill ARG lines backward."
(interactive "p")
(kill-line (- 1 arg)))
(global-set-key (kbd "M-H") 'backward-kill-line)
Are these bindings surprising? In every other non-modal editor, holding
down Shift
with movement keys selects the text that you move over.
But in my mind, holding down Shift
to add modification to a movement
action just makes sense. I use the same principle in my window manager
keyboard configuration. And true Emacsers use Alt-space
to set the
mark for selection, so they should have no issue. And it doesn’t stop
the casuals from doing Shift-selection with the cursor keys.
And that’s it! It would be cool if someone else gets inspired to customize their keybindings in a similar way. Then we’ll all be happily whizzing around in our code and deleting exactly what we want to delete at the speed of instinct.
Full disclosure: I’m not yet fully broken from using Ctrl-{a,e,p,n}
sometimes. Gimme a break, I’ve been using Emacs since 1996!
Concluding remarks
I guess I liked these controls enough to blog about them because they have a logical consistency that appeals to me. I don’t plan to release a package, because if it were a package I probably wouldn’t use it myself; if a customization takes just a small amount of elisp code, I would rather just put it directly in my .emacs where I can see it and tweak it.
There are other, fancier ways of moving the cursor around in Emacs,
from search functions configured with Ctrl+s
to fancy jump modes.
Xah himself has switched to modal editing and has a widely
used mode xah-fly-keys, while ErgoEmacs is now maintained by Matthew L
Fidler. And the search for the perfect key configuration goes on…