Hacking on CIDER

This section explains the process of working with CIDER’s codebase (e.g. to fix a bug or implement some new feature). It outlines the recommended workflows when working on the Emacs Lisp side (CIDER) and the Clojure side (cider-nrepl).

Hacking on CIDER (Elisp)

Obtaining the source code

People typically install CIDER via package.el. While this gives you access the source code (as it’s part of the package), it’s always a much better idea to simply clone the code from GitHub and use it. In general - avoid editing the code of an installed package.

Alternatively you can simply load CIDER in your Emacs straight from its source repo (you’ll have to manually install all the packages CIDER depends on in advance).

CIDER uses Eldev for development, so you should install the tool first.

The easiest and "purest" way to run CIDER is to execute:

eldev emacs

This will start a separate Emacs process with CIDER and its dependencies available, but without your normal packages installed. However, you can use Eldev-local to add some packages with (eldev-add-extra-dependencies 'emacs …​) forms. See Eldev documentation for details.

Alternatively, if you want to load CIDER from source code in the Emacs you use for editing:

  1. Generate autoloads file (that’s done automatically when installing via package.el but you’ll have to do it manually in this case):

    eldev build :autoloads
  2. Add to your .emacs:

    ;; load CIDER from its source code
    (add-to-list 'load-path "~/projects/cider")
    (load "cider-autoloads" t t)

Changing the code

It’s perfectly fine to load CIDER from package.el and then to start making experiments by changing existing code and adding new code.

A very good workflow is to just open the source code you’ve cloned and start evaluating the code you’ve altered/added with commands like C-M-x, eval-buffer and so on.

Once you’ve evaluated the new code, you can invoke some interactive command that uses it internally or open a Emacs Lisp REPL and experiment with it there. You can open an Emacs Lisp REPL with M-x ielm.

You can also quickly evaluate some Emacs Lisp code in the minibuffer with M-:.

Testing the code

The code you’ve wrote should ideally be covered by specs. We use the buttercup library for CIDER’s specs. If you’re familiar with Jasmine or RSpec you’ll feel right at home.

You can run the specs you authored/changed straight from Emacs. Consult the buttercup documentation for all the details.

Running the tests in batch mode

If you prefer running all tests outside Emacs that’s also an option.

There are two test types, main (unit tests) and integration. By default only main tests are run.

Run all unit tests with:

$ eldev[.bat] test

Run integration tests with:

$ eldev[.bat] test --test-type integration

or all tests with:

$ eldev[.bat] test --test-type all
Tests may not run correctly inside Emacs' shell-mode buffers. Running them in a terminal is recommended.

You can also check for compliance with a variety of coding standards in batch mode (including docstrings):

$ eldev lint

To check for byte-compilation warnings you can just compile the project with Eldev:

$ eldev compile

Running the tests in CircleCI

If you prefer to see the full CircleCI CI test suite run successfully, the easiest way to achieve that is to create your own personal account on https://circleci.com. Fork CIDER on GitHub, and then add your fork on CircleCI to start building. Every time you push code to a branch, CircleCI will build it.

Subsequent pushes to your fork will generate a CircleCI build you can monitor for success or failure.

Simulating the Circle CI tests locally in Docker

If you prefer not to wait for CircleCI all the time, or if you need to debug something that fails in CircleCI but does not fail for you on your own machine, then you can also run the CircleCI tests locally with the CircleCI CLI (that’s a mouthful!).

To do this, first install the CircleCI CLI, and Docker.

Currently the CircleCI CLI doesn’t support local builds with version 2.1 of the CircleCI config, so for now we need to convert it to the 2.0 format. Make sure not to commit these changes to the config.yml file.

$ circleci config process .circleci/config.yml > .circleci/config.yml.tmp && \
    mv .circleci/config.yml.tmp .circleci/config.yml

Now, we’re finally ready to run a CircleCI container on our machine. Run circleci local execute --job=<job> where <job> is one of those listed in .circleci/config.yml, e.g. test-emacs-26.

$ circleci local execute --job=test-emacs-26
Docker image digest: sha256:65b2102646d5658f892e0ad8253b7912c676126c857c87c8c12460f0aa4f5aa1
====>> Spin up Environment
Build-agent version 1.0.8563-43047892 (2019-03-06T15:11:54+0000)
Starting container silex/emacs:26-dev
  image cache not found on this host, downloading silex/emacs:26-dev
26-dev: Pulling from silex/emacs
6cf436f81810: Already exists
987088a85b96: Already exists
e58f362a948a: Waiting
...
====>> make elpa
  #!/bin/bash -eo pipefail
make elpa
Compute dependencies
cask install
Loading package information... done
Package operations: 10 installs, 0 removals
...
Indenting region...
Indenting region...done
* Run indent-character
* Run trailing-whitespace
** ELISP-LINT: cider-overlays.el OK
Success!

This may take a while to download the CircleCI build agent and the build containers the first time you run the tests locally.

MS-Windows compatibility

In general, CIDER code should work as well on Windows as it does on Unix.

There are a few points to be aware of when contributing code or writing tests.

  1. Absolute paths. It is a common practice to use dummy absolute paths, such as /tmp/a-dir or /docker/src, in tests, as test inputs. These are not valid absolute paths on Windows though, since they are missing the initial driver letter (e.g.c:/tmp/a-dir), but we can wrap them around with expand-file-name to make them so e.g. in tests

    (let ((a-dir (expand-file-name "/tmp/a-dir"))
          (docker-src (expand-file-name "/docker/src")))
      ;; ...
      )
  2. Command-line arguments. When calling external programs, it might be necessary to quote some long command line arguments, though quoting rules are different on Windows (shells) that they are on Unix. Use shell-quote-argument to achieve the desired compatibility across the different architectures.

Hacking on cider-nrepl (Clojure)

Obtaining the code

Just clone it from GitHub.

Changing the code

Just do cider-jack-in within the cider-nrepl project and start hacking as you would on any other Clojure project. The only thing to keep in mind is that you’ll have to restart CIDER when you add new middleware.

The jacked-in project’s definitions will take precedence over the once you have from a binary cider-nrepl installation. This means it’s pretty easy to get immediate feedback for the changes you’ve made.

Testing the code

The code you’ve wrote should ideally be covered by test. We use the clojure.test library for cider-nrepl's tests.

You can run the tests you authored/changed straight from Emacs. Consult the CIDER documentation for all the details.

Running the tests in batch mode

You can also run the tests in an external shell. Running lein test won’t run pretty much anything, though. (perhaps we should change this?) To run the Clojure and ClojureScript tests you should specify some profile like this:

$ lein with-profile +1.8,+test-clj test
$ lein with-profile +1.8,+test-cljs test

This will run all Clojure and ClojureScript tests against version 1.8 of both languages.