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.

Reply via email to