Whenever I have gone looking for the Emacs equivalent of Drew Neil's amazing Practical Vim1, I have always found people recommending reading the Emacs manual, saying how good it is. For the longest time I put it off, and I was on the verge of ordering Mickey Petersen's Mastering Emacs, which I also often see mentioned, when I decided that I should just bite the bullet and at least start with the manual. It can't be that much of an undertaking, right? ... right?
Coming into 2020, I decided that I'd get through the manual by the end of January. I had no idea how much content was in there. Throughout the first 30 days of 2020 I sunk hour upon hour upon hour into this collection of text documents, assembled through many decades, until I finally found my way out, clothes tattered and torn, beard long and graying2, but my mind opened and enlightened.
What I want to share today is not the entire voyage, but rather just the high points that come to mind when I think back on my journey. Undoubtedly there will be things I've forgotten that should be here and things that are here that I should have forgotten, but such is the nature of human experiences. The best we can do is to just sit back and enjoy what we have.
I will be using the same notation for key bindings as Emacs does in the manual. Most characters are just represented as themselves, but some are special. Chords (or modified keys) are represented as modifiers connected to letters by a hyphen. A list of the modifiers and special keys used in this document is presented below. More information on characters and notation can be found in chapter 2 of the Emacs manual. - ~C~ and ~M~ :: These upper case letters represent ~Control~ (your trusty control key) and ~Meta~ (usually alt), respectively. When used with other characters, they're connected by a hyphen: ~C-a~ and ~C-M-a~, for instance. - <RET> :: The return (or enter) key - <ESC> :: The escape key In addition, note that ~M-x~ opens the ~execute-extended-command~ menu, wherein you can type in the name of a command. Thus, when you see something such as ~M-x other-window~, that means that the text after ~M-x~ is the name of the command. To execute the command, press return.
The Emacs key bindings
Among the reasons to go through the manual, learning the 'proper' Emacs key bindings was actually pretty high up. It might seem trivial, but there's been a number of times where I've ended up in a state that I just can't navigate and don't know how to get out of.
As someone who fell in love with the Vim way of editing, I came to Emacs through Spacemacs, which uses Evil mode to provide a very comfortable editing experience for Vim users. As such, I've already spent a considerable amount of time learning one very specific set of key bindings (and I love it every day). Why would I bother learning another?
For some time, I've been using 'hybrid-mode', giving me Vim key bindings in every mode except insert mode, where I switch to using Emacs key bindings. What I have discovered is that they both have their uses, and they shine in different ways. When navigating text, I feel much safer and much more agile in Vim's normal mode, able to take leaps and bounds through the buffer, working on text as objects, confident that I won't accidentally insert some text by a stray key press. However, when typing out text, having to exit insert mode and then type a command before entering insert mode again can be pretty tedious, and being able to make certain movements from that state just makes a lot of sense. A good example would be needing to go back to an earlier part of a line, delete some text, and then keep inserting at the end. In Vim, assuming we're already in insert-mode:
? d a w A
And in Emacs
If my counting is correct, the Vim version has three more key presses than the Emacs version. Unless you're into golfing, this probably doesn't mean much to you (especially if
d a w feels like a single movement to you), but to me, it feels (subjective, I know) like more work.
A surprising key binding that I've never really considered, but which Emacs has bound to
C-M-v by default:
scroll-other-window. If you have multiple windows open in a single frame, it'll scroll one of the other windows, but lets you keep your focus (and your cursor) in your current window. There may be a way to target a specific window, but I found it most useful when having only two windows open. If you have more than two windows open, it'll scroll the next window as defined by Emacs buffer ordering. From what I can tell, this is left to right, top to bottom. It's the same order as when going through the windows by
C-x o (
Navigating text (chapter 25)
Naturally, coming from Vim, I think that the Vim way is the way for navigating text on a screen. Or at least I did. In fact, I was surprised to learn that Emacs has all the same facilities for navigating a buffer as Vim does, and it turns out that all the same movement patterns that I rely on in Vim are available in Emacs; they're just bound to different keys.
There are a couple of editing patterns that I haven't found the equivalent of yet, though (send me tips if you've got them!):
- The equivalent of ~vim-surround~
- Yup, Evil has a function for it, and I'm sure you can write a function that will contain text, change surrounding delimiters to something else, or delete surrounding delimiters, but it's not immediately available. That said, even in Vim, it's a plugin, so maybe this shouldn't count.
- Delete to next search hit
- In Vim (normal mode), a common way for me to operate on some text is to
d / <search string> <RET>to delete up until the first occurrence of the search string. I haven't found a way to do that in barebones Emacs. Emacs comes with the default binding of
zap-to-char, which is almost what I want. However, rather than being able to input just a single character, I want to be able to input a search string and kill up to that point. It'd be similar to
C-<SPC> C-s <search string> <RET> <DEL>, but without killing the actual search string (kill up to, not including), and it should be a single key chord. If I were to override the
M-zbinding, it'd be
M-z <search string> <RET>.
Overall, though, I am surprisingly happy with Emacs' movement keys, and while I don't think I'll be switching over completely just yet (or ever?), being able to navigate comfortably in either mode can only make things better.
The kill ring (chapter 12.2.1)
Of all the things I've learned, this is probably the one that's given me the most bang for my buck. Whatever your preferred way of getting text into your kill ring (also known as the clipboard), once you've got it there, Emacs doesn't just store the last entry, but rather your last 60 (by default) entries. The reason it's called a ring is that you can cycle through your entries, and once you reach the end, you loop back around.
So when you paste (or yank) something into a buffer with
C-y, you can then follow that up by using
M-y to cycle through the kill ring. You can view the entire contents of the kill ring with
C-h v kill-ring, though be warned: the kill ring is displayed as lisp code, so it may not read as plainly as you'd expect.
Side note: I wish Vim and Emacs could at least agree on the meaning of the word 'yank'. Whether it means to copy something from the buffer (Vim) or to paste something into the buffer (Emacs), I don't care. Just pick one.
The undo-stack (chapter 16.1)
Spacemacs uses the undo-tree-mode (see the Emacs wiki entry) to store buffer states in a change tree. This is really intuitive and lets you visualize your changes in a graphical model that maps pretty well onto my view of a set of changes. What I wasn't aware of was that plain, ol', vanilla Emacs comes with a pretty uncommon, but super-powerful undo history out of the box: instead of taking the view that history branchces after undoing a change, the default undo is more like a strictly linear timeline. When you undo a change, Emacs simply pushes this onto the history 'stack' as a new change. Thus, Emacs doesn't have a traditional redo as such: it's just another undo.
It's a bit tricky to wrap your head around, but is really worth checking out. For context, here is an excerpt from the relevant chapter in the manual (link to web version):
To begin to undo, type ~‘C-/’~ (or its aliases, ~‘C-_’~ or ~‘C-x u’~). This undoes the most recent change in the buffer, and moves point back to where it was before that change. Consecutive repetitions of ~‘C-/’~ (or its aliases) undo earlier and earlier changes in the current buffer. If all the recorded changes have already been undone, the undo command signals an error. Any command other than an undo command breaks the sequence of undo commands. Starting from that moment, the entire sequence of undo commands that you have just performed are themselves placed into the undo record. Therefore, to re-apply changes you have undone, type ~‘C-f’~ or any other command that harmlessly breaks the sequence of undoing; then type ~‘C-/’~ one or more times to undo some of the undo commands. Alternatively, if you want to resume undoing, without redoing previous undo commands, use ~‘M-x undo-only’~. This is like ‘undo’, but will not redo changes you have just undone.
Bookmarks (chapter 13.8)
When reading through a document in several sittings, it's useful to be able to jot down how far you'd gotten so that you can easily resume your reading. To this end, Emacs has a bookmarks system which was very useful when reading through the documentation. Similarly to how one might use bookmarks in a web browser, I've also bookmarked a number of documents to read later, so that I don't forget. In addition to being useful for reading, I can also imagine it being useful if you often need to refer back to a specific file when programming, though registers (chapter 13), specifically File Registers (chapter 13.6), may be better suited to this.
Amusements (chapter 47)
The Amusements chapter covers a couple of really neat, mostly useless, tricks that you can do with Emacs. It lists a couple of built-in games, including classics such as Snake, Pong, and Tetris (turns out I'm horrible at that, by the way); text-based adventure games (
dunnet) and Conway's Game of Life simulation (
life); ways to convert a region into morse code or NATO phonetic alphabet (
nato-region to encode,
denato-region to decode); ways to play with the display when idling (
zone); and references to XKCD.
Glasses mode (chapter 26.9) and flipping tables
In addition to being able to encode a region as morse or the NATO phonetic alphabet, Emacs also comes with something known as glasses mode. This isn't actually an amusement and is originally supposed to help make
camelCased words easier to read by turning them into
snake_cased words instead (or using any other separator that you want). This is all just presentational, so even though Emacs might display the identifier as
my_Favorite_Identifier, it'll get saved as
myFavoriteIdentifier, and when you edit the text, the underlines aren't actually there for you to edit.
Because you can change the separator, you can also use glasses mode to separate your identifiers with an arbitrary text string. My coworker suggested the 'table flip', and sure enough, Emacs is happy to comply:
myFavoriteIdentifier = someOtherIdentifier
my(╯°□°）╯︵ ┻━┻Favorite(╯°□°）╯︵ ┻━┻Identifier = some(╯°□°）╯︵ ┻━┻Other(╯°□°）╯︵ ┻━┻Identifier
and for fun, here it is in morse
--/-.--/..-./.-/...-/---/.-./../-/./../-.././-./-/../..-./.././.-. -...- .../---/--/./---/-/...././.-./../-.././-./-/../..-./.././.-.
Debugging (chapter 27.6)
This is something I want to get into at a later stage, and the manual makes it seem rather impressive. I've not used a debugger at all since switching to Emacs, and while I usually manage just fine, I find myself longing for one every so often.
Compilation buffers and jumping to the next error (chapter 27.2)
Somewhat related to debugging is compiling your programs in your editor. While a lot of text editors have built-in terminals that you can run things in, I haven't often seen them also have the ability to jump to any errors that occurred during compilation, though I haven't actually gone looking. I am told, however, that this is fairly commonplace in applications known traditionally as IDEs. Emacs, eager not to disappoint, comes with support for this built in.
When using Emacs for compiling a program, it will usually open a compilation buffer. If you have compilation errors, you can then use one of a number of keyboard shortcuts (my favorite is `M-g n`) to jump to the next compilation error. The best part is: this works from any buffer, even one not in compilation mode. In other words, if you have errors, you can jump through them sequentially without ever going back to the compilation buffer.
Indentation and programming indentation (chapter 24 and chapter 26.3)
There's a number of cool indentation tricks listed in the indentation and the program indentation chapters, but I think the one I found that the most useful was for indenting languages derived from C. For a detailed explanation, check out this page on customizing indentation in C, C++, and Java, but the short version of it is that you can analyze the various syntactic parts of your program directly in your buffer, and then tell Emacs how it should indent a specific construct.
What about org mode? You'd think that that was one of the best parts of Emacs, and that I'd have a ton of tips to share, right? Well, you're probably right, but org mode comes with its own manual (another pretty massive text document), and I haven't made my way through that one yet. Trust me, though: it's on my list of must-reads this year. I'll get to it later.
So that's the first item on my SMART goal list completed. I'm not quite ready to start configuring Emacs from scratch, but it doesn't feel that daunting anymore. Now: do I go to work on Kubernetes, or do I spend some extra time with org mode to get really comfy with Emacs?
Seriously, if you're into Vim and haven't read it: I highly recommend you take the time to go through it. For a beginner it's an absolute gem, and even for experienced vimmers, I'm sure there's a good few tricks in there that you didn't know about.
I have actually found a grey hair in my beard this month (sshhh!) and I attribute that wholly to Emacs.