The Right Lang for the Job

Exploring the abbyss of non-mainstream programming languages

Write Emacs Lisp like a pro!

A guide to modern Elisp development

Last updated on:

Intro, or - why bother?

This is very wrong:

Emacs is a powerful editor. Its power comes primarily from thousands of man-years spent on writing libraries and apps (or modes) for it. The core Emacs contains half a million lines of Emacs Lisp, and if you go wild with installing packages you can easily end up with a million or more lines of Elisp. There's a lot of functionality there, for sure. You can get pretty far just using other people's code, with minimal customization in hooks and customizeable variables.

However, to actually benefit from all that power to the fullest, you need to delve deeper and understand what Emacs really is. You need to shift your perspective and look beyond the text-based interface Emacs provides.

Emacs is an implementation of Emacs Lisp - and that is its true nature. When thinking about Emacs don't compare it to Sublime Text or VS Code, but rather to Python, Ruby, or JavaScript. Just like them, Emacs provides a language, a standard library, and an ecosystem of packages. You can use Emacs as a tool for text editing, but the full potential will be unleashed only when you begin to treat Emacs as a tool for making tools.

Historically, Emacs Lisp wasn't the greatest language to write programs in. The lack of lexical scoping, messy standard library, no package manager, slow execution were plaguing Emacs for decades. There's a lot of older Elisp code floating around and all the hacks and workarounds in there are a testament to the language's problems.

However, things have changed drastically over the last decade. Almost all problems with Elisp were addressed. Lexical scoping is there, a package manager is in the base distribution, wrapper libraries like dash, s, f expose and extend the functionality in a more organized manner, the AOT compilation of byte-code to native has shown remarkable improvements in performance. You can now write extension modules in any language capable of producing native shared libraries. There's a preliminary support for native threads. Emacs always had the potential, but recently it became a full-fledged IDE for Emacs Lisp, one that could compete (and win) against JetBrains product, if they decided to write one for Elisp.

The only remnant of the dark past, and the biggest outstanding pain point, is lack of namespaces and first-class modules. The improvements on this front would be very welcome, but you can work around this limitation the same way you do when writing C: just namespace your definitions yourself with a prefix of your choosing. I use my- prefix for all my code. It's crude, admittedly, but it works well enough.

In any case, to get the most out of Emacs, you will need to write some Elisp yourself. The better you learn Elisp, the easier it will be for you to bring out the full potential of Emacs.

This series of posts is not a replacement for reading an Elisp tutorial or a book about it. You still need to learn a lot on your own. The tools discussed here will help you along the way - they will let you learn Elisp faster and will help you write your own Elisp faster later on. The time investment of setting all the tools up will be well worth it in the long run.

Basic tools

  • Helm
  • Magit
  • Org
  • Treemacs / Neotree
  • Imenu
  • display-line-numbers-mode / linum-mode
  • fill column indicator
  • highlight current line
  • auto-complete / company
  • yasnippet
  • re-builder (make bindings for search&replace from within)
  • hydra / pretty-hydra

Reading the docs (you don't even need to google!)

  • helpful
  • info viewer
  • info+
  • help+
  • apropos different commands
  • describe

apps and libraries,

libs for elisp consumption

apps with commands for users and settings and stuff

some libs may have a few commands, but not many

buffer api available: batch and background

tools and knowledge

info manual





go to source


refactoring tools



(inspector-inspect 1)



describe- commands



(require 'cl-lib)
(cl-loop for sym being the symbols
         if (s-ends-with? "?" (symbol-name sym))
         collect (symbol-name sym))


TODO startup times of various interpreters relative to Emacs