Why vanilla?

Let’s start with the most obvious question: What’s wrong with Doom Emacs? Short answer: There is nothing wrong with Doom Emacs. I still use it and I still recommend it for beginners. Some years ago I started with Spacemacs and moved to Doom which, in my humble opinion, is far faster and more stable. So if you’re a novice and just entered the “church of Emacs The “Church of Emacs” is a humorous reference to the strong advocacy and devotion some Emacs users have towards the Emacs text editor. It plays on the idea of Emacs being more than just a tool, but almost a way of life for some users. I strongly recommend you do NOT start with vanilla. I recommend Doom because:

That said, I still wanted to go “vanilla,” at least give it a try. My first attempt failed, mainly because I was trying to use someone’s config without really understanding how it works. I also had some “hard requirements” for my configuration:

Go vanilla

If you really decide to continue this journey, I’d like to share some tipps/workflow to make your process more smoothly.

Ever since I’ve started my Emacs journey it seemed like the wholy grail to have your own (vanilla!) configuration without any hard dependencies on frameworks like Doom or Spacemacs. There are plenty of dotemacs configurations ouf there which can serve as a great source of inspiration.

In my case, it was specifically this one which caught my attention: https://config.phundrak.com/emacs/. It had almost everything I needed, it was using evil mode and the whole configuration is written in ORG mode. Bingo! I also droped Lucien a mail expressing my gratitude for having such a great source of an awesome configuration.

Literate config

As a matter of preference I don’t like Elisp based Emacs configurations. I find ORG mode and literate config to be more easy to read and understand what’s going on.

You can have a basic structure in your ORG mode file, define sections, and use the outline functionality to jump to each section. You can then tangle the ORG file to generate the .el files to be loaded by Emacs. Check Introduction to Literate Programming for more insights. Having spent countless hours (and days) tweaking my configuration, reading others and trying to understand custom Elisp functions, I think I’ve reached a level where I exactly know which part of my config is responsible for some misbehavior. Other than that, I’ve found a structure that fits my needs and the way I want my configuration to be structured.

Basic structure

Your configuration should have a basic structure. You can either use a single file for the whole configuration or multiple ones. I prefer multiple ones because you can tangle each one individually and thus make the whole process faster. This is what I have inside my Emacs folder in my dotfiles:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
emacs
├── basic-config.org
├── custom-elisp.org
├── index.org
├── keybinding-managers.org
├── keybindings.org
├── Makefile
├── package-manager.org
├── packages
│   ├── applications.org
│   ├── autocompletion.org
│   ├── editing.org
│   ├── helpful.org
│   ├── org.org
│   ├── programming.org
│   └── visual-config.org
└── tangle_script.sh
Code Snippet 1: Basic structure of my Emacs configuration files

This structure is more or less copied from Phundrak’s one which served as a really good starting point. Of course I stripped down each file to my needs.

The point is that each file would host a different set of customizations relevant to specific functionalities. If I want to change some keybindings I’d then go to keybindings.org and modify stuff. If I want to tweak the autocompletion for lsp-mode I’d then go to autocompletion.org.

Tangling

In Emacs and Org mode, tangling refers to the process of extracting code snippets from an ORG file and writing them to separate source code files. It usually allows you to maintain code and documentation in the same file while keeping them in sync. In my case I use it to generate Elisp code out of my ORG files.

Automation

I like to automate most of the workflows and therefore I use a Makefile and some bash script for tangling all files:

1
2
3
4
# Phony target to tangle all org files
.PHONY: tangle
tangle:
    find . -name "*.org" -exec sh -c 'echo "[!] Tangling {}"; ./tangle_script.sh "{}"' \;
Code Snippet 2: Makefile for my Emacs configuration

And this is the script I use to tangle one individual file:

1
2
3
4
5
#!/bin/bash

emacs -q --batch --eval "(require 'ob-tangle)" \
  --eval "(setq org-confirm-babel-evaluate nil)" \
  --eval "(org-babel-tangle-file \"$1\")"
Code Snippet 3: The tangle script which takes an ORG file as an argument

Manually

I would like my overall configuration (at ~/.config/emacs) to be updated immediately whenever I change something in the Org mode files. Therefore I use .dir-locals.el to define this behaviour for all ORG mode files

1
2
3
4
5
6
7
8
9
;;; Directory Local Variables            -*- no-byte-compile: t -*-
;;; For more information see (info "(emacs) Directory Variables")

((org-mode . ((org-confirm-babel-evaluate . nil)
              (eval .
                    (progn
                      ;; Tangle whole file after being saved
                      (add-hook 'after-save-hook 'org-babel-tangle)
                      )))))
Code Snippet 4: .dir-locals.el

First I don’t want to be asked every time if I want to evaluate the source code blocks (that’s why org-confirm-babel-evaluate is set to nil ). Secondly I want to automatically tangle the file whenever the file gets saved (org-babel-tangle in the after-save-hook).

This way every time I save one file, the Elisp code will be automatically be tangled to the corresponding file.

Inspirations

Sometimes I don’t know exactly how to configure a package or which options I should be using. Instead of searching the web for the examples last year I came up with an idea: I started collecting interesting/useful dotfiles~/~dotemacs collections in a single place. You can find the repository at github.com/dorneanu/dotemacs. So what I usually do is to search inside the folder where I’ve cloned all repositories for specific keywords. For this purpose I use rg.el and some custom function:

1
2
3
4
5
6
7
(setq dotemacs-directory "/cs/priv/repos/dotemacs")
(rg-define-search my/rg-dotemacs
  :query ask
  :format regexp
  :files "everything"
  :dir dotemacs-directory
  :confirm prefix)
Code Snippet 5: From the rg section in my dotemacs config

Conclusion

Checkout my dotfiles (which I manage using chezmoi) if you need some inspiration. If you have other tips on how to further improve my workflow or the overall structure, please drop me an email.