Updated: 2025-12-21
[2025-12-20]

Tips on Emacs Lisp Development for Contributing to Org-mode

In this post I will discuss how I generally setup a development environment for contributing code to Emacs Org-mode. As well as provide some Emacs Lisp development tips I have learned over the years. This post goes a bit beyond beyond what is covered in the Contributing to Org webpage, and covers info that may useful for contributing to any elisp project.

I've gained many of these tips slowly over the years, so I hope sharing this will help others in their elisp journey. There are likely still many workflow improvements I am overlooking. If you notice such gaps please let me know! Although do note I tend to prefer minimal built-in solutions over large packages (e.g. flymake over flycheck).

Prerequisites

In order to proceed you will need some basic knowledge of git and emacs. If you do not know how to use git the Contributing to Org webpage provides some suggestions on how to create a basic diff instead.

You'll need emacs, git, and make installed on your system.

sudo apt install emacs git make

Download and Install the Org-mode Source Code

We can clone the latest version from within Emacs using the package-vc-install which was added in Emacs 29.1. This will ensure you are actively running the current Org version inside Emacs. Note this process can take around 10+ minutes as all of Org is downloaded and compiled.

M-x package-vc-install [RET] org [RET]

Once completed we can confirm we are running a development version by checking the M-x org-version

Org mode version 9.7.11 (release_9.7.11 @ /home/thomas/.config/emacs/elpa/org/lisp/)

As we can see this latest git version of Org has been installed in our ELPA package directory. We can open that directory and start work.

Manual Install

If you wish to download the source code manually you can clone the repository directly with git from the GNU Savannah website.

git clone https://git.savannah.gnu.org/cgit/emacs/org-mode.git/

Then you will need to manually build and install the development version of Org. The included make file provides several options for how to install Org, see Org-mode Build System for more details.

For full options run "make help". For a basic install into your Emacs use "make install" or "make clean-install". The latter will attempt to remove any other versions of Org being used. Be careful to save any changes if you've already started modifying the Org source code. Alternatively, if you do not want to override your current Emacs environment you can use "make vanilla"" to run an unconfigured version of Emacs with the current Org source code.

make install

You can either run the make commands in the terminal or inside Emacs. In Emacs, open the directory in Emacs dired (C-x d) then run M-x compile then enter your preferred make options.

Add Helpful Git Hook Warnings

The Org mode source code provides helpful warnings regarding commit message formatting etc. To enable them run the following inside the directory. Run from a terminal or with M-x compile:

make githooks

Bookmark the Org Directory

The first thing I like to do when setting up a new development project is adding it to my Emacs bookmarks. So I'll visit the directory with:

C-x C-d (list-directory) ~/.config/emacs/elpa/org/

Then I'll create a bookmark on the lisp folder by placing the point there and running:

C-x r m (bookmark-set) to create a bookmark.

Next time we can navigate to the bookmark using:

  • C-x r l (bookmark-list) to show a list of bookmarks, like list-buffers.
  • C-x r b (bookmark-jump) to open a bookmark, like switch-to-buffer.

Navigating the Source Code

After Org is installed all your usual emacs help commands will direct you to the Org git repository.

  • C-h f (describe-function) search functions documentation.
  • C-h k (describe-key) lookup the function bound to a key binding.
  • C-h v (describe-variable) lookup variable documentation.

The commands will open a *Help* buffer describing the function or variable with a link to the Emacs Lisp source code. Those links will now jump straight the definition in to the repository we downloaded.

Once inside a source file navigate around using xref. When the cursor is placed on a global variable or function xref can jump straight to its definition. This is very helpful for quickly walking up the function call chain to better understand how the code is working.

  • M-. (xref-find-definitions) to jump to the definition of the function/variable at the point.
  • M-, (xref-go-back) to return back to the previous point location.

Evaluating Changes

After making some changes I'll usually just start by re-evaluating the defun and variables then manually test if things are working as expected. Evaluating defuns can be done quickly with C-M-x (eval-defun) which I rebind to C-c C-d. If you are making lots of changes you can use eval-buffer which I bind to C-c C-b. If you break something you can always revert your changes with git.

If you want to quickly try out some dummy code consider trying M-x ielm. It is the Emacs Lisp REPL and it can make testing code pretty fun. Especially useful when you don't know exactly what functions are going to output.

Testing

To catch compilations warnings I recommend compiling your changed files with the Emacs Lisp byte compiler. I define the following custom bindings:

  • C-c C-f (elisp-byte-compile-file) compile file but do not load it. Useful for catching errors. Warning it will get loaded next time you start Emacs.
  • C-c C-l (emacs-lisp-byte-compile-and-load) compile the file and load it.

Some of this checking can be enabled automatically with in-buffer warnings using the included flymake package. Test it out with M-x flymake-mode in an elisp file. Enable it in your init file with:

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

Automated Tests

Once you've confirmed with that the changes are working as expected, then it's a good time to check it passes all of Org's automated test suite. From the terminal or M-x compile run:

make test

Committing Changes

For working with git I generally use magit, although I have been investigating1 , 2 using vc the built-in version control tool.

Magit makes it relatively easy to take a whole bunch of changes and break them up into reasonable commits. This can be done using the stage and unstage functionality. Then for greater granularity you can select diff sections with C-SPC then s or k to include or exclude certain changes. This helps me keep my git commits clean and avoid committing unfinished sections.

My understanding is some of this functionality is possible with vc from vc-dir (C-x v d) and by editing the diff directly. So far I have found the workflow to be somewhat less intuitive because vc lacks the stage/unstage concept. Although I am biased because the only version control system I have used is git with magit.

Submit a Patch

Magit can easily create a patch for any commit range with the W command. Patches can be attached to an email and sent to the org-mode mailing list for discussion. Note they have specific commit message formatting requirements discussed in detail on the contributing webpage.

See Also

Footnotes:

1

Emacs: workflow with VC for Git youtube.com — Protesilaos Stavrou

2

Why I Prefer VC Over Magit youtube.com — Thanos Apollo

Comments

Email comments to comment@taingram.org.