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 in 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 differently.
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 a 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 a 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)