Towards a Vim-like Emacs

Contents

I’ve previously written about my own process of transitioning from Vim to Emacs. It’s fairly high-level, however, and doesn’t cover the nitty-gritty: all those long, painful hours spent trying to smash Emacs into reasonable keybindings are lost. You get the retrospective, the analysis, but not the same benefit of hindsight I’ve gathered since I switched. Unfortunately, there aren’t many resources out there on how to do this right. People use Emacs. It’s a tool. Most of its users don’t write about it, and the percentage of Emacs users who try to emulate Vim and also write about it is even smaller.

There is Bling, the vim-airline developer, who switched and ultimately convinced me to give Emacs a shot. But his tips just scratch the surface of what’s necessary to replicate the finger-friendliness of a modern Vim workflow.

It’s a well-known and overstated joke that the default Emacs bindings are bad. If you’re reading this post, you probably already agree with me here, but for the uninitiated: key combos are the devil. Any time you are pressing two keys at once, with the same hand, hundreds of times per day, you are setting yourself up for repetitive stress injury. As programmers, we need to take care of our hands or our careers will be over.

This is going to be part-tutorial, part describing my configuration. With a little determination, this can take you from ground-zero to a working Evil configuration and generic development environment.

This post is geared at the determined Vim user who is willing to give Evil a shot and likes having a heavily customized editor. It has a number of tasks that are intended to teach the right attitude and mindset required to keep working with Emacs on your own. These will get you familiar enough with reading documentation that you know where to look when you want to do something. It is also Elisp-focused, with no emphasis on the more modern customization features of Emacs that ultimately prevent new users from groking its internals.

First, some terminology

When you first fire up Emacs, you need to learn how they reference certain objects and keybindings. This is pretty simple, but can be confusing if you don’t have the initial introduction.

That’s it for the basics. Let’s see where we can go from here.

Package archives

In order to install packages from things besides the default repos, you need to define a variable called package-archives with the URLs of the package sources in it. You do this in your init.el file, which is located at ~/.emacs.d/init.el by default.

(setq package-archives '(("melpa" . "http://melpa.milkbox.net/packages/")
                         ("org" . "http://orgmode.org/elpa/")
                         ("gnu" . "http://elpa.gnu.org/packages/")))

MELPA is the most important source for up-to-date Emacs packages. It’s kind of like the Arch Linux of Emacs package archives - it builds directly from upstream all the time, and it works with the builtin Emacs package manager.

Also, below the above code, you’ll need to initialize the package manager.

(require 'package)
(package-initialize)

Once you’ve added the above to that file, you can evaluate each of these expressions inside Emacs with C-x C-e. To evaluate an expression, position the cursor outside and following the expression and hit that keybinding. This runs the command eval-last-sexp, which evaluates the symbolic expression before your cursor and pretty-prints the output.

You’ll need to do this in order (i.e., evaluate the setq expression first), or it won’t work.

Installing Evil

Once the above is finished, you can install evil-mode with M-x package-install <RET> evil <RET>. The compilation log that pops up at the bottom of the screen can be killed with C-x 4 0. That runs the function kill-buffer-and-window, which you can also call interactively at the M-x prompt. More on that later.

After that, Evil will be installed into the ~/.emacs.d directory. To enable it, type M-x evil-mode. Now all your Vim bindings work, as long as you don’t kill Emacs.

You probably want to enable Evil more permanently. Add the following to the bottom of your ~/.emacs.d/init.el file:

(require 'evil)
(evil-mode 1)

This will automatically enable evil-mode every time you start Emacs. It’s important that it goes at the bottom of the file. Evil relies on starting up after the rest of your packages, so that it can detect them and overlay its keybindings appropriately.

If you break your configuration, restart Emacs with:

$ emacs --debug-init

to get debug information on your init files. Don’t feel bad if you have to use Vim to fix them in the meantime. Don’t get worried thinking Evil is not a first-class citizen in Emacs: this is an editor built to be ripped to pieces by the competent user.

The interesting part of Emacs is its Lisp engine. It’s the scores of reusable functions for automating your interaction with code. Keybindings are just one way of calling these things.

Modes

Like Vim, Emacs uses the word modes to refer to an element of state in its editor. Unlike Vim, this is not referring to modal editing, but rather to the composition of various modules that make up your current editing environment.

A major mode defines your primary interaction with a buffer in Emacs. There can only be one of these active at once, and they are not all necessarily for editing text. For example, dired is a major mode for editing directories, and magit is a Git interaction interface. An important major mode to be aware of is fundamental mode, which is a major mode with no discerning features besides the ability to type text into a buffer.

Minor modes are compositional - there can be more than one of them, and minor modes loaded after others can override the settings of a previous one. Evil is one such example of a minor mode.

States

Evil uses the term state to refer to what Vim calls a mode. There are more states than these, but here are a few to get you going:

  • evil-emacs-state1
  • evil-insert-state
  • evil-normal-state
  • evil-visual-state

Each of these can be called interactively with M-x to enable them. The way Evil works is each of these states is bound to a different keymap, and those keymaps change the meanings of your keys to call different functions when they are pressed. This affords you the ability to remap bindings across different states, where they will only work when evil-mode is enabled and Evil is also in the right state to activate the keymap.

Use ESC, i, v, etc. as you would in Vim to switch between Evil states. Then play around with using M-x to toggle the different states before moving on.

Binding keys

Let’s get started by adding some bindings to Evil. We want switching between windows to be easy, so we can bind the following:

(define-key evil-normal-state-map (kbd "C-h") 'evil-window-left)
(define-key evil-normal-state-map (kbd "C-j") 'evil-window-down)
(define-key evil-normal-state-map (kbd "C-k") 'evil-window-up)
(define-key evil-normal-state-map (kbd "C-l") 'evil-window-right)

This binds <CTRL>-hjkl to window movement commands when Evil is in normal state.

There are a number of interesting things about these expressions. First, position your cursor over the word define-key and call M-x describe-function. It will provide the default value of the thing under your cursor, so you can just press RET again to bring up a buffer with help information. Read the help information it gives you, then move on. The buffer that appears will be in help-mode, which does not have Evil bindings, but you can use q to close it and keep working.

The proper term in Emacs for your cursor would be point. This is used extensively in the help documentation, so it’s worth remembering. The thing at point that provided the default argument for describe-function was a symbol.2 A symbol is basically any thing in Emacs Lisp which has a name and can be hashed into a lookup table, where it then becomes an object in Lisp. These objects could be anything: functions, data, or text, for example, but symbols are interesting because we can give them names and refer to them later somehow.

From the official manual:

You can test whether an arbitrary Lisp object is a symbol with symbolp:

— Function: symbolp object

This function returns t if object is a symbol, nil otherwise.

Now, use M-x apropos RET point RET and skim through the list that pops up. If you have Evil working properly, you can use :q to close that window when you’re done with it.

Quoting

Readers with keen eyes may have noticed that one of the arguments in the above code has an apostrophe (') before it. This is because evil-window-left is a function’s name, and we want to be able to call it later by binding it to a key. Putting an apostrophe before it when passing it as an argument to a function means we’re passing the quoted form of evil-window-left to define-key, not what it evaluates to.

Since our intent is to pass the symbol 'evil-window-left into define-key, and not the evaluated form of evil-window-left itself, this is the right thing to do.

All arguments in Elisp expressions, without quoting, will be evaluated before they are passed into a function call. Quoting lets us avoid that and pass their symbols instead.

Maps and keys

The two other arguments to each of those keybindings were unquoted. The keymap, evil-normal-state-map, goes directly into the function, since the purpose of define-key is to modify that map. The expression (kbd "C-h") is actually another separate function call that happens before the outside expression is evaluated. If we use M-x describe-function to look at the help documentation for kbd, we see:

kbd is a compiled Lisp function in `subr.el'.

(kbd KEYS)

Convert KEYS to the internal Emacs key representation.
KEYS should be a string constant in the format used for
saving keyboard macros (see `edmacro-mode').

We need to use the kbd function to describe our keybindings, since they contain an extra operator (the <CTRL> key). While single character bindings can be looked up in keymaps directly, a key sequence like C-h is not stored in the map in that form.

You can look at the value of (kbd "C-h") by typing it on a line below those bindings, and then evaluating it with C-x C-e as before. In the minibuffer, the text area with a blank line at the bottom of the screen, "^H" is displayed. That tells you that the expression

(define-key evil-normal-state-map (kbd "C-h") 'evil-window-left)

is internally binding "^H" to evil-window-left, but don’t doing that yourself—the way it’s shown in the minibuffer is still a displayed form, which is different from the hashed value it eventually becomes.

Lisp navigation

Accessing help documentation using M-x describe-function is pretty awesome, but the interface for doing it is fairly clunky. We can make it better using elisp-sime-nav-mode, the superior Lisp interaction mode for Emacs. You can install it with M-x package-install RET elisp-slime-nav.

Slime mode needs to be enabled for it to be used. To do this, we will define a function that we’ll tie to the hook for emacs-lisp-mode. A hook is a function that gets evaluated when something predefined happens in your editor. Most modes have hooks already configured, and all you will need to do is add functions to call with them using add-hook for them to become useful.

First we require the package elisp-slime-nav, which ensures that it is loaded when Emacs starts:

(require 'elisp-slime-nav)

Then we define our function:3

(defun my-lisp-hook ()
  (elisp-slime-nav-mode)
  (turn-on-eldoc-mode)
  )

Add that into your init file after the require call. Note that the function definition is prefixed by my-. While not all Emacs packages do this, Elisp does not have namespaces like Python or Ruby does. To counteract this, convention is to define all of your functions prefixed by your package name, and for personal code using my- is not uncommon.

Then, we add it to to the emacs-lisp-mode-hook using add-hook:

(add-hook 'emacs-lisp-mode-hook 'my-lisp-hook)

This makes elisp-slime-nav-mode and turn-on-eldoc-mode4 get called every time emacs-lisp-mode is enabled. Now go ahead and evaluate these with C-x C-e. To make this easier, you can surround the block in a (progn), which makes the whole thing get treated as one big expression for evaluation:

(progn
  (require 'elisp-slime-nav)
  (defun my-lisp-hook ()
    (elisp-slime-nav-mode)
    (turn-on-eldoc-mode)
    )
  (add-hook 'emacs-lisp-mode-hook 'my-lisp-hook)
)

While the (progn) here doesn’t serve any practical purpose, it might help you group blocks of code for evaluation while you’re hacking at them.

Since emacs-lisp-mode is already running (you’re in a .el file), you can force your hook’s evaluation by typing (my-lisp-hook) into the buffer and evaluating it manually.

You’ll notice that when you hover over functions now, eldoc-mode shows their signature in the minibuffer. If you want to see the help information like we’d been doing manually before, though, you still need to type describe-function into the M-x prompt. Now that we have Slime, we can simplify this with another keybinding:5

(evil-define-key 'normal emacs-lisp-mode-map (kbd "K")
  'elisp-slime-nav-describe-elisp-thing-at-point)

Evaluating the above will do contextual lookup on the thing at point whenever you press K in Evil’s normal state.

The syntax here is different from when we defined the window movement bindings earlier. This is because we want to define K to call elisp-slime-nav-describe-elisp-thing-at-point only when we are in emacs-lisp-mode-map and Evil is in normal state. The evil-define-key function lets us do this, by providing arguments for both the Evil state and the keymap for the binding to be active in.

Now you have the tools necessary to explore Emacs Lisp code without getting lost. Doing documentation lookups on everything you see that you don’t understand is a great way to start familiarizing yourself with Elisp code.

Before we move on, lookup the descriptions for progn, require, add-hook, and emacs-lisp-mode-hook and read them. Don’t be afraid if you encounter words you don’t understand. Seeing the bigger picture in all the lingo takes time, but just doing this will help you start to understand it.

Managing buffers

You can list the buffers that are currently open by typing M-x list-buffers. Using the bindings we defined earlier, you can switch to the window that is opened and hit q to close it when you’re done. To switch to one of these buffers, typing M-x switch-to-buffer will bring up a minibuffer prompt where you can type the name of a buffer to switch to it.

For a better listing, you can use M-x ibuffer.

IBuffer with the default settings

The default bindings you should care about right now are:

IBuffer has all sorts of useful features for browsing, filtering, and editing open buffers. But at least for a Vim user, its keybindings won’t at all be intuitive. Typing j accidentally will call jump-to-buffer, which is almost certainly not what you want. If you felt like typing the name of the buffer at a prompt, you probably wouldn’t have opened IBuffer to begin with!

Aside from being unnatural for Vim users, the interface to IBuffer isn’t actually that bad. The keybindings are mostly single-key sequences, unlike more poorly-designed Emacs modes, and the functions allow for quick actions that will save you tons of work.

Stealing IBuffer’s keymap

When I previously wrote about my experience switching to Evil, I mentioned there are a couple of different ways to deal with major mode keymaps being inconsistent with Evil. I’ll be covering the full remapping approach here, since it has a few benefits:

  • Your major modes will be more tightly integrated with Evil.
  • You’ll have the ability to redefine keys at will, easily and quickly.
  • Remapping keys this way offers a chance at better understanding the functions in a major mode, which might just be missed otherwise. For core components of Emacs, like IBuffer and dired, building a more useful keymap can be a rewarding learning experience in itself.

With ibuffer open, type M-x describe-mode to pull up the help info below.

A link to ibuffer.el in help-mode

Following that link6 will take you to the source code for IBuffer. Somewhere in there, you’ll find the keymap:

Default IBuffer keymap

Any one of these major mode keymaps is bound to be really large, so I won’t reproduce it here. The idea is to redefine these into a map within Evil, so IBuffer will respect your Evil keymaps and still have its functionality. The evil-define-key function we used earlier has the option of taking an unlimited number of arguments. Now, copy lines like the following out of ibuffer.el:

(define-key map (kbd "m") 'ibuffer-mark-forward)
(define-key map (kbd "t") 'ibuffer-toggle-marks)
(define-key map (kbd "u") 'ibuffer-unmark-forward)
(define-key map (kbd "=") 'ibuffer-diff-with-file)
(define-key map (kbd "j") 'ibuffer-jump-to-buffer)
(define-key map (kbd "M-g") 'ibuffer-jump-to-buffer)
(define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch)
(define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp)
;; ...

and drop them into ~/.emacs.d/init.el, after (require 'evil), like follows:

(evil-define-key 'normal ibuffer-mode-map
  (kbd "m") 'ibuffer-mark-forward
  (kbd "t") 'ibuffer-toggle-marks
  (kbd "u") 'ibuffer-unmark-forward
  (kbd "=") 'ibuffer-diff-with-file
  (kbd "j") 'ibuffer-jump-to-buffer
  (kbd "M-g") 'ibuffer-jump-to-buffer
  (kbd "M-s a C-s") 'ibuffer-do-isearch
  (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp
  ;; ...
  )

I used a Vim macro and visual block selection to do the rewrite into evil-define-key form for me, and it only took about a minute to perform.

To ensure IBuffer will use Evil’s keybindings, add the line

(evil-set-initial-state 'ibuffer-mode 'normal)

to your init file. You can use this to set Evil’s initial state for any major mode - before you know what to bind in a mode, sometimes using Emacs state isn’t a bad idea.

Now, if you try to actually use this configuration, it won’t work.7 The reason is we need to ensure the Evil bindings are not applied until after IBuffer is loaded, since it needs to do some special setup. The solution here is to surround the bindings in an eval-after-load block, like follows:

(eval-after-load 'ibuffer
  '(progn
     (evil-set-initial-state 'ibuffer-mode 'normal)
     (evil-define-key 'normal ibuffer-mode-map
       (kbd "m") 'ibuffer-mark-forward
       (kbd "t") 'ibuffer-toggle-marks
       (kbd "u") 'ibuffer-unmark-forward
       (kbd "=") 'ibuffer-diff-with-file
       (kbd "j") 'ibuffer-jump-to-buffer
       (kbd "M-g") 'ibuffer-jump-to-buffer
       (kbd "M-s a C-s") 'ibuffer-do-isearch
       (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp
       ;; ...
       )
     )
   )

This ensures your custom keymap does not try to set itself until after ibuffer has already initialized it properly.

Your goal after this section is to read the help information for eval-after-load, as well as for some of the IBuffer bindings. Just pick ones that seem interesting, and again - don’t worry if you don’t understand things. Just read a few of them anyway.

Once you’ve done your reading, get the custom keymap to work by evaluating the block with C-x C-e, and ensure it’s functional in evil-normal-state by calling M-x evil-normal-state manually within IBuffer.

Rebinding

You might think it’s crazy to place all of this configuration in one lone init file. We’ll get to that in the next section. For now, keeping things in init.el will get the job done and let us focus on keybindings.

The obvious thing to do, now that we’ve copied the keymap, is to add proper hjkl bindings. Usually in major modes like this you want to bind j and k to evil-next-line and evil-previous-line, respectively.

  • Since J wasn’t taken, I changed ibuffer-jump-to-buffer to J and rebound j to evil-next-line.
  • The binding for k is less obvious: it’s tied to ibuffer-do-kill-lines.

Looking at the help documentation:

ibuffer-do-kill-lines is an interactive autoloaded compiled Lisp function in ibuf-ext.el.

(ibuffer-do-kill-lines)

Hide all of the currently marked lines.

IBuffer has a marking system that lets you select multiple buffers on which to perform actions. Personally, I don’t care very much for hiding marked lines, so I simply removed that binding. Now we have

    (kbd "j") 'evil-next-line
    (kbd "k") 'evil-previous-line

bound, which covers the absolute basics. But what about l? I’m used to ranger, a Vim-inspired file manager, where l takes you into the current item. In IBuffer, l is bound to ibuffer-redisplay, a useless function that redisplays the current buffers without loading new ones.8 Deleting that line lets us rebind it to

    (kbd "l") 'ibuffer-visit-buffer

and now we can navigate IBuffer much more naturally.

Another Ranger replication: by default, ibuffer-toggle-marks is bound to t, and v is bound to ibuffer-do-view, which opens the buffer at point fullscreen and hides the others. I never need to do that, so I’ve added

    (kbd "v") 'ibuffer-toggle-marks

to my config.

I’ll add that it’s not really necessary to duplicate the entire keymap in your init file. As you’d guess, you only need to explicitly define keys in Evil if:

  • Evil would overwrite them otherwise, replacing them with something useless
  • You need to change them

If neither of these apply, then you can get rid of the bindings. But pasting them in to start with, then trimming the bindings down to what you’re actually interested in gives you the chance to examine the default keymap and rebind things that sound useful.

Handling lots of buffers

Over time, when you use Emacs you’ll end up with a lot of garbage buffers. Tons of different commands will open scratch buffers to show you things and never kill them. Eventually you’ll need to learn to filter IBuffer’s output so it’s actually relevant to you, and quickly group and delete buffers that aren’t.

Typing / in the IBuffer window starts a filter command. I’ll list the default filter commands here, but remember that you can rebind them.

key action
/ n Filter by name
/ e Filter by extension
/ f Filter by filename
/ s Save filters
/ ! Negate filter
/ g Make filters into group
/ S Save filter groups
/ r Switch to saved filters
/ R Switch to saved filter group

Separating your init files

As I said before, putting everything in one init file gets old after a while. Emacs has a variable called load-path that you can use to customize where it looks for files. This is similar to the $PATH variable in most UNIX-derived shells.

Adding the following to the beginning of your ~/.emacs.d/init.el file will make Elisp files in the directory ~/.emacs.d/config available for loading:

(add-to-list 'load-path (concat user-emacs-directory "config"))

If you use K in Evil’s normal state to look up the definition of concat, you’ll see:

(concat &rest SEQUENCES)

Concatenate all the arguments and make the result a string. The result is a string whose elements are the elements of all the arguments.

Since this won’t be the last time you see it, I suggest reading the docs for add-to-list as well.

You can use M-x describe-variable to see the definition of user-emacs-directory or load-path. It will also tell you the variable’s value. Hitting K with the symbol at point will also take you to this, but it’s good to do it the hard way at least once.

Now you can create a file, ~/.emacs.d/config/my-ibuffer.el, and move your IBuffer configuration over there. It won’t be loadable by default, though, unless you declare it at the bottom of the file:

;; code goes here

(provide 'my-ibuffer)

Then, in ~/.emacs.d/init.el, you’ll need to require the file, as we did with Evil and Slime, for it to be loaded automatically.

(require 'my-ibuffer)

Now your IBuffer settings will be loaded at startup, but they won’t clutter your main init file.

Dired

Dired is one of Emacs’ killer apps - a full-featured file manager built in to the editor. No package installation necessary. But the default bindings in Evil get some core things wrong, and not just in respect to my Vim-like preferences.

Dired is very good about using single-key bindings for the most important things. Changing them to be better is easy: you just have to know what functions to bind.

First, opening a subdirectory in Dired spawns a new Dired buffer. The sane action, dired-find-alternate-file, is locked behind a feature gate that will prompt you the first time you use it. I rebound l to dired-find-alternate-file, which means that moving forward into a new Dired buffer happens in the same buffer (or window) as the current one. This does wonders in not cluttering up my buffer list with dead Dired exploration.

Repeating the steps used to build a new keymap for IBuffer, we can hack apart the Dired maps similarily so.

  (evil-define-key 'normal dired-mode-map "h" 'dired-up-directory)
  (evil-define-key 'normal dired-mode-map "l" 'dired-find-alternate-file)
  (evil-define-key 'normal dired-mode-map "o" 'dired-sort-toggle-or-edit)
  (evil-define-key 'normal dired-mode-map "v" 'dired-toggle-marks)
  (evil-define-key 'normal dired-mode-map "m" 'dired-mark)
  (evil-define-key 'normal dired-mode-map "u" 'dired-unmark)
  (evil-define-key 'normal dired-mode-map "U" 'dired-unmark-all-marks)
  (evil-define-key 'normal dired-mode-map "c" 'dired-create-directory)
  (evil-define-key 'normal dired-mode-map "n" 'evil-search-next)
  (evil-define-key 'normal dired-mode-map "N" 'evil-search-previous)
  (evil-define-key 'normal dired-mode-map "q" 'kill-this-buffer)

You’ll notice the mark toggling is rebound to v here as well, which gives me a somewhat consistent interface between ranger, Dired, and IBuffer.

Rebinding n is another important thing here. By default, n and p are used for navigation within Dired, but with hjkl bindings set that’s not really useful. Changing n and N to Evil’s search commands gives us Vim-like searching within the file manager.

Another thing to note about the above code is that I’ve made each binding an explicit expression. This is useful when you’re just testing new keybindings - if you might want to change them and play around until you find something that works, you want to be able to evaluate each expression independently. If we feel like evaluating these all at the same time, we can just surround them in a (progn) block, or visual select the code and use M-x eval-region to do so.

One problem with this config is that while l will use dired-find-alternate-file, h will keep the old Dired buffers around. To fix this, we need to write a function that will jump up one directory, and close the old Dired buffer.

(defun my-dired-up-directory ()
  "Take dired up one directory, but behave like dired-find-alternate-file"
  (interactive)
  (let ((old (current-buffer)))
    (dired-up-directory)
    (kill-buffer old)
    ))

Rebinding h to our new function makes buffer navigation behave much closer to other Vim-like file browsers.

(evil-define-key 'normal dired-mode-map "h" 'my-dired-up-directory)

Dired-x

Many incredibly useful Dired features are disabled by default, like dired-jump, which jumps to a Dired buffer in the same place as the current file.

Adding the following to your init file will enable these advanced features, making Dired a much nicer environment to work in:

(require 'dired-x)

Some of my Dired-related keybindings, like dired-jump below, require dired-x loaded to work.

Evil-Leader

Evil-Leader lets you define a leader key within Evil. I use , as my Evil leader key, where \ is reserved as the leader key for Emacs (per Bling’s Emacs as my <Leader> post series). As usual, M-x package-install RET evil-leader will install this for you.

You should require Evil-Leader and run (global-evil-leader-mode) before Evil is loaded, or otherwise it won’t work in buffers like *scratch* and *messages*.

The first obvious thing to do is to bind w and q to save and quit functions, as many people do in Vim:

(evil-leader/set-leader ",")
(evil-leader/set-key "w" 'save-buffer)
(evil-leader/set-key "q" 'kill-buffer-and-window)

Some other useful Evil-Leader bindings that work with all the packages we’ve seen so far:

(evil-leader/set-key "h" 'dired-jump)
(evil-leader/set-key "v" 'split-window-right)
(evil-leader/set-key "e" 'pp-eval-last-sexp)
(evil-leader/set-key "," 'other-window)
(evil-leader/set-key "b" 'ibuffer)
(evil-leader/set-key "x" 'helm-M-x)

With these set, we can eliminate two-key combos in most of our daily editing tasks.

Use-package

As you start collecting Emacs plugins, your startup times will begin to grow. In addition, your ability to deploy on multiple machines (which may not have those plugins installed) and handle dependencies properly will decrease significantly over time.

Use-package lets you avoid that problem by automating the bad parts of configuring a package, and establishing deferred bindings so that you can evaluate code after a given package is loaded, and trigger a package loading on the evaluation of arbitrary commands or opening of arbitrary filetypes.

With it, the top section of my init file looks like this:

(require 'package)
(package-initialize)
(setq package-enable-at-startup nil)

(add-to-list 'load-path (concat user-emacs-directory "config"))
(setq package-archives '(("melpa" . "http://melpa.milkbox.net/packages/")
                         ("org" . "http://orgmode.org/elpa/")
                         ("gnu" . "http://elpa.gnu.org/packages/")))

(unless (package-installed-p 'use-package)
    (package-refresh-contents)
    (package-install 'use-package))
(require 'use-package)

The effect of this is that it automatically downloads and installs use-package from MELPA if it isn’t already present. Then you can use :ensure within a use-package declaration to do the same for packages you would normally install manually.

(use-package evil-leader
      :commands (evil-leader-mode)
      :ensure evil-leader
      :demand evil-leader
      :init
      (global-evil-leader-mode)
      :config
      (progn
        (evil-leader/set-leader ",")
        ;; bindings from earlier
        )
      )

There’s pretty detailed help in the README on GitHub, but I’ll summarize some of it here:

argument meaning
:ensure Automatically fetch and install the package if it is not already installed.
:mode Defer the loading until a given file extension is found.
:commands Define the given commands, but don’t load the package until they are called.
:init Command to be executed immediatley when the expression is found.
:config Commands to be executed after the package is loaded.

The colons are necessary because these are optional, named arguments to an Elisp expression. You could use use-package with nothing but the first argument, although that wouldn’t be very different from using require.

Also note that you generally want :init and :config to be wrapped in a (progn), since they only take one command normally.

Your task for this section is to go get the previous code into Use-Package.

Daemonizing Emacs

I use the following systemd unit to start an Emacs daemon when my machine boots:

[Unit]
Description=Emacs daemon

[Service]
Type=forking
WorkingDirectory=%h
ExecStart=/usr/bin/emacs --daemon
Restart=no

[Install]
WantedBy=console.target

Then you can make a simple script like

#!/bin/sh
/usr/bin/emacsclient -c $@

And use that to spawn Emacs. It will just attach itself to the server process, allowing for instant startup.

Non-systemd users can still use emacs --daemon in an init script somewhere for the same effect.

Magit

I’ve talked about Magit before. It’s the only Git interface I’ve ever liked for doing actual work, and I found it 3 years after I started using Git.

Giving it proper jk bindings is simple:

(use-package magit
  :ensure magit
  :config
  (progn
    (evil-set-initial-state 'magit-mode 'normal)
    (evil-set-initial-state 'magit-status-mode 'normal)
    (evil-set-initial-state 'magit-diff-mode 'normal)
    (evil-set-initial-state 'magit-log-mode 'normal)
    (evil-define-key 'normal magit-mode-map
        "j" 'magit-goto-next-section
        "k" 'magit-goto-previous-section)
    (evil-define-key 'normal magit-log-mode-map
        "j" 'magit-goto-next-section
        "k" 'magit-goto-previous-section)
    (evil-define-key 'normal magit-diff-mode-map
        "j" 'magit-goto-next-section
        "k" 'magit-goto-previous-section)))

Tips and tricks

Avoid using customize

Easy customization is a feature where Emacs autogenerates lisp code for you, then places that in a specific file with your graphical customizations.

Since this breaks customizing Emacs programmatically, I recommend avoiding it in most cases. It’s better to use Customize to browse for useful settings and copy the generated code into your real init files, that way you’re free to modify it.

Ditch the terminal

It’s a little-known fact among hardcore tmux users that window managers serve a useful purpose besides displaying a web browser. That was how I felt, at least. I used Vim inside the shell, since the graphical version was annoying: it had a different font, clunky menus, and I couldn’t use tmux’s copy-paste functions to move text around.

If you’re moving to Emacs full-time, be prepared to change that mindset. Emacs is better to use in a graphical window. It will actually play nicely with your graphical environment.

Typing M-x new-frame opens a new window (in your window manager, not Emacs) that is attached to the same Emacs process. This behavior gives you the best of both worlds: you can use Emacs and split it up however you’d like to, but you can take advantage of the fancy features of your window manager.

Just trust me. Give it a shot. I promise it’s better.

Hide the startup messages

(setq inhibit-splash-screen t
      inhibit-startup-echo-area-message t
      inhibit-startup-message t)

After

Useful when managing package dependencies and controlling load order. Taken from milkbox:

(defmacro after (feature &rest body)
  "After FEATURE is loaded, evaluate BODY."
  (declare (indent defun))
  `(eval-after-load ,feature
     '(progn ,@body)))

Better word wrapping

Emacs has a long history of being terrible at word wrapping. The situation has improved lately, however, and visual line mode gives you sane word wrapping in almost all cases.

(visual-line-mode 1)

Enforce trailing newlines

Some software (e.g., newsbeuter) breaks if you don’t provide a trailing newline.

(setq require-final-newline t)

Hide the toolbar

The toolbar is useful at first, but once you’re familiar with the major mode you’re working in, you might want to disable it to preserve vertical space.

(tool-bar-mode -1)

My config

My config files are on GitHub if you want to explore where I’ve gone with this. Caution that they don’t follow this post exactly, and they may not work on everyone’s system or be broken due to versioning (I build Emacs from the latest upstream source every couple weeks).


  1. evil-emacs-state uses Emacs keybindings exclusively.↩︎

  2. Note that not everything in a given buffer is a symbol, even though everything in Elisp is an object. Since you were looking up a function definition, it was a symbol, but symbol refers exclusively to those objects that have names.↩︎

  3. Often you’ll see people defining hooks using a lambda construct. This is counterproductive, since once you add a hook to a list it can be complicated to get it out. If you messed anything up with your lambda, you can have a hard time removing it. Giving all of your hooks explicit names lets you remove them easily with remove-hook without restarting your Emacs session.↩︎

  4. As of Emacs 24.4, turn-on-eldoc-mode is a deprecated alias for eldoc-mode, which should be used instead.↩︎

  5. One reader wrote to me, finding that the code I provide here did not work for him.

    I can see the elisp-slime description appearing at the bottom section, but when I press K it seems like it’s running another function. I’ve also tried mapping it to T, but I’m not able to get it working (but by running elisp-slime-nav-describe-elisp-thing-at-point from the M-x, (or : when in evil-normal-mode) it works perfectly)

    When he changed it to the following, it worked:

    (evil-define-key 'normal emacs-lisp-mode-map "K"
      'elisp-slime-nav-describe-elisp-thing-at-point)

    So readers who have issue with my code might want to try binding to K per above.↩︎

  6. A friend of mine pointed out that his version of Emacs (24.4, I believe) did not incldue a jump-to-source link in his describe-mode help window. While this was reported as a bug back in 2011, I was fairly certain that it has since been resolved …

    I tried this out and, indeed, the same was true for me: either the feature had been removed, or our Emacs’ packages were built incorrectly (e.g., without the source files). I think it’s possible to fix this by modifying the package source for whatever distro one is using to not strip the .el.gz files, but trying this on my own system has thus far not solved the issue.↩︎

  7. I got errors about the R in R E T not being a valid prefix key when I was testing this. YMMV.↩︎

  8. ibuffer does not refresh itself by default. You need to call ibuffer-update for new buffers to be shown.↩︎