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…