|
| 1 | +# Indentation |
| 2 | + |
| 3 | +When we talk about how rules affect indentation of source code, we |
| 4 | +refer to <code>(foo arg<sub>1</sub> arg<sub>2</sub>... |
| 5 | +arg<sub>n</sub>)</code> as a form, `foo` as a form symbol, and |
| 6 | +<code>arg<sub>1</sub> arg<sub>2</sub> ... arg<sub>n</sub></code> as |
| 7 | +form arguments. |
| 8 | + |
| 9 | +The default indentation rules are encoded |
| 10 | +[here](cljfmt/resources/cljfmt/). |
| 11 | + |
| 12 | +Rules affect indentation of form arguments. A form argument is |
| 13 | +eligible for indentation only when it is the first element on a line. |
| 14 | + |
| 15 | +An indentation rule specifies an indentation type and indentation type |
| 16 | +arguments. One or more rules can be applied to a form symbol. |
| 17 | + |
| 18 | +Indentation types are: |
| 19 | + |
| 20 | +* `:inner` - |
| 21 | + two character indentation applied to form arguments at a depth |
| 22 | + relative to a form symbol |
| 23 | + |
| 24 | +* `:block` - |
| 25 | + first argument aligned indentation applied to form arguments at form |
| 26 | + depth 0 for a symbol |
| 27 | + |
| 28 | +## Form depth |
| 29 | + |
| 30 | +A rule for depth n affects indentation of form arguments relative to |
| 31 | +form symbol at depth n. |
| 32 | + |
| 33 | +Form depth is the nested depth of any element within the form. |
| 34 | + |
| 35 | +A contrived example will help to explain depth: |
| 36 | + |
| 37 | +```clojure |
| 38 | +(foo |
| 39 | + bar |
| 40 | + (baz |
| 41 | + (qux plugh) |
| 42 | + corge) |
| 43 | + (grault |
| 44 | + waldo |
| 45 | + (thud wubble flob))) |
| 46 | +``` |
| 47 | + |
| 48 | +If we look at the example code as a tree, we can visualize the effect |
| 49 | +of different form depths relative to `foo`: |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | + |
| 54 | + |
| 55 | +## Default behavior |
| 56 | + |
| 57 | +In the absence of indentation rules: |
| 58 | + |
| 59 | +```clojure |
| 60 | +(foo bar (foo bar |
| 61 | +baz == formats to => baz |
| 62 | +bang) bang) |
| 63 | +``` |
| 64 | + |
| 65 | +```clojure |
| 66 | +(foo (foo |
| 67 | +bar == formats to => bar |
| 68 | +bang) bang) |
| 69 | +``` |
| 70 | + |
| 71 | +## Inner rules |
| 72 | + |
| 73 | +The `:inner` rule applies an indentation of two spaces to all eligible |
| 74 | +form arguments of forms at a given form depth. It has 2 rule type |
| 75 | +arguments: |
| 76 | + |
| 77 | +* `form-depth` - |
| 78 | + apply inner indentation within forms at this depth |
| 79 | + |
| 80 | +* `limit-to-form-index` - |
| 81 | + optionally limit indentation formatting to a single form, by default |
| 82 | + formatting is applied to all forms at `form-depth` |
| 83 | + |
| 84 | +Indent rule: |
| 85 | + |
| 86 | +```clojure |
| 87 | +{foo [[:inner 0]]} |
| 88 | +``` |
| 89 | + |
| 90 | +Will indent all arguments for symbol `foo` at depth `0` by two spaces: |
| 91 | + |
| 92 | +```clojure |
| 93 | +(foo bar (foo bar |
| 94 | +baz == formats to => baz |
| 95 | +bang) bang) |
| 96 | +``` |
| 97 | + |
| 98 | +Indent rule: |
| 99 | + |
| 100 | +```clojure |
| 101 | +{foo [[:inner 1]]} |
| 102 | +``` |
| 103 | + |
| 104 | +Results in `:inner` indenting form arguments at depth `1`. Form |
| 105 | +`(bang...)` is at depth `1` so its arguments are affected: |
| 106 | + |
| 107 | +```clojure |
| 108 | +(foo bar (foo bar |
| 109 | +baz baz |
| 110 | +(bang == formats to => (bang |
| 111 | +quz quz |
| 112 | +qoz)) qoz)) |
| 113 | +``` |
| 114 | + |
| 115 | +Because no rule was specified for depth 0, default indentation is |
| 116 | +applied to `bar` `baz` and `(bang...)`. |
| 117 | + |
| 118 | +## Limiting inner indentation |
| 119 | + |
| 120 | +Sometimes it is useful to limit `:inner` indentation to one, rather |
| 121 | +than all, forms at the specified depth. For example, we'd like `letfn` |
| 122 | +to use inner indentation only in its binding vector. |
| 123 | + |
| 124 | +Let's look at `letfn` example in the absence of any indentation rules: |
| 125 | + |
| 126 | +```clojure |
| 127 | +(letfn [(double [x] |
| 128 | + (* x 2))] ;; want inner indentation here |
| 129 | + (let [y (double 2) |
| 130 | + z (double 3)] |
| 131 | + (println y |
| 132 | + z))) ;; but not here |
| 133 | +``` |
| 134 | + |
| 135 | +Applying the rule: |
| 136 | + |
| 137 | +```clojure |
| 138 | +{letfn [[:inner 2]]} |
| 139 | +``` |
| 140 | + |
| 141 | +Brings in the `letfn` function body to where we want it by affecting |
| 142 | +form `(double [x]...)`: |
| 143 | + |
| 144 | +```clojure |
| 145 | +(letfn [(double [x] |
| 146 | + (* x 2))] ;; want inner indentation here |
| 147 | + (let [y (double 2) |
| 148 | + z (double 3)] |
| 149 | + (println y |
| 150 | + z))) ;; but not here |
| 151 | +``` |
| 152 | + |
| 153 | +But also affects all other forms at depth `2`. In this case, |
| 154 | +`(println...)` indentation is affected in an undesirable way. To limit |
| 155 | +formatting to `(double [x]...)`, the `0`th form at depth `2`, the |
| 156 | +`limit-to-form-index` rule type argument is added: |
| 157 | + |
| 158 | +```clojure |
| 159 | +{letfn [[:inner 2 0]]} |
| 160 | +``` |
| 161 | + |
| 162 | +... giving us: |
| 163 | +```clojure |
| 164 | +(letfn [(double [x] |
| 165 | + (* x 2))] ;; want inner indentation here |
| 166 | + (let [y (double 2) |
| 167 | + z (double 3)] |
| 168 | + (println y |
| 169 | + z))) ;; but not here |
| 170 | +``` |
| 171 | + |
| 172 | +Remember that when calculating `limit-to-form-index`, all forms at the |
| 173 | +specified depth are included, even self-evaluating ones. Given: |
| 174 | + |
| 175 | +```clojure |
| 176 | +(foo a b c |
| 177 | + (e f |
| 178 | + g) |
| 179 | + (h i |
| 180 | + j)) |
| 181 | +``` |
| 182 | + |
| 183 | +To affect inner indentation within form `(e...)` only, we use a rule |
| 184 | +of: |
| 185 | + |
| 186 | +```clojure |
| 187 | +{foo [[:inner 1 3]]} |
| 188 | +``` |
| 189 | + |
| 190 | +Which results in: |
| 191 | + |
| 192 | +```clojure |
| 193 | +(foo a b c |
| 194 | + (e f |
| 195 | + g) |
| 196 | + (h i |
| 197 | + j)) |
| 198 | +``` |
| 199 | + |
| 200 | +Because `(e...)` is the 4th (index `3`) at form depth `1`. |
| 201 | + |
| 202 | +#### Block rules |
| 203 | + |
| 204 | +The `:block` rule works like the `:inner` rule under some |
| 205 | +circumstances, and like a normal list form under others. It takes one |
| 206 | +argument: |
| 207 | + |
| 208 | +* `line-threshold-index` - |
| 209 | + if the argument at this index starts a new line, all following lines |
| 210 | + will be indented by a constant 2 spaces. Any other lines are |
| 211 | + indented normally. |
| 212 | + |
| 213 | +For example: |
| 214 | + |
| 215 | +```clojure |
| 216 | +{foo [[:block 0]]} |
| 217 | +``` |
| 218 | + |
| 219 | +If the argument at index 0 (the first argument) does not start a new |
| 220 | +line, the form is indented as normal: |
| 221 | + |
| 222 | +```clojure |
| 223 | +(foo bar (foo bar |
| 224 | +baz == formats to => baz |
| 225 | +bang) bang) |
| 226 | +``` |
| 227 | + |
| 228 | +If it does, the lines are indented with a constant 2 spaces: |
| 229 | + |
| 230 | +```clojure |
| 231 | +(foo (foo |
| 232 | +bar == formats to => bar |
| 233 | +baz baz |
| 234 | +bang) bang) |
| 235 | +``` |
| 236 | + |
| 237 | +To give another example |
| 238 | + |
| 239 | +```clojure |
| 240 | +{foo [[:block 1]]} |
| 241 | +``` |
| 242 | + |
| 243 | +This time we're looking at the argument at index 1 (the second |
| 244 | +argument). If it starts a new line, the indent is constant: |
| 245 | + |
| 246 | +```clojure |
| 247 | +(foo bar (foo bar |
| 248 | +baz == formats to => baz |
| 249 | +bang) bang) |
| 250 | +``` |
| 251 | + |
| 252 | +But if it does not, start a new line, normal indentation rules are |
| 253 | +used instead: |
| 254 | + |
| 255 | +```clojure |
| 256 | +(foo bar baz == formats to => (foo bar baz |
| 257 | +bang) bang) |
| 258 | +``` |
| 259 | + |
| 260 | +Any lines before the threshold are always indented normally: |
| 261 | + |
| 262 | +```clojure |
| 263 | +(foo (foo |
| 264 | +bar bar |
| 265 | +baz == formats to => baz |
| 266 | +bang) bang) |
| 267 | +``` |
| 268 | + |
| 269 | +## Multiple rules |
| 270 | + |
| 271 | +Multiple rules can be specified. Picking up from our previous `letfn` |
| 272 | +example, the rule: |
| 273 | + |
| 274 | +```clojure |
| 275 | +{letfn [[:inner 2 0]]} |
| 276 | +``` |
| 277 | + |
| 278 | +Gave us: |
| 279 | + |
| 280 | +```clojure |
| 281 | +(letfn [(double [x] |
| 282 | + (* x 2))] ;; want inner indentation here |
| 283 | + (let [y (double 2) |
| 284 | + z (double 3)] |
| 285 | + (println y |
| 286 | + z))) ;; but not here |
| 287 | +``` |
| 288 | + |
| 289 | +Adding a `:block` rule: |
| 290 | + |
| 291 | +```clojure |
| 292 | +{letfn [[:block 1][:inner 2 0]]} |
| 293 | +``` |
| 294 | + |
| 295 | +Matches the [current default rule for `letfn`][default-rule] and |
| 296 | +results in indenting the `(let...` to where we want it: |
| 297 | + |
| 298 | +```clojure |
| 299 | +(letfn [(double [x] |
| 300 | + (* x 2))] ;; want inner indentation here |
| 301 | + (let [y (double 2) |
| 302 | + z (double 3)] |
| 303 | + (println y |
| 304 | + z))) ;; but not here |
| 305 | +``` |
| 306 | + |
| 307 | +In this case, single form argument `[(double...)]` does not break the |
| 308 | +`line-arg-count-threshold` of `1` and we therefore get inner |
| 309 | +indentation for form argument `(let...)`. |
| 310 | + |
| 311 | +[default-rule]: cljfmt/resources/cljfmt/indents/clojure.clj |
0 commit comments