Nice. It's good to see that it's so similar.
Apparently they use a separate spec for grouping args as well.

2015-09-17 8:28 GMT+01:00 Jozef Wagner <jozef.wag...@gmail.com>:

> Dunaj uses metadata to guide IDEs and pretty printer regarding
> indentations, arg grouping, ...
>
> http://www.dunaj.org/metadata.html#_indentation
> http://www.dunaj.org/day10.html#_ide_support
>
> Jozef
>
>
> On Sunday, September 13, 2015 at 12:06:50 PM UTC+2, 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.

Reply via email to