Start using Emacs now

Table of Contents

If you’re someone who writes text a lot everyday you’re probably using a word processor. If you develop software it may be an IDE or text editor. Some software in these categories that I can think of off the top of my head is:

I recommend you stop using whatever you are and start using Emacs. If you use Vim you should start using Emacs. If you use a distribution of Emacs, start configuring your own. Emacs is the best text editor ever and to not, at the very least, try it out is a massive disservice to yourself.

There’s the TL;DR for anyone who can’t concentrate for more than 5 seconds without a subway surfers video on the side. For the rest of us, here are some arguments in case you aren’t magically convinced by the previous paragraph.

Other editors are like cities, Emacs is like your garden

Any word processing software is designed around some common denominator. The keybindings, layout and overall aesthetic are engineered around some philosophy of the developers, which is enforced on the user. How much you get to change of that is based on the whims of the people who make that environment for you.

In that sense, IDEs are like cities. You can choose your way around it, whether that be arbitrarily long or as fast as possible, but at the end of the day you are limited by the people who designed the city. You can’t just walk through a house to get to another street; you have to walk around the block.

On the one hand that means everyone has the same experience as you so it’s relatively easy to get advice when something doesn’t seem right. On the other hand if something really annoys you, there may not be any way to fix that; you’ve just got to get used to it.

For the average use case that may be tolerable. However, if you’re spending hundreds of hours in the same environment you’ll want to introduce changes to better fit the way your mind works. Depending on the editor and the change in question, this can be really trivial or a major refactor of the source code with hundred of man hours required. So what do you do? Either learn to accept it or move on to greener pastures…

Emacs, in comparison, is designed from the ground up to be edited and mutated for your wants and needs. There is a single design decision which makes Emacs the most configurable experience imaginable: it is a Lisp interpreter first. Beyond some internal and core functions, written in the implementation language C, all of Emacs’ features and options come from Emacs Lisp code.

This erodes the distinction between the user and the developer that other software has. Core packages from the developer are indistinguishable from stuff written by the user: it’s all just code. Since core developer code is usually loaded into the runtime before user code, any user configuration will shadow and take precedence over the developers. So any functions you overwrite in your configuration will be the version that Emacs uses.

Using a metaphor, Emacs is closer to a personal garden. When you’re starting out it has the absolute essentials: fertile soil and some space. It may also have a few things that the people who owned it before you planted, some shrubs and flowers. But, because it’s your garden, you can uproot, plant and modify anything you want. By doing this over and over again this patch of land becomes your own personal space. You effectively gain an understanding of every component as you come to use it, throwing away that which you dislike and don’t need, cultivating the stuff that you like and planting new things you want.

Screw your metaphorical bullshit, give me some examples

Alright, that’s understandable. What follows is a tour over some stuff I like in Emacs, specifically the things that allow you to extend it to do what you want. Later on I give some snippets of code for more complex behaviour you may want from Emacs.

What’s this key do?

Every input in Emacs is a thinly veiled function call. Emacs, as a Lisp machine, is capable of inspection on any internals and code evaluated. The (describe-key) function asks you to input some key combination, then presents you with the documentation for the corresponding function. It’s bound to Ctrl+h k by default and you can even ask (describe-key) about itself (by doing Ctrl+h k Ctrl+h k).

The documentation includes stuff like:

  • what other keys are bound to this?
  • function signature
  • text documentation by the developer
  • link to the source code

With this you can quickly find documentation for what any input does.

Writing Lisp

With (describe-key) you can find out the function that a key is bound to. There’s actually a whole host of (describe-) functions, including (describe-function) (which (describe-key) uses internally to display the documentation of the function bound to a key). It’s bound to Ctrl+h f by default.

But how do you write Emacs Lisp? You can use the info pages (bound to Ctrl+h i), a set of manuals for most things in Emacs. There’s a manual on Lisp for non-programmers that should get you up to speed. Here’s a little primer for you.

Lists are Lisp’s main poison of choice, the thing it uses to express everything. All expressions in Lisp are either lists or atomic values. An atomic value is something that isn’t a list, like an integer or a string. Let’s see this in action:

(+ 2 3)

This expression adds the numbers 2 and 3 together. Note how + is at the start of the list, and the arguments (2 and 3) are after it, which is prefix notation. This is true for all function calls in Lisp: a list with the first member being the function name, followed by any arguments.

A benefit of this is that we can trivially write variadic functions. In fact, the mathematical operators are all variadic functions, so instead of writing (+ (+ 3 4) (+ 5 6)) we can just write (+ 3 4 5 6).

To define a function, we use the defun function. defun takes a name, an argument list then the body of the function. Let’s make a function which adds one to the argument given:

(defun add-one (x)
  (+ x 1))

To call this function, we use the same notation as for all other functions, (add-one 2).

Rebind anything

Now you know what’s bound to a key, how do you change it? Just call a Lisp function of course!

Say I want to bind Ctrl+r such that when I press it Emacs tells me the time1. Keys are bound to commands, functions that have (interactive) at the start of the body. The function has to tell us the current time when we call so we can’t just hard code the value. Something like this should work:

(defun tell-me-the-time ()
  (interactive)
  (message "%s" (format-time-string "%H:%M:%S")))

I used the documentation of format-time-string to write the format string in this example, and if you’re actually using Emacs at this point you can really easily look up documentation for the functions I’ve called.

How do I bind this to a key? There’s a few ways to do so in default Emacs, but the way I recommend is bind-key. Looking at the documentation, the signature for bind-key is:

(bind-key KEY-NAME COMMAND &optional KEYMAP PREDICATE)

&optional just indicates that the arguments after it are not required, so we can ignore KEYMAP and PREDICATE. From the documentation, KEY-NAME can be a “key vector” or a string representing the keys you want to bind. COMMAND is a reference to the command we want to bind to that key. So for our use case, the bind-key call would look like:

(bind-key "C-r" #'tell-me-the-time)

Emacs has its own notation for key bindings. It’s terse and allows one to easily communicate a key combination over text, certainly easier than writing out the spoken form. A quick summary of the syntax:

  • C-(something) means “Control+(something)”
  • M-(something) means “Alt+(something)” (pronounced Meta (something) for historic reasons from the era of dinosaurs)
  • C-M-(something) means “Control+Alt+(something)” (pronounced control meta something)
  • (a) (b) means perform (a) then (b). For example C-h k means input Control+h then k

That last rule means you can make arbitrarily long combinations. To encode, say, the keyboard combination of Ctrl+Alt+m then Alt+x then Control+y then finally Control+z, you’d write C-M-m M-x C-y C-z. The latter is terser than the natural language equivalent and is a valid string for use in bind-key.

Any key can be bound to a function. Anything you don’t like can be bound to something that works for you, using this simple format. It’s difficult to really understand how incredible this is till you try it yourself.

Install external packages

To install external packages you declare them via package-install. For example, if I wanted to get the 2048 game in Emacs, I could install it from Melpa like so:

(package-install '2048-game)

Oh yeah, you can play 2048 in Emacs. By default Emacs comes with Tetris and snake as well. All written in Lisp. These are relatively simple applications in the grander scheme of things: RSS readers, mail clients, fully featured git clients and an HTTP request package for JSON APIs are just some of the things you can install and use. Though Emacs isn’t super popular it’s had a lot of very smart and innovative people use it and make packages for it.

They all follow the same conventions you’d expect from Emacs as well: you can figure out what any function does via describe-function, any key bindings that these packages setup can be describe-key’d, and you can rebind any key in these applications through bind-key. You can run these systems in parallel i.e. have your RSS client up, reading a new article, while also playing tetris.

From this point we’re going to be looking at some interesting problems and Lisp code that allows you to solve them.

Automatically format code for C/C++ files

Whenever I’m in a C/C++ file I want to format it automatically using clang-format. Most editors would either support it through a custom extension or an in built option, but we’re going to write it ourselves. clang-format is an Emacs package that comes with clang by default, so as long as you have clang you can use it.

How do we figure out when Emacs is saving a C/C++ file? In event driven programming there is the notion of “hooks”, something which can have functions registered to it which run when an event occurs. Emacs’ hooks are very simple: each event usually has a variable named event-hook which is a list of functions when that event occurs. You can add a hook via add-hook. Looking through the documentation, there exists a before-save-hook variable. Perfect!

Here’s a function which checks the major-mode for C or C++ then does clang-format-buffer.

(defun clang-format-on-save ()
  (when (or (eq major-mode 'c-mode)
            (eq major-mode 'c++-mode))
    (clang-format-buffer)))

before-save-hook triggers on saving any file. We want to affect only C/C++ files, which is why we do the conditional check first. When Emacs is visiting a file, that file has a major mode activated in it. A major mode is how Emacs considers that file, such as a text file or a source code file. There are major-modes for essentially every type of file, including C and C++ files. major-mode is a variable which we can test against to ensure we’re only working on C/C++ files.

To register this to the before-save-hook, we just do the following:

(add-hook
 'before-save-hook
 #'clang-format-on-save)

Compile code when I save

Say I’m working on something that has a build step. I want to build whatever I’m working on when I make a change to a file. This can apply for writing some LaTeX or developing software. For the sake of an example, let’s say I’m working on my fork of DWM. It has a Makefile, so I can call make to build the project.

Like before, we want to register a function to some hook. We’d only want to compile after saving a file, hence we need to use after-save-hook. What are the conditions in which Emacs should build the project?:

  1. Be in a C file
  2. Be in the DWM source code directory

We already know how to check (1): (eq major-mode 'c-mode). The second one requires a bit more work. To get the current directory of the file we’re visiting we can use (file-name-directory buffer-file-name) which returns the directory as a string, where buffer-file-name is the current file name. We just need to check if this string is equivalent to the DWM source code directory, which we can use string= for.

Here’s the function:

(defun compile-dwm-on-save ()
  (when (and (eq major-mode 'c-mode)
             (string= "~/.local/src/dwm"
                      (file-name-directory buffer-file-name)))
    (compile "make")))

compile is a function for running some shell command in Emacs related to building some application. To register this function onto the hook, we do the same as before:

(add-hook
 'after-save-hook
 #'compile-dwm-on-save)

Message “Going to the next line” whenever I go to the next line

Whenever I go to the next-line, I want to use the message function to provide a log of the fact the editor is going to the next line. There are a couple of ways to do this:

  1. Define a function which logs then goes the next line, then replace any binding and function call to next-line with this new function
  2. “advise” the next-line to run some code after execution

Let’s do the latter. First let’s make a function that does the log I want.

(defun log-next-line ()
  (interactive)
  (message "Going to the next line..."))

How do I fit this into next-line? Through the bespoke “advice system” of Emacs:

(advice-add 'next-line :after #'log-next-line)

You can read this expression as “after the next line function has run, run the log-next-line function”. The :after is a positional, which I can replace with :before and :around to get log-next-line to run at different points of next-line’s execution.

Cool right? You can advise any function you want, which adds a whole layer of customisation. Can you think of another system, let alone a text editor, that can do something like that?

Customise for different machines

You may use Emacs on different machines. Sometimes you need configuration that is specific to a certain machine. How do you do that?

A quick look through documentation gives the (system-name) function, which returns a string representing the hostname of the machine. You can run conditionals on it to write system specific code!

Here’s an example where I set the colour of keywords for different machines.

(cond
 ((string= (system-name) "my-laptop")
  (set-face-attribute 'font-lock-keyword-face nil
                      '(:foreground "blue")))
 ((string= (system-name) "my-desktop")
  (set-face-attribute 'font-lock-keyword-face nil
                      :foreground "orange")))

Cond, standing for conditional, is just a Lisp form. Each element is a list, the first member being a test. If the test is successful, the code is executed. If not, it goes to the next test. So if (string= (system-name) "my-laptop") is true, then run the corresponding code.

The set-face-attribute function just sets certain attributes in how Emacs displays stuff. In this case we want to change the foreground attribute of the font-lock-keyword-face which you can consider a variable holding a value that Emacs uses to colour certain things.

Because everything is an expression in Lisp, we can put that cond inside of the set-face-attribute for a simpler looking expression:

(set-face-attribute
 'font-lock-keyword-face nil
 (list :foreground
   (cond
    ((string= (system-name) "my-laptop")
     "blue")
    ((string= (system-name) "my-desktop")
     "orange"))))

Vim in Emacs, or why Vim is irrelevant

I hate Emacs’ default keybindings. They’re awful and can literally cause RSI. I like Vim’s modal layout. But I don’t want to use Vim because it’s not Emacs. So what do I do?

There’s this external package called evil or the Emacs Vi Layer. It brings Vim’s modal system in all its glory to Emacs. I’m not kidding, the entire editor can just be ported over to Emacs.

There are other packages which port over stuff like evil-surround and evil-commentary using just Emacs alone.

With this, Emacs is an operating system with a good text editor.

Conclusion

I’ve provided some interesting arguments to try and use Emacs. Though it’s kinda oriented around programmers, Emacs is actually heavily used in academia and the writing industry; there are people with non technical backgrounds who use Emacs for writing documents. Can you think of another editor that has such a wide set of use cases?

I hope you try out Emacs. The default experience can be quite horrible, Emacs does look weird out of the box, and the learning curve is quite steep. But once you get past that, you’ll see how truly unique it is while being incredibly powerful.


  1. Bit arbitrary, I know, but it demonstrates the things I want from this example. ↩︎