An Emacs Survival Guide

I expect the learning curve with Emacs is a core reason why people tend to not use it with the same exhuberance with which other text editing software and IDEs are utilized. While it has become less common for modern developers to use classic editors like Emacs and Vim, Emacs has even less of a following than its "evil" rival. It really is a shame too, because Emacs is truly the classic workhorse in just about every possible way.

I won't lie, it took me a while to get on the Emacs train. Over the years, I've always had a general preferencee for simplicity over complexity. It's great to have a lot of nice features, but ultimately I'm looking for a simple tool to edit text. This is where apps like SublimeText, BBEdit and TextWrangler, Notepad++, Kedit, and similar really shine. The interfaces aren't bulky, you can edit text, and, well, what else do you really want? Maybe a little more.

When I'm progamming, it's definitely nice to have a linter. As much as I prefer statically-typed, compiled languages and I know a portion of the development process includes getting put in my place by the compiler, it's helpful to have a tool to catch errors during development. Similarly, when I'm writing research papers or blog posts, it's definitely nice to have a spell checker. It's not that I can't spell, but rather I type pretty fast and that's just naturally conducive to typos.

And, since my projects rarely consist of a single file, it's nice to have some sort of tool to manage the project as a whole. Searching within the project, version control tools, being able to quickly open and close a set of files, etc.

As it turns out, there are actually a lot of tools which offer value. And in fact, while there are many of these tools which are available out-of-the-box, the beauty of Emacs is that as a user, you have the ability to customize to your heart's content.

Managing the Learning Curve

While it is true that Emacs can be complicated, we also have the ability to get information in real time as we need it. Let's identify some basic functionality.

The most important command is going to be our trap door command, C-g which is how you cancel. Suppose you start opening a file and you see the find file interface in the mini-buffer, but you don't actually want to find the file – you just hit C-g.

ActionCommandLisp Function
Open a fileC-x C-ffind-file
Save a fileC-x C-ssave-buffer
Move to the beginning of the lineC-abeginning-of-visual-line
Move to the end of the lineC-eend-of-visual-line
Move down by paragraphC-vscroll-down-command
Undo ModificationC-/ or C-x uundo
Move up by paragraphM-vscroll-up-command
Quit EmacsC-x C-csave-buffers-kill-terminal

The first point to mention is the command notation. For example, if I want to open a file, I use C-x C-f which means to execute ctrl+x followed by ctrl+f. This is called a binding or key binding and means that we are associating the command sequence C-x C-f to a lisp function find-file.

Suppose we wanted to customize one of our key bindings; we can easily do this by writing a line of lisp code which we store in an initialization file. As an example, I tend to use the command to move backwards and forwards by a single word a great deal. Out of the box, this is bound to M-f for move forward by one word and M-b for move back by one word. However, given how I tend to hold my fingers over the keyboard (I actually re-map the caps lock to ctrl), I find these bindings rather uncomfortable. Additionally, as a Mac user, I have grown accustomed to using 'option' along with the left and right keys to accomplish this. I also tend to use Command along with the left and right keys to move to the beginning and end of the lines. I don't want to stop using C-a and C-e, but I do want to add some additional key bindings.

(global-set-key (kbd "s-<left>") 'beginning-of-visual-line)
(global-set-key (kbd "s-<right>") 'end-of-visual-line)
(global-set-key (kbd "M-<left>") 'backward-word)
(global-set-key (kbd "M-<right>") 'forward-word)

In order to reference the OSX "Command" key, we use s, so CMD with the left arrow key is expressed by s-<left>.

Using Emacs Packages

We've been discussing some of the most important and most helpful commands in Emacs for basic editing and use, but it's important to remember that Emacs has a rich history and a large community – there are a lot of packages which already do a lot of great things and customize and improve some of the standard commands.

Essentially, Emacs has these things called "modes" (majors and minors) and they are libraries of code which you can turn on or off. For example, when I'm working with a Julia file, I use julia-mode and julia-snail-mode. The previous handles things like syntax highlighting and Julia-specific code indenting. The latter is for running a Julia REPL process through a vterm and executing code. This means that I have a general workflow where I can have two or more windows where one or more are whatever files I'm actively working on and the other one is a Julia REPL. When I'm in a jl file, my distribution automatically turns on julia-mode and julia-snail-mode so I can execute C-c C-z to launch a REPL and then in my Julia file, I can execute C-c C-l to run a single line of code or I can mark a region, meaning highlighting a section of code, and use C-c C-r to execute the region.

I haven't read through the code. but what's probably happening is C-c C-l copies the current line from the jl file and inserts it into the REPL process followed by a newline to execute it. This is what makes Emacs so powerful – lots of simple solutions. There's something similar for Ruby projects, C projects, OCaml projects, Python projects, etc. Stuff to make the code look right, maybe handle builds or compiling. Then there are packages like magit which handle git-related things like creating branches, committing code, and much more.

Point is, there are lots of packages you can install which will make your Emacs distribution as robust as you like and you can pull it off without knowing much (if any) Lisp. But, since we're talking about getting up and running quickly, there are a couple of super helpful packages which I want to mention.

which-key

One of the most challenging aspects of getting comfortable with Emacs is remembering all of the key sequences and there can be a lot. Just working on my blog, I'm generally running at least four or five modes in each file with robust key sequences. This is where which-key comes in. Suppose you know to execute a line of code in julia-snail starts with C-c but you can't remember the next step or steps. As you hit C-c, the mini-buffer displays every command that starts with C-c and the remaining keys for those commands.

projectile

One of the main reasons people work with big, clunky IDEs is because they can easily maneuver around a project, meaning finding the files they're looking for, maybe grepping within a directory subtree, and ultimately working with a contained set of files. This what projectile is for. You can manually define what a project includes, but a .git initialized directory is all you need.

neotree

Another helpful component that most IDEs have is a nice tree-structure for a project, so you can see all of the files and access them quickly. neotree creates a side panel which contains a nice directory tree with the ability to toggle sub-directories opened or closed, open files quickly, and create and delete.

ivy, counsel, and swiper

Searching and auto-completion are also core functions of any well-tuned development environment. I use a combination of ivy, counsel, and swiper. Together these are a really powerful combination of tools in general, but as a point of note, Swiper solves a big problem. Out of the box, Emacs has separate forward and reverse searching. While there is something to be said on improved efficiency if you indeed know what you're looking for is above or below your current point, with most modern text editors there is a single find function and we get that from swiper.

I've actually taken it a step further with avy, but I wouldn't recommend including avy into your tools until you're more comfortable with Emacs.

use-package

use-package is something that will make your life a lot easier and keep your initialization files a lot cleaner once you really dive in. It's basically a macro for requiring packages. What is particularly nice about using it comes down to being able to handle key binds, config, and requirement deferring all in a nice, clean way.

I have a very little bit of initialization code in early-init.el and init.el, a collection of core "kernel" files, and then I house all of my includes as separate files or separate groupings of "modules" which all use use-package.

Customize As Little or As Much As You Want

Emacs does a lot out of the box and you don't need to be able to write or read Elisp to be productive with it. There are also some great pre-configured distributions available that combine a solid set of packages to get you up and running quickly such as Prelude or Galactic Emacs.

However, if you're willing to learn some Lisp and customize a little further according to your specific needs, you can really supercharge your workflow and have a lot of fun at the same time.