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
- Contributing to Org orgmode.org
- Org-mode Build System orgmode.org
- Pro Git git-scm.com — Scott Chacon
Footnotes:
Emacs: workflow with VC for Git youtube.com — Protesilaos Stavrou
Why I Prefer VC Over Magit youtube.com — Thanos Apollo
Comments
Email comments to comment@taingram.org.