= Indentation Specification

== Overview

An indent spec can be used to specify intricate indentation rules for the more
complex macros (or functions). It is provided as a value in the var metadata,
under the `:style/indent` key.

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

It can take one of 3 forms:

* Absent, meaning _"indent like a regular function call"_.
* An integer or a keyword `x`, which is shorthand for the list `[x]`.
* A list, meaning that this function/macro takes a number of special arguments,
and then all other arguments are non-special.
 ** *The first element* describes how the arguments are indented relative to the sexp. It can be:
  *** An integer `n`, which indicates this function/macro takes `n` special
arguments (see below for the meaning of this).
  *** The keyword `:form`, meaning _"every arg indents like a function form"_.
  *** The keyword `:defn`, which means _"every arg not on the first line is non-special"_.
 ** *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).
 ** If the function/macro has more arguments than the list has elements, the last
element of the list applies to all remaining arguments.

'''

== Examples

Here we go into several examples using some well-known macros and forms from
`clojure.core`. Obviously these are already known by `clojure-mode`, so you
don't need to specify them. They are just examples to guide you when writing
indent specs for your own macros, or for macros from third party libs.

One very simple example is the `do` form. All of its arguments get the same
indentation, and none of them are special. So its indent spec is simply `[0]`,
or `0` for short.

[source,clojure]
----
(do
  (something)
  (quick))

(do (whatever)
    (you)
    (want))
----

Sticking to simplicity, the `when-let*` macro has one special argument (the
binding vector) and there's no out-of-the-ordinary internal structure
involved. So the indent spec is just `1` (which is shorthand for `[1]`).

'''

Let's see something more sophisticated. If the `defrecord` indent spec used by
`clojure-mode` is `[2 :form :form [1]]`. This is saying:

* `defrecord` has 2 special arguments (the name and the arglist).
* The first two arguments have no special internal structure.
* All remaining arguments have an internal indent spec of `[1]` (which means
only the arglist is indented specially and the rest is the body).

[source,clojure]
----
(defrecord Thing [a]
  FileNameMap
  (getContentTypeFor [_ file-name]
    (str a "-" file-name))
  Object
  (toString [_]
    "My very own thing!!"))
----

For something even more complicated: `letfn` is `+[1 [[:defn]] :form]+`. This means

* `letfn` has one special argument (the bindings list).
* The first arg has an indent spec of `+[[:defn]]+`, which means all forms
_inside_ the first arg have an indent spec of `+[:defn]+`.
* The second argument, and all other arguments, are regular forms.

[source,clojure]
----
(letfn [(twice [x]
          (* x 2))
        (six-times [y]
          (* (twice y) 3))]
  (six-times 15))
----

== Special Arguments

Many macros have a number of "special" arguments, followed by an arbitrary
number of "non-special" arguments (sometimes called the body). The "non-special"
arguments have a small indentation (usually 2 spaces). The special arguments
are usually on the same line as the macro name, but, when necessary, they are
placed on a separate line with additional indentation.

For instance, `defrecord` has two special arguments, and here's how it might be indented:

[source,clojure]
----
(defrecord TheNameOfTheRecord
    [a pretty long argument list]
  SomeType
  (assoc [_ x]
    (.assoc pretty x 10)))
----

Here's another way one could do it:

[source,clojure]
----
(defrecord TheNameOfTheRecord
           [a pretty long argument list]
  SomeType
  (assoc [_ x]
    (.assoc pretty x 10)))
----

_The point of the indent spec is *not* to specify how many spaces to use._

The point is just to say "a defrecord has *2* special arguments", and then let
the editor and the user come to an agreement on how many spaces they like to use
for special and non-special arguments.

== Internal indentation

The issue goes a bit deeper. Note the last argument in that `defrecord`. A
regular function form would be internally indented as:

----
(assoc [_ x]
       (.assoc pretty x 10))
----

But this is not a regular function call, it's a definition. So we want to
specify that this form internally has 1 special argument (the arglist vector),
so that it will be indented like this:

----
(assoc [_ x]
  (.assoc pretty x 10))
----

The indent spec does this as well. It lets you specify that, for each argument
beyond the 2nd, if it is a form, it should be internally indented as having 1
special argument.

== Indentation inference

It's worth noting that starting from cider-nrepl 0.32, indentation can be inferred for you,
so you wouldn't have to specify it.

For that to happen, it's most recommended that you write idiomatic Clojure macros:

* If your macro is analog to a clojure.core one, name it identically
 ** e.g. name your macro `defprotocol`, not `my-defprotocol`
  *** (this is intentful usage of Clojure's namespace system)
* If your macro is analog to a clojure.core one, mirror all its arglists
 ** The exact names that you choose for your args do not matter
 ** It's the structure of the arglists that have to match.
 ** It doesn't matter if you express a given arg as a name, or as a destructured map/vector.
* Name 'body' args like using clojure.core customs
 ** good: `[opts body]`
 ** bad: `[opts etc]`
 ** good: `[& body]`
 ** bad: `[& etc]`
 ** Other commonly accepted names include `forms`, `clauses`, etc.

You certainly don't _have_ to follow these suggestions - it's only for your convenience,
as the indentation produced by CIDER will be better.

Other tools may eventually also use these very same inference rules.
