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.