Emacs Evil Motion Training

20200628
~07 mins
tl;dr: Punish yourself for poorly chosen evil motions in Emacs.

I made the switch to Emacs last year after having been a resolute vim user ever since I dual booted Slackware on my family’s first computer as an early teen.

Needless to say the power of the Emacs pseudo lisp machine quickly opened my eyes. I immediately lunged into consolidating practically all my text use cases sans browsing into Emacs: programming, note taking, RSS, mail, git porcelain, GitHub PRs and issues, IRC/Slack. I even entirely replaced my use of a separate terminal emulator. My browser has since clawed back the mail, Slack and some GitHub use cases from Emacs' grasp, but if it weren’t for me staunchly trying to stick to Wayland I am quite sure I’d be writing this from inside EXWM by now.

However, the old adage goes:

“Emacs is a great operating system missing a great editor.”

And it was true for me, but fixable.

Evil Mode

I tried Emacs native key chords for all of a day or two before giving up and enabling evil mode. It could be that I’m too far gone, but I simply could not live without modal editing and the intuitive verb-object vi key bindings that I had become accustomed to.

For me, having proficiency at moving around a buffer and manipulating text in this manner means anything else feels like a bit of a regression. What’s more, I’ve always used vi styled bindings anywhere I can, be it in terminal readline mode, my tiling window manager du jour, or Firefox (Tridactyl is my pick of the post-XUL era bunch). Even back in my enterprise Java days, when forced to dip into the heavyweight IDE world with the likes of Eclipse and IntelliJ IDEA, I’d still reach for a plugin.


I think with evil mode and Emacs you’re truly getting the best of both worlds. Emacs can be the great editor (neo)vi(m) is. It can be just as snappy (see native-comp), start just as fast (see emacsclient / Doom’s optimisations), and has all the modern trimmings you would expect in an editor (e.g. LSP, ligatures, pgtk).

It is, however, the famed Emacs extensibility that sets it apart from the crowd for me. Vimscript, Neovim’s Lua extensions, even VSCode’s extensions API are—to butcher Greenspun’s aphorism—just ad hoc, informally-specified, bug-ridden, slow implementations of half of Common Lisp Elisp.

With Elisp packages, Emacs can become a cybernetic extension of your arm. Though package authors are not really writing an extension, they’re just writing more Emacs. That, I think, is the crux of it.

Speaking of packages, there are of course all the usual big hitter packages that you’ll find on any list, like Magit, Org, TRAMP, Projectile, Ivy and Dired to name a few. However, today I’m showcasing a small package to improve proficiency in evil motions.

Proficiency

Not long before my switch to Emacs I had started trying to kick some bad habits with vim. Let’s call them lazy motions. I knew better ways of moving the cursor from a to b, but the cognitive overhead, or lack of muscle memory perhaps, was too much to overcome. If you’re also a vim user then there’s a chance you know what I mean: hhhhhhhhhhhhjjjjjjjjkkkkkllllhjk. That is, favouring a single character/line oriented movement over a more esoteric (but known to you!) and undeniably precise movement.

The word-wise motions (e.g. wW, bB, eE, ge), character searches (e.g. fF, tT, ,, ;) and line jumps (e.g. 10j 5k) will almost always get you where you want to be with less keystrokes.

I was slowly beginning to fix this through a somewhat Pavlovian vim plugin called vim-hardtime which would tase me when I repeatedly used these keys in succession. Unfortunately I lost this with the switch to Emacs and the return to familiar modal surroundings in evil mode, and sure enough the bad habits came back.

To my dismay I could not find a directly equivalent Emacs package so today I’m releasing the evil-motion-trainer on GitHub.

Evil Motion Trainer

Just like the vim plugin, entering evil-motion-trainer-mode means Emacs will drop lazily repeated hjkl-based motions after a configurable threshold, forcing you to think about a more efficient motion:

Configuration

Enable in a buffer with:

(evil-motion-trainer-mode)

Turn on for all buffers:

(global-evil-motion-trainer-mode 1)

Configure the number of permitted repeated key presses:

(setq evil-motion-trainer-threshold 6)

Enable a super annoying mode that pops a warning in a buffer:

(setq evil-motion-trainer-super-annoying-mode t)

Add to the suggested alternatives for a key:

(emt-add-suggestion 'evil-next-line 'evil-avy-goto-char-timer)
;; See also: (emt-add-suggestions)