Unfortunately as tools developers we can't force our indentation
preferences on our users, although I'd be fine with it if you convinced
everyone to just use two spaces for everything, even though it's not my
preferred formatting. Cursive has supported this for ages (copied from
Emacs) but I don't know how many people actually use it.

As above, I agree that this shouldn't be in the code.

I also agree very strongly that this shouldn't just adopt whatever Emacs
does for formatting. The one-space indent for list forms, in particular,
drives me nuts and is purely an implementation detail, not because that
makes any sort of sense for code.

You're right that the format spec is pretty obtuse, although we have far
worse out there (the pprint format, ahem). Separating the format spec out
into a separate doc would allow something more verbose to be used which
could be more expressive.

On 16 September 2015 at 23:34, Chas Emerick <c...@cemerick.com> wrote:

> Hi all; here to satisfy the quarterly quota to maintain my status as "that
> guy".
>
> This is a questionable proposal. It:
>
> * introduces completely orthogonal, transient concerns (presentation) into
> code, ideally a canonical, long-lived source-of-truth
> * sets up a bikeshed at the top of every def* form
> * adopts idiosyncratic implementation details of a particular editor's
> language support (the defrecord example's :indent is particularly obtuse
> IMO, even if you are aware of how clojure-mode is implemented)
>
> I *think* I coined the "always two spaces" shorthand for the (admittedly,
> minority) position that list forms should be formatted completely
> regularly, so as to:
>
> * make formatting a trivial operation, not requiring any "real" reading
> * eliminate this entire topic
>
> Here's the first time I talked about this IIRC:
> https://groups.google.com/forum/#!msg/clojuredev-users/NzKTeY722-I/3hmNvJulcksJ
>
> Best,
>
> - Chas
>
>
> On 09/13/2015 06:06 AM, Artur Malabarba wrote:
>
> Hi everyone,
>
>
> Over at CIDER we're adding a feature where the author of a macro (or
> function) can specify how that macro should be indented by adding an
> :indent metadata to its definition. This way the editor (and other tools,
> like cljfmt) will know what's the proper way of indenting any macro (even
> those custom-defined) without having to hardcode a bajillion names.
>
> Here's an example of how you specify the indent spec for your macros
>
>
> (defmacro with-out-str
>   "[DOCSTRING]"
>   {:indent 0}
>   [& body]
>   ...cut for brevity...)
>
> (defmacro defrecord
>   "[DOCSTRING]"
>   {:indent [2 nil nil [1]]}
>   [name fields & opts+specs]
>   ...cut for brevity)
>
> (defmacro with-in-str
>   "[DOCSTRING]"
>   {:indent 1}
>   [s & body]
>   ...cut for brevity...)
>
>
> We'd like to hear any opinions on the practicality of this (specially from
> authors of other editors).
> Below, I'll be saying “macros” all the time, but this applies just the
> same to functions.
>
> *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). These
> 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:
>
>
> (defrecord TheNameOfTheRecord
>     [a pretty long argument list]
>   SomeType
>   (assoc [_ x]
>     (.assoc pretty x 10)))
>
>
> Here's another way one could do it:
>
>
> (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 call 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 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 we're working on 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 if it had 1 special argument.
>
> *The spec*
>
>
> An indent spec can be:
>
>    - nil (or absent), meaning *“indent like a regular function call”*.
>    - A vector (or list) meaning that this function/macro takes a number
>    of special arguments, and then all other arguments are non-special.
>       - The first element of this vector is an integer indicating how
>       many special arguments this function/macro takes.
>       - Each following element is an indent spec on its own, and it
>       applies to 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 aguments than the vector has
>       elements, the last element of the vector applies to all remaining 
> arguments.
>    - If the whole spec is just an integer n, that is shorthand for [n].
>
>
> *Examples*
>
>
> So, for instance, if I specify the defrecord spec as [2 nil nil [1]],
> this is saying:
>
>    - defrecord has 2 special arguments
>    - The first two arguments don't get special internal indentation
>    - All remaining arguments have an internal indent spec of [1] (which
>    means only the arglist is indented specially).
>
> Another example, reify is [1 nil [1]] (which should be easy to see now).
>
>
> (reify Object
>   (toString [this]
>     (something)
>     else
>     "here"))
>
>
> For something more complicated: letfn is [1 [[1]] nil]. This means
>
>    - letfn has one special argument (the bindings list).
>    - The first arg has an indent spec of [[1]], which means all forms
>    *inside* the first arg have an indent spec of [1].
>    - The second argument, and all other arguments, are regular forms.
>
> (letfn [(twice [x]
>           (* x 2))
>         (six-times [y]
>           (* (twice y) 3))]
>   (println "Twice 15 =" (twice 15))
>   (println "Six times 15 ="
>            (six-times 15)))
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to