Skip to content

Commit 1e8a0f7

Browse files
committed
[Fix #329] Document the new backtracking indent spec in the Readme
1 parent a9e44f9 commit 1e8a0f7

File tree

2 files changed

+62
-25
lines changed

2 files changed

+62
-25
lines changed

README.md

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,6 @@ You can do so by putting the following in your config:
7373
(put-clojure-indent '->> 1)
7474
```
7575

76-
You can also specify different indentation settings for symbols
77-
prefixed with some ns (or ns alias):
78-
79-
```el
80-
(put-clojure-indent 'do 0)
81-
(put-clojure-indent 'my-ns/do 1)
82-
```
83-
8476
This means that the body of the `->/->>` is after the first argument.
8577

8678
A more compact way to do the same thing is:
@@ -91,32 +83,77 @@ A more compact way to do the same thing is:
9183
(->> 1))
9284
```
9385

86+
You can also specify different indentation settings for symbols
87+
prefixed with some ns (or ns alias):
88+
89+
```el
90+
(put-clojure-indent 'do 0)
91+
(put-clojure-indent 'my-ns/do 1)
92+
```
93+
9494
The bodies of certain more complicated macros and special forms
9595
(e.g. `letfn`, `deftype`, `extend-protocol`, etc) are indented using
96-
a contextual backtracking indentation method, controlled by
97-
`clojure-backtracking-indent`. Here's some example config code:
96+
a contextual backtracking indentation method, require more sophisticated
97+
indent specifications. These are described below.
98+
99+
### Indent Specification
100+
101+
An indent spec can be used to specify intricate indentation rules for
102+
the more complex macros (or functions).
103+
It can take one of 3 forms:
104+
105+
- Absent, meaning _“indent like a regular function call”_.
106+
- An integer or a keyword `x`, which is shorthand for the list `(x)`.
107+
- A list, meaning that this function/macro takes a number of special arguments, and then all other arguments are non-special.
108+
- **The first element** describes how the arguments are indented relative to the sexp. It can be:
109+
- An integer `n`, which indicates this function/macro takes `n` special arguments.
110+
- The keyword `:function`, meaning _“indent like a regular function call”_.
111+
- The keyword `:defn`, which means _“every arg not on the first line is non-special”_.
112+
- **Each following element** is an indent spec on its own, and it details the internal structure of the argument on the same position as this element. So, when that argument is a form, this element specifies how to indent that form internally (if it's not a form the spec is irrelevant).
113+
- If the function/macro has more aguments than the list has elements, the last element of the list applies to all remaining arguments.
114+
115+
#### Examples
116+
117+
So, for instance, if I specify the `defrecord` spec as `(2 nil nil (1))`, this is saying:
118+
119+
- `defrecord` has 2 special arguments
120+
- The first two arguments don't get special internal indentation
121+
- All remaining arguments have an internal indent spec of `(1)` (which means only the arglist is indented specially and the rest is the body).
122+
123+
For something more complicated: `letfn` is `(1 ((:defn)) nil)`. This means
124+
125+
- `letfn` has one special argument (the bindings list).
126+
- The first arg has an indent spec of `((:defn))`, which means all forms _inside_ the first arg have an indent spec of `(1)`.
127+
- The second argument, and all other arguments, are regular forms.
128+
129+
```
130+
(letfn [(twice [x]
131+
(* x 2))
132+
(six-times [y]
133+
(* (twice y) 3))]
134+
(println "Twice 15 =" (twice 15))
135+
(println "Six times 15 ="
136+
(six-times 15)))
137+
```
138+
139+
A few more examples:
98140

99141
```el
100-
(put 'implement 'clojure-backtracking-indent '(4 (2)))
101-
(put 'letfn 'clojure-backtracking-indent '((2) 2))
102-
(put 'proxy 'clojure-backtracking-indent '(4 4 (2)))
103-
(put 'reify 'clojure-backtracking-indent '((2)))
104-
(put 'deftype 'clojure-backtracking-indent '(4 4 (2)))
105-
(put 'defrecord 'clojure-backtracking-indent '(4 4 (2)))
106-
(put 'defprotocol 'clojure-backtracking-indent '(4 (2)))
107-
(put 'extend-type 'clojure-backtracking-indent '(4 (2)))
108-
(put 'extend-protocol 'clojure-backtracking-indent '(4 (2)))
109-
(put 'specify 'clojure-backtracking-indent '(4 (2)))
110-
(put 'specify! 'clojure-backtracking-indent '(4 (2)))
142+
(define-clojure-indent
143+
(implement '(1 (1)))
144+
(letfn '(1 ((:defn)) nil))
145+
(proxy '(2 nil nil (1)))
146+
(reify '(:defn (1)))
147+
(deftype '(2 nil nil (1)))
148+
(defrecord '(2 nil nil (1)))
149+
(specify '(1 (1)))
150+
(specify '(1 (1))))
111151
```
112152

113153
Don't use special indentation settings for forms with names that are not unique,
114154
as `clojure-mode`'s indentation engine is not namespace-aware and you might
115155
end up getting strange indentation in unexpected places.
116156

117-
Please, see the docstrings of the Emacs Lisp functions/vars noted above for
118-
information about customizing this indentation behavior.
119-
120157
## Related packages
121158

122159
* [clojure-mode-extra-font-locking][] provides additional font-locking

clojure-mode.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ it from Lisp code, use (put-clojure-indent 'some-symbol :defn)."
895895

896896
;; binding forms
897897
(let 1)
898-
(letfn '(1 ((1)) nil))
898+
(letfn '(1 ((:defn)) nil))
899899
(binding 1)
900900
(loop 1)
901901
(for 1)

0 commit comments

Comments
 (0)