Skip to content

p3r7/awesome-elisp

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
November 10, 2022 10:23
October 15, 2020 12:55
November 10, 2022 10:38

README.org

Emacs Logo

Awesome Elisp

Welcome to Awesome Elisp, a list of resources linked to Emacs Lisp (Elisp) development.

Its aim is to not be a simple index but a compendium: resources are not only listed but also commented.

It tries to be as exhaustive as possible.

For a more general index related to all-things Emacs, use Awesome Emacs.

Table of Contents

What is Elisp?

Elisp is short for Emacs Lisp, a dialect of Lisp specific to Emacs.

If you’re a fresh Emacs user, you’ve certainly practiced it a bit by editing your init.el (i.e. configuration).

You may also have spotted that most packages (i.e. plugins) available to Emacs are written in pure Elisp.

In fact, Elisp is not limited to extending Emacs functionalities: a good chunk (and admittedly not enough) of Emacs is written in it.

This means that any user can browse, extend or even override core Emacs functionalities at runtime.

As such, in essence, Emacs is not an editor but more a platform allowing users to write text-based apps.

Being an editor is not its intrinsic nature but merely a feature.

Learning Elisp will up your Emacs game tremendously, unlocking its full potential by writing functionalities either for your personal needs or to share with the world.

As an added bonus, it’s great fun.

Iconography

./rsc/icon/standard.pngstandard (bundled with every Emacs install)
./rsc/icon/informal-standard.pnginformal standard (not bundled with Emacs, but used in many major packages)

Resources

Entry-level

An Introduction to Programming in Emacs Lisp

read online

Also comes bundled with Emacs. Just C-h i (or M-x info) and open Emacs Lisp Intro.

A bit scholarly. Not the easiest read.

Emacs In A Box - Elisp Programming

read online, source

Very complete and gentle introduction.

Written by Caio Rordrigues (@caiorss).

(Almost) All You Need to Know About Variables

read online

A must read!

elisp-guide

read online

Focused on introducing general concepts and terminology.

Emergency Elisp

read online

Focused around data structures. More like a cheat sheet.

ergoemacs - Practical Emacs Lisp

read online

Not super up to date but generally well put together.

One of the first resources on the web introducing Elisp in a concise and comprehensible way.

Please note that the more complex examples follow a coding style regarded as not so great: big monolithic functions instead of multiple small functional ones.

To Xah’s defense, some packages now considered standard are also written this way (we’re looking at you ediff).

ElispCheatSheet

read online, source

Focused around data structures.

Author’s Common Lisp background can be felt.

Advanced

Emacs Lisp Reference Manual

read online

Also comes bundled with Emacs. Just C-h i (or M-x info) and open Elisp.

Comprehensive guide of core Elisp APIs.

Generally well written but needs you to understand its logic and be familiar with Emacs terminology.

The Emacs Lisp Style Guide

read online

Provides solid guidelines on the dos and don’ts for quality Elisp code.

The Emacs Package Developer’s Handbook

read online, source

@alphapapa’s organized notes about Elisp development.

List bunch of tools and libraries for helping package developers.

Also provides various snippets and best practices.

Lots of good insights.

nullprogram.com

Chris Wellons (@skeeto)’s blog, especially the posts tagged #elisp.

A few highlights:

Emacs Lisp Programming Thoughts

read online

Pretty old but has very good insights, guidelines and real-world examples.

Byte compiler section is outdated but general coding style recommendations and sections about macros and profiling are still relevant to this day.

Cookbooks

elisp-demos

read online, source

Very good and beginner-friendly.

Almost complete list of single-liner examples of standard function. Also packs examples for dash and s.

Emacs In A Box - Elisp Snippets

read online, source

Really nice selection of snippets with real-world use-cases.

EmacsWiki’s Cookbook

read online

Community-driven snippets, beginner-friendly.

@alphapapa’s unpackaged.el

read online, source

Real-world selection of snippets, not beginner-friendly.

On Package Authoring

The Emacs Lisp Style Guide applies all the more in this context.

Article: Take Your Emacs to the Next Level by Writing Custom Packages

read online

Real world experience of a user writing and submitting his first package.

MELPA recommandations

read online

There’s a high chance that you’ll be uploading your package on MELPA.

They have clear recommandations.

Don’t worry, for your first submissions, they will be very comprehensive and will help you fixing what’s wrong.

Contributing to Emacs

The CONTRIBUTE file is the official document describing the process. Additional development tips and coding conventions can be found in the Elisp Manual.

M-x view-emacs-todo shows a lists of TODO items you might want to work on. You can also browse the bug archive using M-x debbugs-gnu using the debbugs package.

Contributing to Emacs gives some helpful background information and overview about the contribution workflow for newcomers.

Development Tools

By default, Emacs is already pretty well set up for Elisp development.

But some features can be hard to learn and some stuff can be improved with additinal packages.

See also those talks John Wiegley gave about his setup for Elisp development:

Interactive Development & Debugging

Emacs is built with interactive development in mind.

You could spend days developing Elisp code without ever having to restart Emacs.

Standard commands used are:

  • eval-last-sexp (C-x C-e)
  • eval-defun (C-M-x)
  • eval-buffer
  • eval-region

The *scratch* buffer also provides a temporary zone to try and test ideas. In it can be used eval-print-last-sexp (C-j) which acts like eval-last-sexp but also prints the result after the s-exp in the buffer.

eval-expression (M-:) allows quickly evaluating a s-exp from anywhere by entering it in the minibuffer.

For logging, function (message "<text>") allows printing into the *Messages* buffer.

For debugging, the most basic command is toggle-debug-on-error to get a stacktrace.

See also:

IELM

./rsc/icon/standard.png

Stands for Inferior Emacs Lisp Mode.

Provides a REPL for evaluating Elisp code.

edebug

source, doc

./rsc/icon/standard.png

edebug is the interactive Elisp debugger.

The documentation is a bit rough to get started. I recommend reading this series of posts:

You can also read the dedicated chapter in book An Introduction to Programming in Emacs Lisp.

trace

source

./rsc/icon/standard.png

Provides a simple facility to output a trace of function calls into a buffer (*trace-buffer*).

Please note that this trace is very basic and has no performance data. For more advanced tracing see Profiling.

Tracing is switched on / off with commands trace-function, untrace-function and untrace-all.

macrostep

source & doc

Interactive macro expander.

Expand nested macros one by one.

Way better than using default macroexpand.

eval-expr

source

Provides eval-expr, an enhanced eval-expression command.

Some highlights:

  • automatic display of output in temp buffer if too big
  • allows pretty printing of results (with pp)
  • invalid s-expr don’t have to be retyped on 2nd try

eval-sexp-fu

source

Visual improvment.

Flashes the sexps during the evaluation.

eros

source

Show evaluation results inline.

Documentation & Introspection

To get the documentation of a symbol, you could use one of the built-in:

  • describe-symbol: get documentation of symbol
  • describe-function: get documentation of function
  • describe-variable: get documentation of variable
  • describe-key: get documentation of command associated with keybinding

These would spawn a *Help* buffer. Hence documentation in Emacs is often referred to as the help. For searching through symbols Emacs also comes with various apropos-* commands which populate a buffer with your search results.

Some packages improve on these.

helpful

source & doc

Provides more contextual information.

helpful commanddefault commandcomment
helpful-at-pointdescribe-symbol
helpful-callableno equivalentlike helpful-function but also works on macros and special forms
helpful-functiondescribe-function
helpful-macrono equivalent
helpful-variabledescribe-variable
helpful-keydescribe-key

elisp-demos

source

Provides usage examples in the *Help* buffer.

which-key

source & doc

which-key is like an always-on describe-key.

It displays automatically all the possible keybindings following a key prefix.

suggest

source

Discover elisp functions by specifying input and the desired output.

Code Editing

Jump to definition

To jump to the definition of a symbol Emacs provides xref-find-definitions. In practice it works with nicely with functions but is kind of hit-or-miss with variables.

In addition, the following more specialised functions exist:

  • find-function: go to the definition of function
  • find-variable: go to the definition of variable
  • find-library: go to the definition of feature (i.e. module, package)

Better options exists so that you don’t have to remember all of these.

Honorable mention: elisp-slime-nav, that can be seen as an ancestor to elisp-def. If you want to jump to symbols in files which aren’t loaded in your Emacs you can fallback to the more general dumb-jump package.

elisp-def

source & doc

Provides elisp-def that allows jumping to the definition of function / variable / feature.

Like a better xref-find-definitions.

Is able to distinguish between functions / variables / features depending on the context.

Also handles macros, functions defined through macros and let-bound variables.

Search & Replace

In Emacs regular expressions can make use of syntax information provided by the major-mode. This means that to some extend semantic searches are possible with isearch and occur. To search and jump to toplevel definitions of a buffer you can use the built-in imenu. The imenu-anywhere package allows to extend the scope to buffers of the same project or mode.

elisp-refs

source

Semantic code search for Elisp which parses the code instead of doing dump text searches.

el-search

source

Lets you execute search and replace operations on symbolic expressions. For example you can search for things like defvars which don’t specify an init value using the pattern `(defvar ,_)`.

Editing

Honorable mentions:

  • YASnippet: generic (not Elisp-specific) powerful abreviation-based snippet expander. Even though it could be used in the place of speed-of-thought-lisp, it is less context-aware and requires a specific key combination to trigger. It offers other features, though, and can be used complementarily.

speed-of-thought-lisp

source

Allows writting Elisp blazingly fast with the use of context-aware abbreviations triggered after <SPACE> keypress.

elisp-docstring

source

Enriched syntax highlighting for docstring contents. Together with string-edit you can edit docstrings in a temporary buffer and get automated special character escaping.

Editing S-exps

Elisp is a Lisp and Lisps are written using a structure of nested lists called S-expressions.

Mastering how to navigate and manipulate this structure with ease is essential.

By default Emacs doesn’t offer much apart from forward-list / backward-list and forward-sexp / backward-sexp.

Luckily, powerful minor-modes are available to give you the power you deserve.

lispy

source & doc, cheat sheet, video demos

Easiest to learn yet most powerful solution in that list.

Like paxedit, commands are context-aware.

The killing feature is that shortcuts are single characters and not key combinations.

The trick is that commands get triggered only when the point is at a delimiter (e.g. a parenthesis) or the region is active.

Provides a powerful command combination system and refactoring commands.

paxedit

source & doc

Heavily inspired by paredit.

The major difference with the latter is that commands are context-aware, they behave differently depending on what the cursor is hovering on.

The direct consequence is that fewer commands / shortcuts needs to be learned to perform the same amount of things.

paredit

tutorial, source

The first powerful S-exp editing mode for Emacs.

Learning curve is a bit steep.

Still actively maintained and very popular.

Refactoring

elisp-depmap

source & doc

Aids the refactoring process by presenting a graphical visualization of project dependencies.

emacs-refactor

source & doc

Contains various refactoring commands for Elisp.

Formatting

aggressive-indent-mode

source & doc

Auto-indents code as you type.

elfmt

source

Focuses on placement of lists and tries to break lines at fill-column

Testing

For simulating interactive user input, consider using libraries such as with-simulated-input (launch commands) and dokey (simulated keyboard shortcut presses). To test behavior and interactive usage in a clean and temporary environment emacs-sandbox.sh is useful.

ERT

doc, blog post on nullprogram.com

./rsc/icon/standard.png

Stands for /”Emacs Lisp Regression Testing”/.

Featureful and easy to use.

Suitable for unit tests with mocking.

Buttercup

source & doc

Behavior-Driven Emacs Lisp Testing

Especially suitable for integration tests.

Allows defining test suites (i.e. goups of related tests) with a shared context (through set-up and tear-down phases).

Also provides mocking capabilities.

For a complete example of integration w/ undercover and coverage:

director

source & doc

Program sequence of user interactions. Useful for end-to-end testing.

Inspired by Selenium Webdriver.

undercover

source & doc

Track test coverage and integrate w/ coverage reporting solutions.

For in-Emacs reporting, use the coverage package.

Profiling

Emacs provides 2 Elips profilers:

  • profiler.el: profile a whole call stack, easier to use
  • elp.el: profile only selected functions

Both are briefly mentioned in the profiling section of the Emacs Lisp Reference Manual.

Either one is of a great help to debug slow Elisp code, most noticeable during user interactions (Emacs seems to freeze).

profiler.el is easily toggled using profiler-start, profiler-stop. To obtain a result report call profiler-report.

elp.el can target individual functions with elp-instrument-function or a whole package with elp-instrument-package.

To profile individual forms Emacs also comes with the benchmark library. The Emacs Package Developer’s Handbook has a whole section dedicated to this with thorough examples and helper macros.

etrace

source & doc

Wrapper around elp.el outputting a report in the Chromium Catapult Trace Event Format.

This allows opening them in external applications to explore them as flame graphs.

Validation

Emacs provides various functions to validate an Elisp file / project:

  • byte-compile-file: validate the file compiles cleanly
  • checkdoc: validate the documentation
  • check-declare-file / check-declare-directory: validate the declaration of symbols
  • package-lint-current-buffer: validate format for submitting as a package

It’s tedious to run manually each and every of those commands. Thankfully projects aim at making this process easier.

For maximum efficiency, they can be integrated into a CI chain (GitHub actions or Travis).

melpazoid

source & doc

In addition to standard validation, it adds a license checker and some additional checks.

Created by MELPA member @riscy to validate submissions.

Does not run tests.

Provides recipes for integration with GitHub actions or Travis.

makem.sh

source & doc

Very straightforward way to validate an Emacs package folder / repository.

Provides a makefile with different targets to run.

Implemented in bash with a makefile wrapper.

Performs linting (make lint), tests (make test) or everything (make all).

In addition to standard checks, also validates indentation and optionally elsa checks.

Supports both ERT and buttercup tests.

One drawback is that this makem.sh sources have to be dropped in each of your package source repository.

Provides recipes for integration with GitHub actions.

makel

source & doc

Provides a makefile with different targets to run.

Implemented completely as a makefile.

Requires a bit of configuration for each package.

One drawback is that this makel sources have to be dropped in each of your package source repository.

No CI integration recipes.

elisp-check

source

A zero config github action to validate packages.

auto-compile

source

Compiles current file on save and display compile errors/warnings in the mode-line.

elisp-lint

elisp-lint

Performs standard validation of specified file. Also checks for indentation.

No CI integration recipes.

elsa

source

Static Elisp code analyzer providing helpful hints.

Can be launched directly from makem.sh.

package-lint

source

Lints Elisp files for requirements of packages. Can be integrated with flycheck (a general linter framework) by installing flyspell-package.

Building

Those tools, in addition to what those in the Validation section provide, are full-fledged build-definition tools, allowing to make complex CI/CD chains.

They require a fair amount of configuration and are not for the faint of heart.

They only seem necessary when building larger packages with exotic dependencies.

Eldev

source & doc

Stands for /”Elisp Development Tool”/.

Certainly the most modern of the lot.

100% written in Elisp.

One small drawback is that it does not run in a dedicated isolated Emacs process.

cask

doc, source

Pretty advanced and hard to get into.

Implemented in python.

Runs in a dedicated isolated Emacs process

emake

source & doc

The most simple to use from this list.

Implemented in Elisp with a makefile wrapper.

Easier to integrate with CI tools such as Travis.

Syntax Highlighting & Visual Enhancements

Several packages provide visual improvements and extend default syntax highlighting (font locking in Emacs lingo).

All those listed bellow are complementary.

Honorable mentions:

Not Elisp-specific but commonly used in the context of Elisp development:

  • traditionally, form feed characters (^L) are used in Elisp source as a section delimiters. Either page-break-lines or form-feed can be used to display them as intended.
  • for those that can barely stand parentheses, paren-face can be used to dim them in Lisp-based modes
  • for those that love parentheses, rainbow-delimiters allows displaying them in different colors depending on their nesting depth

lisp-extra-font-lock

source & doc

Various additional syntax highlightings.

Killer feature is having different faces for special vars (global) VS normal ones (local).

highlight-function-calls

source & doc

Make functions calls stand out with a specific face.

cl-lib-highlight

source & doc

Provides additional / alternative font-locking for cl-lib symbols, to make them stand out in your code.

Also highlights deprecated cl symbols with a different face. Useful when reading legacy code.

easy-escape

source & doc

Make regular expression strings more readable.

nameless

source & doc

Hide prefix in symbols of a package.

Pretty Printing

pp

source

./rsc/icon/standard.png

Standard Emacs pretty-printing util.

ppp

source & doc

Advanced pretty-printing utils.

Libraries

Traditionally, it was recommended to not use external libs/dependencies and prefer using standard APIs bundled with Emacs.

These recommendation are still mostly valid but predated the advent of package.el.

Some external libs are now considered “standard”, as lots of popular packages use them and they can outperform standard implementations while still being simpler to use (e.g. dash).

Some libraries might be listed several times, as they fit in several categories (e.g. subr-x, dash).

Core / General Purpose

cl-lib

./rsc/icon/standard.png

Lib extending Elisp with functionalities inherited from Common Lisp. Replaces the deprecated cl package which did not use name prefixes. To help with updating the code from cl to cl-lib there is cl-libify.

Just do a (require 'cl-lib) to use it.

subr-x

source

./rsc/icon/standard.png

Intended as an extension to subr.el, the core library of basic functions written in Elisp.

Provides:

  • threading macros (a la Clojure, thread-first and thread-last)
  • additional binding helpers (if-let, if-let*, when-let, when-let* and and-let*) - hash-table manipulation helper (hash-table-empty-p, hash-table-keys and hash-table-values)
  • string manipulation helper (string-empty-p, string-blank-p, string-join, string-trim, string-trim-left, string-trim-right, string-remove-prefix and string-remove-suffix)
  • region manipulation helpers (replace-region-contents)

dash

source & doc

./rsc/icon/informal-standard.png

Even though this lib revolves primarily around list manipulation, it also offers for general purpose utils.

Those are:

They all seem to be heavily inspired by Clojure.

el-patch

source and doc

More perene advices, get notified when they break.

anaphora

source & doc

Allows the definition of anaphoric functions (as can be found in Common Lisp, Clojure…).

with-simulated-input

source & doc

./rsc/icon/informal-standard.png

Simulate user interactions (i.e. launch commands).

Mostly usefull for writing tests.

dokey

source & doc

Trigger keyboard events.

contract

source & doc

Provides data structure defintions as contracts (essentially interface description).

Port of Racket’s contract to Elisp.

Akin to Clojure’s spec.

signal

source & doc

Reimplementation of hooks, with more advanced features.

weak-ref

source & doc

Allows creating weak reference to vars. Weak reference offer better performance but can be garbage collected.

predd

source & doc, blog post

Provides Clojure-style multimethods (multiple dispatch over an ad hoc type hierarchy).

fn

source & doc

Provides macros for a more concise lambda syntax, a la Clojure.

Data Structures

Strings

subr-x

source

./rsc/icon/standard.png

Provide the following helpers: string-empty-p, string-blank-p, string-join, string-trim, string-trim-left, string-trim-right, string-remove-prefix and string-remove-suffix.

s

source & doc

./rsc/icon/informal-standard.png

Advanced yet easy to use string manipulation helpers.

rx

tutorial, source

./rsc/icon/standard.png

Macro for helping writing Elisp regexp.

xr

source & doc

Convert regexp to their more human-readable rx macro form.

Also provides regexp linting, detecting mistakes and bad practices.

Relies on its own internal parser.

Sequences

seq

source, doc

./rsc/icon/standard.png (since version 25)

dash

source & doc

./rsc/icon/informal-standard.png

Advanced yet easy to use list manipulation helpers. Lots of them also have alternative anaphoric forms.

stream

source & doc

Allows defining streams of data as data sequences. Compatible w/ seq.el.

trie

source

Provides APIs for building and manipulating tries, sequence-like data structures where both storage and retrieval are space- and time-efficient.

Stored elements must be ordered sequences, i.e. strings (most common use-case), lists or vectors.

lister

source & doc

Provides lister-mode, major mode for building and manipulating list-based user-interfaces.

Inspired by tablist (for tables) and hierarchy (for trees).

Maps

(Hash)maps are a special type of sequences that allow representing a list of key / value pairs. In other languages they can also be called associative arrays or dictionaries.

In Elisp, a map can be represented as:

  • an alist (association list, preserving element order)
  • a plist (property list, more human-readable)
  • an hash-table
data structurehuman-readabilityinsert speedlookup speedordered?
alistmehfastestslower as data growsyes
plistvery goodokfastno
hash-tableokokvery fastno

The official doc also has a nice section comparing plists and alists.

tl;dr:

  • planning on doing lots of inserts and a few lookups (or mostly on recent elements), use an alist
  • planning on having a big number of elements and lookup speed is critical, use an hash-map
  • every other case, use a plist

Older Emacs packages tend to rely mostly on alists, sometimes for no good reason.

Each data structure has its own APIs to get/insert/update.

Thankfully, some libraries provide an abstraction layer that allows having a single API for multiple data structures.

I would recommend sticking with the default map.el library, unless you really enjoy the Clojure syntax in which case a.el is also a nice choice. If you know for sure that you want to stick with an alist or a hash-table, asoc.el and ht are high quality choices.

map

source

./rsc/icon/standard.png (since version 25)

supports: alists, plists and hash-tables.

Shared API for all 3 Elisp map objects (+ arrays).

No documentation other than what is inlined in source.

asoc

source & doc

./rsc/icon/informal-standard.png

supports: only alists.

Nice set of additional APIs for alists.

ht

source & doc

./rsc/icon/informal-standard.png

supports: only hash-tables, but allow converting from/to alists and plists.

Nice set of additional APIs for hash-tables.

a

source & doc

supports: alists and hash-tables.

Shared API for alists and hash-tables. Like map.el, but in a more “Clojurey” syntax.

kv

source & doc

support: mostly alists, but allow converting from/to alists and plists.

dict-tree

source

Provides APIs for building and manipulating Dictionary trees, hybrid between tries and hash tables.

Think about it as a more storage-efficient hash tables.

Custom Types & OOP

Can be done natively using records, additional custom user-defined types.

cl-lib (defstruct API)

API documentation

./rsc/icon/standard.png

One part of cl-lib is APIs to define and manipulate C-like data structures, strongly typed.

Provides the cl-defstruct macro.

Built on top of the native records system.

See also this blog post from @skeeto: Options for Structured Data in Emacs Lisp

EIEIO

doc

./rsc/icon/standard.png

Stands for Enhanced Implementation of Emacs Interpreted Objects.

Brings an OOP layer to Elisp, based upon the Common Lisp Object System (CLOS).

Provides the defclass macro.

Built on top of the native records system.

Date & Time

ts

source & doc

./rsc/icon/informal-standard.png

Advanced yet easy to use datetime / timestamp library.

datetime

source & doc

Library for parsing, formatting, matching and recoding timestamps and date-time format strings.

datetime-format

source & doc

Provides datetime-format, inspired by PHP’s Datetime::format method.

Tables

tabulated-list

./rsc/icon/standard.png

Library for defining, manipulating and displaying tables.

tablist

source & doc

./rsc/icon/informal-standard.png

Extension to tabulated-list, adding possibility to mark and filter items.

navigel

source

Facilitate the creation of tabulated-list-based UIs.

Also relies on tablist.

gridlock

source & doc

Provides gridlock-mode, major mode for building and manipulating spreadsheet-based user-interfaces

Also provides gridlock-csv-mode and gridlock-fix-mode minor modes, backporting the API to CSV and FIX files.

cell

doc, source

Provides cell-mode, major mode for building and manipulating spreadsheet-based user-interfaces.

ctable

source & doc

Library for defining, manipulating and displaying tables.

Queues

queue

source

./rsc/icon/standard.png

Provides FIFO / FILO queue APIs.

fifo-class

source & doc

An EIEIO abstract class class to provide FIFO methods to slots.

Rings

Even though ring is the standard implementation, some core libs use their own internal implementation (e.g. the kill-ring).

ring

source

./rsc/icon/standard.png

Provides APIs to create and manipulate a ring data structure.

Used by: ERC

dynaring

source

Similar to ring, but w/ a dynamic size.

Trees

Escaped and nested S-exps is the most straightforward way to encode a tree in (E)lisp.

Some libraries deliver higherèlevel data structure with manipulation functions for improved performance and convenience.

heap

source

Provides APIs to build and manipulate a ternary (at most 3 children per node) heap (self-sorting tree).

avl-tree

source

./rsc/icon/standard.png

Provides APIs to build and manipulate a self-balancing binary tree.

hierarchy

source & doc, blog post

Allows defining trees as well as building user interfaces displaying them.

treepy

source & doc

Allows defining and traversing trees.

taxy

source & doc

Allows defining hierarchical taxonomies, i.e. trees w/ automatic classification based on (nested) rules.

rbit

source

Self-balancing interval trees.

Implementation of Chris Okasaki’s algorithm from “Red-black trees in a functional setting”, JFP’99.

pair-tree

source & doc

Visualize and explore nested S-exps as a tree.

Parsers & Parse Trees

Those libraries allow parsing a document in a format / language and converting it to an tree, called an an AST.

parse-it

source & doc

Regexp-based parser, supporting a bunch of languages.

tree-sitter

doc, source, reddit post, example usage article

Implemented as a module, binding with the tree-sitter parser (written in Rust).

For a concrete use-case, have a look at tree-edit.

For a better sitter grammar for elisp (distinguishing between var, functions and macros), use tree-sitter-elisp.

moldable-emacs

source & doc, presentation @ EmacsConf21

Powerful parser and transformer library, relying on the concept of composable functional molds.

Also support asynchronous processing (relying on async).

tNFA

source

Provides APIs to build and manipulate NFA (Nondeterministic Finite Automaton), i.e. a state machine / decision tree.

It was built manily with regexp parsing in mind.

parsec

source & doc

Parsing library in the spirit of Haskell’s parsec.

pl

source & doc

Parsing library in the spirit of Haskell’s parsec. Somewhat limited.

XML/HTML

dom

./rsc/icon/standard.png

DOM manipulation and searching functions.

xml-query

source

List-based XML selectors. Part of the elfeed package.

Org-mode outlines

org-mode outlines (spec) can be considered both a file format and a tree format.

org-element

source, doc, tutorial on ergoemacs

./rsc/icon/standard.png

org-mode’s internal parser, used to convert a text buffer into a tree structure (parse-tree).

org-ml

source & doc

Functional manipulation of an org parse-tree.

org-ql

source & doc

Query language (DSL) for parsing, searching and filtering an org outline.

org-ba

source & doc

More user-friendly APIs for writting code for interacting with org documents.

Faces

Faces are a group of attributes controlling the formatting of text in Emacs.

It’s akin to CSS for HTML or styling ANSI escape sequences for terminal text.

You can read more about faces in the Emacs manual or the Emacs Lisp Reference Manual.

engrave-faces

source & doc

Convert faces to other formats.

Currently, only LaTeX is supported.

Color Codes

color

source

./rsc/icon/standard.png

color-tools

source & doc, blog post

Color codes manipulation, with support for various color spaces.

yk-color

source

Color codes manipulation.

Concurrency / Asynchronicity

Concurrency in Elisp / Emacs is a hot topic.

Due to its single-threaded nature, we can’t do parallel processing unless using some dirty tricks (see async).

But that doesn’t prevent us from doing concurrent processing, with say timers.

Emacs recently extended this support with generators (since 25.1) and native threads (not what you might be thinking of, since 26.1).

For more info on those subject, read:

Timers

timer

source

./rsc/icon/standard.png

Default timer lib.

named-timer

source & doc

Easier to use timer lib.

Promises & Delays

thunk.el

source

./rsc/icon/standard.png

Provides an API for creating and dereferencing / evaluating delays.

promise.el

source & doc

Reimplementation of the Promises/A+ open standard (originally targeting Javascript).

aio

source & doc, blog post

Mostly an async/await lib but implements its own promise system internally.

Async Elisp function calls

deferred

source & doc

./rsc/icon/informal-standard.png

Not super-actively maintained, but quite stable and featureful.

Achieves concurrency through the use of timers.

Also allows handling async (sub-)processes and HTTP calls with request.el bindings.

concurrent

source, doc

Higher-level wrapper around deferred.

Provides various syntaxes inspired by those of other programming languages, such as:

  • Clojure / Java / Lua’s coroutines (threads)
  • Python’s asyncio coroutines (generators)
  • Clojure’s core.async pipelines (signals / channels).

async

source & doc

./rsc/icon/informal-standard.png

Achieves true parallel processing by spawning a child Emacs sub-process. As such, necessary context needs to be passed w/ async-inject-variables.

Supports defining callbacks.

Offers bindings w/ dired, bytecomp and smtp-mail.

timp

source & doc

Multithreading through sub-processes with over-the-wire payload capabilities.

Achieves true parallel processing by spawning a child Emacs sub-process for each thread.

aio

source & doc, blog post

Short for async-io.

Allows writing coroutines with the async/await syntax found in Python’s asyncio.

Internal representation relies on its own promise implementation and generators.

async-await

source & doc

Simple implementation of Async/Await, based on the TypeScript syntax.

Relies on promise.el and generators.

lcr

source

lcr stands for Lightweight CoRoutines.

Seems to rely on timers.

Async sub-processes

These libs only allow to run asynchronously command processes (as opposed to Elisp function calls).

It can be done in standard with low-level function make-process or derivatives start-process, make-pipe-process and start-process-shell-command.

Some advanced behaviours are hard to program, that’s why wrapper libraries can help you.

Notably:

  • ensuring the process is launched asynchronously (not blocking Emacs)
  • configuring callbacks (by binding a sentinel to the process)

deferred

source & doc

Not super-actively maintained, but featureful.

Also allows handling async Elisp function calls and HTTP calls with request.el bindings.

bpr

source & doc

Stands for Background Process Runner. Allows running a command process in the background.

Allows advanced callback behaviours.

It relies on start-process-shell-command.

pfuture

source & doc

Allows running a command process in the background.

Result can be handled either with a future (pfuture-new, pfuture-result) or a callback (pfuture-callback).

It relies on make-pipe-process for the future-based implementation and make-process for the callback one.

Async interpreter commands

Emacs provides a layer on top of make-process for spawning commands from a shell interpreter (i.e. bash or zsh).

These are provided by simple.el (source).

The async version of these command is async-shell-command.

Some advanced behaviours are hard to program, that’s why wrapper libraries can help you.

dtache

source & doc

Provides dtache-shell-command, a drop-in replacement for async-shell-command that allows command execution to persist even after the Emacs process exits.

Also works on remote hosts.

Relies on dtach to create a persistent session.

friendly-shell-command

source & doc

friendly-shell-command provides friendly-shell-command-async, a wrapper around async-shell-command with easier access to advanced behaviours thanks to optional keyword arguments.

It notably eases associating a callback to the end of the execution, running on remote hosts and launching with alternative interpreters.

Buffer Manipulation

b

source & doc

Utility functions for buffer manipulation.

tp

source

Utilities for helping with manipulating a buffer’s text properties.

m-buffer

doc, source

List-oriented functions for accessing and manipulating the contents of Emacs buffers.

Filesystem Interactions

f

source & doc

./rsc/icon/informal-standard.png

Modern API for working with files and directories.

Networking

HTTP client

Emacs comes already with an HTTP client, url.el, written in pure Elisp (source), which has a few limitations. It exposes functions url-retrieve-synchronously and url-retrieve (async).

request

source & doc

./rsc/icon/informal-standard.png

If found on the system, uses the cURL binary instead of url.el. Can be customized with request-backend.

Supports a bunch of options exposed clearly with keyword arguments.

Advanced asynchronicity via bindings with deferred.

plz

source & doc

Uses the cURL binary (curl) instead of url.el.

Supports a bunch of options exposed clearly with keyword arguments.

Supports both synchronous & asynchronous calls, as well as queuing.

When doing async request, the returned handler is a curl process object.

Strong contender for a lightweight alternative to request.

mb-url

source & doc

Stands for “Multiple Backends for URL package”.

Provides API-compatible replacements to url-retrieve and url-retrieve-synchronously using cURL and HTTPie.

websocket

source

./rsc/icon/informal-standard.png

Websocket (peristent HTTP connection) client for Emacs.

apiwrap

source & doc

Macros to ease the definition of binding functions to HTTP APIs.

with-proxy

source & doc

Wrapper for let-binding HTTP proxies.

HTTP server

simple-httpd

source & doc

A web server written in pure Elisp, serving HTTP.

web-server

source & doc

A web server written in pure Elisp, serving HTTP APIs bound to Elisp functions (handlers).

RPC server

A Remote Procedure Call server allows Emacs to receive commands from a remote process through a messaging system.

It’s a common strategy of inter-process communication (IPC).

porthole

source & doc

Start a HTTP-based RPC server under Emacs.

Commands are direct Elisp code to be executed. They can (by default) only be called synchronously.

Messages are encoded in JSON (following the JSON-RPC 2.0 Specification) which makes it support client libraries of almost any language.

Relies on web-server.

EPC

source & doc

Start a RPC client & server under Emacs.

It implements its own protocol (over TCP) and support both synchronous & asynchronous execution (via bindings with deferred).

Commands are explicitly defined (akin to handlers bound to routes in an HTTP API).

Messages are encoded as Lisp / S-exprs, which makes it more challenging to implement client libraries in non-Lisp languages.

D-Bus

D-Bus is the most popular inter-process communication (IPC) protocol under Linux.

Emacs supports it by default.

dbus

doc, source

./rsc/icon/standard.png

Very boilerplate-y to use.

debase

source & doc

EIEIO abstractions over dbus for writting easier interaction code.

Database Access

SQL

sql

./rsc/icon/standard.png

source, emacswiki

Not a client per se.

Provides sql-mode, a comint-based REPL wrapper supporting various CLI client interpreters.

sqlite

./rsc/icon/standard.png (since version 29)

Recent Emacs now embbeds a native SQLite3 database & the accompagnying client.

emacsql

source & doc

High-level client to SQLite, PostgreSQL & MySQL.

Queries and schema definitions are written in specific tree-based DSLs, allowing easy programmatic manipulation.

closql

source

ORM providing mapping between EIEIO and SQLite tables.

Relies on emacsql.

edbi

source & doc

Client to SQL dialects, using Perl’s Database Interface (DBI) as a connection interface.

In addition to programmatic querying capabilities, provides several major modes for user interactions with database instances.

triples

source & doc

Abstraction on top of SQL clients (either emacsql or sqlite) to represent & store a graph database.

GUI

Honorable mention: magic-buffer, an executable cookbook on how to use & abuse Emacs’ buffer display engine.

Popups

frog-menu

source & doc

User selection menu in the form of a popup.

Overlays

ov

source & doc

Helpers to manipulate overlays. Originally authored by @ShingoFukuyama. Unmaintained.

Charts & diagrams

chart

tutorial

./rsc/icon/standard.png

Heroes

Emacs has too many heroes to really list.

In this section, we list some users who have significantly contributed with libraries and resources that improve the Emacs development experience.

They are listed in alphabetical order.

Another complementary list is elisp-maintainers.

@alphapapa

github

Contributed to Elisp development with:

Bozhidar Batsov (@bbatsov)

github, Emacs-related blog, open to sponsoring

Known for:

  • projectile: the best project management package for Emacs
  • CIDER: the interactive Clojure development environment for Emacs

Contributed to Elisp development with:

Caio Rordrigues (@caiorss)

github

Contributed to Elisp development with:

Chris Wellons (@skeeto)

github, blog

Known for:

  • elfeed, the popular Emacs RSS reader
  • skewer-mode, interactive web development with auto-reload on edit

Contributed to Elisp development with:

  • his blog, nullprogram.com
  • aio
  • emacsql
  • simple-httpd
  • week-ref

John Wiegley (@jwiegley)

blog, github, dot emacs

Known for:

  • being the head of the Emacs project maintainers
  • authoring use-pacakge

Contributed to Elisp development with:

Jonas Bernoulli (@tarsius)

blog, github, open to sponsoring

Known for:

Contributed to Elisp development with:

Magnar Sveen (@magnars)

github, twitter

Contributed to Elisp development with:

  • s (strings)
  • dash (lists)

Nicolas Petton

portfolio, blog, github

Known for:

  • creating the popular Indium interactive Javascript development environment

Contributed to Elisp development with:

  • creating the now standard seq.el and map.el
  • stream.el

Oleh Krehel (@abo-abo)

blog, github, open to sponsoring

Author of many high-quality packages such as ivy, hydra, lispy

Toby ‘qubit’ Cubitt

website

Known for:

Contributed to Elisp development with his implementation of basic and more complex data structures: queue, heap, avl-tree, trie, dict-tree, tNFA.

Xah Lee

website, open to sponsoring

A controversial figure in the Emacs community (he is notorious for trolling), Xah nethertheless created the first online digestible resource for learning Elisp.

His contribution to the Emacs world is unquestionable and as such he deserves his place in this list.

Contributing

Contributions and suggestions are always welcome!

The original author made this document available as he felt something like it was missing.

The idea is to have this evolve into a community effort, the initial version being only a baseline.

Guidelines

PR and Issues

Open one issue or PR / subject matter.

Don’t go submit a gazillion unrelated changes that would conflict with other’s submitted PRs.

Opinions

Try to not be too opinionated.

Some solutions are objectively better in some regards than others and that can be stated but don’t go launch a flame war.

Descriptions of libraries and tools expressed in this document are always subject to change. If a description feels too negative, don’t hesitate to open an issue to discuss it.

Scope

The aim of this document is to (loosely) follow the style of other awesome lists.

Content should be concise and always follow the same format.

In this spirit, no block quotes, no code snippets and no in-depth explanation of concepts should appear here.

This is no cookbook, no manual, no article.

Section can have small introduction to contextualize things (e.g. built-in libs) but should remain succinct, instead favoring links to external articles.

The introduction of the Concurrency / Asynchronicity is a good example of concisely presenting the necessary information and linking to external resources.

On the contrary, the Maps section goes into too much details and should instead link to an article.

Relevant Content: Development Tools

In Development Tools, only list tools and package that are specific to Elisp development.

It’s very tempting to list stuff such as projectile or treemacs but those packages apply not only to Elisp development and should not be listed.

Don’t create a sub-section for tools that have modern counterpart and are deprecated / no more maintained. You could eventually mention them like it’s done for highlight-defined in Syntax Highlighting & Visual Enhancements.

Relevant Content: Libraries

In Libraries, only list packages that were created to be used as libraries and generic enough to target a broad range of applications.

E.g. HTTP client libs such as request have their place, wrappers targeting a specific API (such as ghub or pocket-lib) don’t.

Comments

Each linked resource / tool / library should be commented.

This comment is a short intro and analysis and must not be copy-pasted directly from the linked resource page.

Instead it should provide insights as to how it compares to other links in a similar category: what are the differences, advantages, drawbacks.

This description should be short and ideally not exceed a few lines.

Order of Tools & Libraries

Try to put the most “standard” entries first.

By standard we mean, in order: embedded in Emacs, most sane or used by the most people / projects.

Order of Categories

Don’t submit a PR single-handedly deciding to reorganize the whole document structure.

Open an issue and provoke conversation.

What can feel natural to you can be counter-intuitive to others.

License & Acknowledgments

https://licensebuttons.net/p/zero/1.0/88x31.png

Ribbon icons courtesy of icons8.

About

🏵️ A curated list of emacs-lisp development resources

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published