Indentation

CIDER relies on clojure-mode to do the indentation of Clojure code. While clojure-mode will generally indent code "the right way" from time to time you might want to teach it how to indent certain macros.

There are two ways to do this - you can either add some indentation configuration in your Emacs config or you can add it to your Clojure code and let CIDER generate the necessary configuration for clojure-mode automatically. We’ll refer to the first approach as "static indentation" and to the second one as "dynamic indentation".

Static Indentation

Everything is this section will work as described even if CIDER is not present/active. Static indentation doesn’t require a REPL to work.

clojure-mode is smart enough to indent most Clojure code correctly out-of-the-box, but it can’t know if something is a macro and its body should be indented different.

clojure-mode is very flexible when it comes to indentation configuration and here we are going to go over the basics.

Indentation Modes

There are few common ways to indent Clojure code and all of them are supported by clojure-mode.

The indentation of function forms is configured by the variable clojure-indent-style. It takes three possible values:

  • always-align (the default)

(some-function
 10
 1
 2)
(some-function 10
               1
               2)
  • always-indent

(some-function
  10
  1
  2)
(some-function 10
  1
  2)
  • align-arguments

(some-function
  10
  1
  2)
(some-function 10
               1
               2)
You can read more about the indentation options in clojure-mode here.

Macro Indentation

As mentioned earlier clojure-mode can’t know if something in your code is a macro that has to be indented differently from a regular function invocation (most likely because the macro takes some forms as parameters). In such situation you need to teach clojure-mode how to indent the macro in question. Consider this simple example:

(defmacro with-in-str
  "[DOCSTRING]"
  {:style/indent 1}
  [s & body]
  ...cut for brevity...)

;; Target indentation
(with-in-str str
  (foo)
  (bar)
  (baz))

To get clojure-mode to indent it properly you’ll need to add the following code to your Emacs config:

(put-clojure-indent 'with-in-str 1)

;; or

(define-clojure-indent
  (with-in-str 1)
You can find more details here.

Dynamic Indentation

It is common for macros to require special indentation mechanisms. This is most common in macros that start with do, def, or with-. CIDER has some heuristics to detect these macros, but it also lets you explicitly specify how a macro should be indented.

Here’s a simple example of how someone would specify the indent spec for a macro they’ve written (using an example in core):

(defmacro with-in-str
  "[DOCSTRING]"
  {:style/indent 1}
  [s & body]
  ...cut for brevity...)

;; Target indentation
(with-in-str str
  (foo)
  (bar)
  (baz))

And here’s a more complex one:

(defmacro letfn
  "[DOCSTRING]"
  {:style/indent [1 [[:defn]] :form]}
  [fnspecs & body]
  ...cut for brevity...)

;; Target indentation
(letfn [(six-times [y]
           (* (twice y) 3))
        (twice [x]
           (* x 2))]
  (println "Twice 15 =" (twice 15))
  (println "Six times 15 =" (six-times 15)))

Don’t worry if this looks intimidating. For most macros the indent spec should be either just a number, or one of the keywords :defn or :form. A full description of the spec is provided in the indent spec section of the manual.

If you don’t want to use this feature, you can disable it by setting cider-dynamic-indentation to nil in your Emacs init file.

(setq cider-dynamic-indentation nil)