I feel like this post could be subtitled “For real this time”. Let’s just say that it’s certainly not my first time down an Emacs rabbit hole. I’ve used Spacemacs, then given up because I found it hard to maintain and fix small issues that arose. Then I moved to Doom Emacs, and liked it a lot. It was more compact and less monolithic than Spacemacs, but it still required more Emacs knowledge than I had at the time to understand how all the working parts fitted together. Then I went back to Neovim, and so the bouncing between Vim and Emacs cycle began again. This time, something struck me: what if I was approaching Emacs in the wrong way, trying to make it into something it isn’t, namely Vim? What if I actually took the time to learn how to do things the Emacs Way, and built up my configuration from scratch, adding only what I needed and understood? It was a crazy idea, but it might just work…
I remember bookmarking Huy Tran’s Emacs from Scratch post a while ago, and when this urge to start with a clean slate overtook me1, I dug it out. It’s a fantastic guide for taking the first steps, and gives you enough knowledge — and importantly, a nice enough starting point — to enable you to build on the basics. After that, I did what I have been meaning to do for a while and bought Mickey Petersen’s Mastering Emacs book. If you don’t have it already, and you use Emacs, I would highly recommend getting a copy. It takes you through the essentials (and some more advanced material), but more importantly, it educates you in the ‘Emacs Way’. He shows you how to find your own answers in Emacs’ extensive documentation, but also explains the way text structures work and the benefits of everything being a buffer. I don’t think that I had ever really grokked this before, and it made a big difference to the way that I look at solving tasks in Emacs.
The second milestone was trying to do without evil-mode. I started off adding this back in to my minimal configuration, but having read Mastering Emacs, it felt like a crutch in more than one way: it was helping me, but also making a lot of things in Emacs more awkward. So, I took a deep breath and got rid of it. As a support while I was thinking about how to avoid killing my fingers with all the Emacs keybindings, I used the general package to bind a prefix of
C-SPC and then set up keybindings underneath that, with
which-key description strings to build a ‘Spacemacs-like’ command menu. For example, to switch between projectile projects, I could hit my customised dedicated
C-SPC key on my Ergodox EZ keyboard, then
ps, and the command would be launched. After the initial prefix, each layer of keybindings (e.g. ‘p’ for project) shows a short description of the bound commands and their shortcut. This helped a great deal, and I will probably continue to expand and rearrange these menus. However, I missed the ability to use the Emacs default keybinding for setting a mark, which is
C-SPC, so I have moved to using
C-; as a prefix instead. I’ve revised my Ergodox keymapping to have a plain Ctrl key on the right hand thumb cluster (so the modifier keys are symmetrical on both halves), and moved the dedicated
C-; key to where the big
SPC is on the second layer. This is easy to reach, so gives me the best of both worlds. I’ve also set up one of the big vertical keys on the right hand half (next to the home row) to issue
M-x as I frequently launch (or search for) commands using this keybinding.
Structuring the configuration file
While I was learning how to build up the configuration, I used an
init.org file, exporting Lisp code in source blocks to an
init.el file using a command. This helped a lot in keeping things organised, and enabling me to write text explaining to myself why I had set things up the way I had, and keep a running todo list at the top to keep track of things to add or fix. This was all going well until I had added a lot of packages in a rather haphazard way, and ended up with startup times of 15 seconds or so. In searching for ways to optimise my configuration, I came across Joe Schafer’s Emacs configuration, which had a neat way of dividing the configuration into core files and module files, as well as some handy bits of code to speed up loading. I moved the pieces of my configuration over to this arrangement bit by bit, using
:defer t a lot in my
use-package blocks to defer loading a package until one of its commands is actually called. This has brought my startup time down to around 2-3 seconds, which is fine by me. I do like using an Org file to generate and document the parts though, so I’ll probably rework mine to generate the files from source blocks. Breaking the configuration up into modular parts and thinking about the function of each of these parts and the way they interact has been very helpful though, and saved some duplication in places.
What I’m using
When I used Spacemacs, I used to use Helm as an interface for choosing files, switching between buffers and so forth. It’s an incredibly powerful package, but — for that reason — a little overwhelming. This time around, I’ve switched to using the Ivy completion suite, and I am loving it. It doesn’t do quite as much as Helm, but it is plenty for me. It has quite a lot of tricks up its sleeves too. I recently had to make a whole host of changes to pages in this blog, updating old
http image links to
https to avoid Netlify generating errors when compiling the site. It was a tricky replacement task, as the targets were scattered across lots of different files, associated with different image types, and needing to be treated in different ways.
The way I tackled this was to use
counsel-projectile-rg (part of the Ivy suite) to search across all files within the project and find a subset of lines matching an image URL regular expression. I then used
ivy-occur to convert the found text into a buffer, making the buffer editable with the help of
wgrep. This buffer lists each item of matching text, along with some context around it, so it’s easy to see what kind of change you need to make. Finally, you can use whatever search and replace functions you want to make the changes, taking them bit by bit. When finished with the changes
wgrep-finish-edit writes all the changes to their respective files. It sounds like a complicated procedure, but it’s really not in practice. This probably saved me hours of grubbing around in files, or trying to construct one gigantic regex to deal with all eventualities. It shows the power of the Emacs approach quite well, I think.
Other than that, I haven’t tried to stack my configuration with too much, and have tried wherever possible to exploit Emacs’ considerable built-in capabilities. I’ve finally learned to use dired, eshell and ibuffer modes properly, and am finding them an enormous help. Alongside these, I’ve installed the always awesome Magit (of course), Flycheck for linting and syntax checking in lots of different modes, and window-purpose to help manage windows and layouts for an IDE-like feel. Together these tools feel very well integrated and coherent, and I have rarely felt the need to leave Emacs to get some component of a task done. It’s a bit like running a suite of tools under tmux, but where all the tools operate using coherent keybindings and communicate seamlessly with each other. Speaking of seamlessness, I used Tramp to edit a file on a server at work the other day, and I was blown away by how easy and natural it felt. If you set up dired in the right way, you can even open two instances of dired in neighbouring windows (one showing local files, one showing files on the Tramp-connected server) and copy files back and forth between them. It’s magic.
My writing needs are covered by Org mode (with
ox-pandoc to help me export via a familiar interface), Markdown mode, and Deft to manage little notes and snippets of information. I learned about mixed pitch mode, so I am now able to use a nice proportional font for the text blocks of Org mode files, while retaining a monospace font for the source blocks, tables and so on. This has really improved Org mode for me. My programming needs are met by ESS for R, and anaconda-mode for Python (both using Flycheck and Auto-Complete seamlessly). I’ve taken my time to configure these how I want them, and this time around I’ve managed to solve all the niggling issues I had with them last time. I think this is because I’ve got a much simpler system, and because I am learning much more about how Emacs works.
Out of all of the Emacs distributions I have used, I loved Doom Emacs best for
its appearance. Both the themes and the modeline are really gorgeous, which —
while seemingly a trivial point — I have found is quite important for me to
enjoy using Emacs. Thankfully both the themes and the modeline are available as
separate packages, so I’ve been using them. I’m using the Nord dark and light
themes, which are restful but very clear and readable. I wanted to be able to
switch smoothly between dark and light themes without leaving artefacts from the
last theme. I discovered that this happens because Emacs just layers a new theme
on top of an old one, so you need to reset everything before applying a new
theme. I considered learning how to do this until I found a little package
called Heaven and hell, which does just that very capably. I’ve bound
toggle between dark and light themes, and they switch very cleanly, modeline and
Bringing back modality
Finally, I was missing some kind of modality for repetitive editing of text, moving around files and so on. I knew that I didn’t want to go back to Evil mode because it does feel alien in Emacs. I tried out a number of different modal packages: fingers.el is flexible and clever, and enables most of the marking, editing and movement commands you could want. However, I found it hard to learn for some reason. Similarly, xah-fly-keys is fantastic, and puts the most commonly used commands in a sensible arrangement on the home row and surrounding keys. Again, I found it too much of a challenge to learn yet another set of commands for doing the most common things.
What I settled on was the amusingly named god-mode. Hit a keybinding to toggle the mode, and it effectively holds down the
Ctrl modifier for you, and lets you hit
g to stand in for
C-M. This means that a string of commands that would result in finger gymnastics (even on an ergonomic keyboard) can be achieved more quickly with single keys. You can also repeat a command by setting up a binding for it (I use the suggested ‘.’). So jumping around text by word or line and deleting words ends up being a sequence like
a gf...4d e. I’ve used
key-chord to bind
jk pressed together to toggle it on and off, so it is quick to activate and deactivate. I’ve also just managed to write a couple of functions to change the background colour of the modeline to something bright (a different colour depending on whether it is a dark or light theme) so that I can easily tell when I am in god-mode. I love it as it makes complicated sequences of commands effortless. It’s not as elegant as Vim’s composeable editing commands, but it is still very functional. Better still, you are not having to learn different keybindings for the modal mode and ordinary ‘insert mode’ editing, as they are the same: you just omit the modifier key in god-mode.
I’m really happy with my Emacs setup now. I know I’ve been here before, but having built my configuration myself, sorted out niggling problems and learned much more about how Emacs works, it feels more sustainable this time. I’m able to do most of my writing and coding tasks entirely within Emacs (including interacting with git, creating, moving and renaming files), and it feels very comfortable and efficient. I still want to adjust my Org mode set up a bit, set up some more capture templates and so on, but I am happy to take that gradually. It has certainly been a fun process.
- Honestly, I think it’s like a migratory urge or something. I can almost hear Sir David Attenborough explaining it in hushed tones over a swelling orchestral score: “And so, as text editor bankruptcy sets in, the weary geek must depart on an epic and arduous journey to find a window into which she can type text more efficiently.” ↩