Emacs config

Set up chemacs and Doom Emacs

This is the config of a mostly-Vim user trying to use Emacs.

The main noteworthy bits are my fondness for Org and perverse determination to get Emacs functioning equally well on Linux, macOS, and Windows 10.


For me, learning an environment includes trying out other, more functional versions of that environment. Chemacs lets me play with assorted Emacs distributions without destroying the config I’ve worked so hard to barely understand.

Now I can check out Doom Emacs!

Probably want to put ~/.emacs-doom/bin in my path or set some aliases.

emacs --with-profile doom

See StarterKits for other distributions to try out.

  (("default" . ((user-emacs-directory . "~/.emacs-bmw")))
   ("doom" . ((user-emacs-directory . "~/.emacs-doom"))))

Right now I’m mainly exploring Doom Emacs, so that’s my default profile now.


Doom Emacs

The default Emacs bindings work in Doom — the ones I know, at least. So yay! The little bit of muscle memory I have for tangling Org files still works!


init.example.el shows the full list of modules, including what’s activated by default.

Run doom sync after modifying!

Yes, I know. Sounds like a great thing to automate in the tangle process. I’ll get there.

The Doom Emacs features I enabled in my init.el, with descriptions provided by the example init.

This table may not look super interesting in the HTML export, but trust me it’s a blast sorting and filtering these rows in Org mode.

section module arguments description
:completion company the ultimate code completion backend
:completion ivy a search engine for love and life
:ui doom what makes DOOM look the way it does
:ui doom-dashboard a nifty splash screen for Emacs
:ui doom-quit DOOM quit-message prompts when you quit Emacs
:ui modeline snazzy, Atom-inspired modline, plus API
:ui ophints highlight the region an operation acts on
:ui popup +defaults tame sudden yet inevitable temporary windows
:ui vc-gutter vcs diff in the fringe
:ui vi-tilde-fringe fringe tildes to mark beyond EOB
:ui workspaces tab emulation, persistence & separate workspaces
:editor evil +everywhere come to the dark side, we have cookies
:editor file-templates auto-snippets for empty files
:editor fold (nigh) universal code folding
:editor snippets my elves. They type so I don’t have to
:emacs dired making dired pretty [functional]
:emacs electric smarter, keyword-based electric-indent
:emacs undo persistent, smarter undo for your inevitable mistakes
:emacs vc version-control and Emacs, sitting in a tree
:checkers syntax tasing you for every semicolon you forget
:tools eval +overlay run code, run (also, repls)
:tools lookup navigate your code and its documentation
:tools magit a git porcelain for Emacs
:lang crystal ruby at the speed of c
:lang data config/data formats
:lang emacs-lisp drown in parentheses
:lang json At least it ain’t XML
:lang javascript all(hope(abandon(ye(who(enter(here))))))
:lang lua one-based indices? one-based indices
:lang markdown writing docs for people to ignore
:lang org +hugo organize your plain life in plain text
:lang python beautiful is better than ugly
:lang raku the artist formerly known as perl6
:lang rst ReST in peace
:lang sh she sells {ba,z,fi}sh shells on the C xor
:lang web the tubes
:lang yaml JSON, but readable
:config default +bindings +smartparens (not a module, but so convenient to put here)

Let Python generate my Doom init from the summary table. I’d use elisp if I really knew what I was doing, but clearly I do not.

sections = {}

for section, m, args, _ in modules:
    if args:
        m = f"({m} {args})"
    sections.setdefault(section, []).append(m)

section_strings = "\n".join([ f"{section} {' '.join(included)}" for (section, included) in sections.items()])
print(f"(doom! {section_strings})")

Running that code with my doom-module-summary table as input produces something Doom can use:

(doom! :completion company ivy
:ui doom doom-dashboard doom-quit hl-todo modeline ophints (popup +defaults) vc-gutter vi-tilde-fringe workspaces
:editor (evil +everywhere) file-templates fold snippets
:emacs dired electric undo vc
:checkers syntax
:tools (eval +overlay) lookup magit
:lang crystal data emacs-lisp json javascript lua markdown (org +hugo) python raku rst sh web yaml
:config (default +bindings +smartparens))

Next some basic configurations.

Doom shell adjustments

Adds a few Doom-specific utilities to my path

manage and maintain the Doom Emacs configuration
Popup an org capture menu
Tangle files from the command line

addpath "$HOME/.emacs-doom/bin"

edoom to run Emacs Doom in a terminal

Emacs Doom is close enough to Vim for muscle memory and starts fast enough that I won’t get impatient waiting. Starting it up without a graphical frame is useful for quick edits in the middle of a tmux session, or my many scripts that fire off $EDITOR.

emacs -nw --with-profile=doom "$@"
Got a comment? A question? More of a comment than a question? Talk to me about this config!

Back to the config section