@@ -196,10 +196,21 @@ Similarly we have the `clojure-indent-keyword-style`, which works in the followi
196196#### Indentation of macro forms
197197
198198The indentation of special forms and macros with bodies is controlled via
199- ` put-clojure-indent ` , ` define-clojure-indent ` and ` clojure-backtracking -indent` .
199+ ` put-clojure-indent ` and ` define-clojure -indent` .
200200Nearly all special forms and built-in macros with bodies have special indentation
201201settings in ` clojure-mode ` . You can add/alter the indentation settings in your
202- personal config. Let's assume you want to indent ` ->> ` and ` -> ` like this:
202+ personal config.
203+
204+ Indent specs use a ** modern tuple format** shared with ` clojure-ts-mode ` :
205+
206+ | Spec | Meaning |
207+ | ------| ---------|
208+ | ` '((:block N)) ` | First N args are special, rest indented as body |
209+ | ` '((:inner 0)) ` | All args indented as body (like ` defn ` ) |
210+ | ` '((:inner D)) ` | Body-style indent at nesting depth D |
211+ | ` '((:inner D I)) ` | Body-style at depth D, only at position I |
212+
213+ You can combine multiple rules. For example, let's say you want to indent ` ->> ` and ` -> ` like this:
203214
204215``` clojure
205216(->> something
@@ -211,8 +222,8 @@ personal config. Let's assume you want to indent `->>` and `->` like this:
211222You can do so by putting the following in your config:
212223
213224``` el
214- (put-clojure-indent '-> 1 )
215- (put-clojure-indent '->> 1 )
225+ (put-clojure-indent '-> '((:block 1)) )
226+ (put-clojure-indent '->> '((:block 1)) )
216227```
217228
218229This means that the body of the ` ->/->> ` is after the first argument.
@@ -221,24 +232,28 @@ A more compact way to do the same thing is:
221232
222233``` el
223234(define-clojure-indent
224- (-> 1 )
225- (->> 1 ))
235+ (-> '((:block 1)) )
236+ (->> '((:block 1)) ))
226237```
227238
228239To indent something like a definition (` defn ` ) you can do something like:
229240
230241``` el
231- (put-clojure-indent '>defn :defn )
242+ (put-clojure-indent '>defn '((:inner 0)) )
232243```
233244
234245You can also specify different indentation settings for symbols
235246prefixed with some ns (or ns alias):
236247
237248``` el
238- (put-clojure-indent 'do 0 )
239- (put-clojure-indent 'my-ns/do 1 )
249+ (put-clojure-indent 'do '((:block 0)) )
250+ (put-clojure-indent 'my-ns/do '((:block 1)) )
240251```
241252
253+ ** Note:** A legacy format using integers (e.g., ` 1 ` ), keywords (` :defn ` ), and
254+ positional lists (e.g., ` '(1 ((:defn)) nil) ` ) is also accepted for backward
255+ compatibility. It will be removed in clojure-mode 6.
256+
242257##### Backtracking (contextual) indentation
243258
244259Certain macros and special forms (e.g. ` letfn ` , ` deftype ` ,
@@ -248,65 +263,54 @@ indentation**: when indenting a line, it walks up the sexp tree to
248263find a parent form with an indent spec, then uses the current
249264position within that spec to decide how to indent.
250265
251- A backtracking indent spec is a ** quoted list** where each element
252- controls indentation at the corresponding argument position
253- (0-indexed). The allowed elements are:
254-
255- | Element | Meaning |
256- | ---------| ---------|
257- | An integer N | First N args are "special" (indented further); rest are body |
258- | ` :defn ` | Indent like a function/macro body |
259- | ` :form ` | Indent like a regular form |
260- | ` nil ` | Use default indentation rules |
261- | A list ` (SPEC) ` | This position holds a ** list of forms** , each indented according to SPEC |
262-
263- For example, ` letfn ` uses ` '(1 ((:defn)) nil) ` :
266+ Multi-rule specs combine ` :block ` and ` :inner ` rules to control
267+ nested indentation. For example, ` letfn ` uses ` '((:block 1) (:inner 2 0)) ` :
264268
265269``` clojure
266- (letfn [(twice [x] ; ; pos 0 → spec 1 (1 special arg = the binding vector)
267- (* x 2 )) ; ; inside binding → spec ((:defn)) applies:
268- (thrice [x] ; ; each binding is a list of :defn -style forms
269- (* x 3 ))] ; ; so function bodies get :defn indentation
270- (+ (twice 5 ) ; ; pos 1+ → spec nil (default → body indentation)
270+ (letfn [(twice [x] ; ; (:block 1) → 1 special arg ( the binding vector)
271+ (* x 2 )) ; ; (:inner 2 0) → at depth 2, position 0 in the binding
272+ (thrice [x] ; ; vector, use body -style indentation
273+ (* x 3 ))]
274+ (+ (twice 5 ) ; ; after the block arg → body indentation
271275 (thrice 5 )))
272276```
273277
274- And ` defrecord ` uses ` '(2 nil nil (:defn )) ` :
278+ And ` defrecord ` uses ` '((:block 2) (:inner 1 )) ` :
275279
276280``` clojure
277- (defrecord MyRecord ; ; pos 0 → spec 2 (2 special args: name + fields)
278- [field1 field2] ; ; pos 1 → spec nil (within special args zone)
279- SomeProtocol ; ; pos 2 → spec nil
280- (some-method [this] ; ; pos 3+ → spec (:defn) — each method gets :defn -style
281+ (defrecord MyRecord ; ; (:block 2) → 2 special args ( name + fields)
282+ [field1 field2]
283+ SomeProtocol ; ; (:inner 1) → nested sub-forms at depth 1
284+ (some-method [this] ; ; get body -style indentation
281285 (do-stuff this)))
282286```
283287
284- Here are the built-in backtracking specs:
288+ Here are the built-in multi-rule specs:
285289
286290``` el
287291(define-clojure-indent
288- (letfn '(1 ((:defn)) nil ))
289- (deftype '(2 nil nil (:defn )))
290- (defrecord '(2 nil nil (:defn )))
291- (defprotocol '(1 (:defn )))
292- (definterface '(1 (:defn )))
293- (reify '(:defn ( 1)))
294- (proxy '(2 nil nil (:defn )))
295- (extend-protocol '(1 :defn ))
296- (extend-type '(1 :defn ))
297- (specify '(1 :defn ))
298- (specify! '(1 :defn )))
292+ (letfn '((:block 1) (:inner 2 0) ))
293+ (deftype '((:block 2) (:inner 1 )))
294+ (defrecord '((:block 2) (:inner 1 )))
295+ (defprotocol '((:block 1) (:inner 1 )))
296+ (definterface '((:block 1) (:inner 1 )))
297+ (reify '((:inner 0) (:inner 1)))
298+ (proxy '((:block 2) (:inner 1 )))
299+ (extend-protocol '((:block 1) (:inner 0) ))
300+ (extend-type '((:block 1) (:inner 0) ))
301+ (specify '((:block 1) (:inner 0) ))
302+ (specify! '((:block 1) (:inner 0) )))
299303```
300304
301- These follow the same rules as the ` :style/indent ` metadata specified by [ cider-nrepl] [ ] .
305+ This format is shared with ` clojure-ts-mode ` . It also follows the same
306+ rules as the ` :style/indent ` metadata specified by [ cider-nrepl] [ ] .
302307For more details on writing indent specifications, see
303308[ this document] ( https://docs.cider.mx/cider/indent_spec.html ) .
304- The only difference is that you're allowed to use lists instead of vectors.
305309
306310Backtracking is controlled by ` clojure-use-backtracking-indent `
307311(default ` t ` ) and limited to ` clojure-max-backtracking ` levels
308312(default 3). Disabling backtracking will break indentation for
309- all forms with list-based specs.
313+ all forms with multi-rule specs.
310314
311315The indentation of [ special arguments] ( https://docs.cider.mx/cider/indent_spec.html#special-arguments ) is controlled by
312316` clojure-special-arg-indent-factor ` , which by default indents special arguments
0 commit comments