Re: Using metadata to specify how calls to a macro should be indented

2015-09-23 Thread Artur Malabarba
Great! ☺ Bring it up on the cider gitter room.
On 23 Sep 2015 3:55 pm, "Phillip Lord"  wrote:

> Artur Malabarba  writes:
> >>
> > Yes, that's what the current (but unmerged) implementation does. :)
> >
> >> If this cache were persisted between Emacs sessions then the problem
> >> largely goes away.
> >>
> > Yes, that's very plausible to do.
>
> I am happy to do the implementation for this (i.e. the persistance!),
> given that I am raising the problem, if that would be a help.
>
> Phil
>

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-23 Thread Phillip Lord
Artur Malabarba  writes:
>>
> Yes, that's what the current (but unmerged) implementation does. :)
>
>> If this cache were persisted between Emacs sessions then the problem
>> largely goes away.
>>
> Yes, that's very plausible to do.

I am happy to do the implementation for this (i.e. the persistance!),
given that I am raising the problem, if that would be a help.

Phil

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-23 Thread Artur Malabarba
2015-09-23 10:32 GMT+01:00 Phillip Lord :

> Specifically wrt to CIDER, the easier solution is the cache the metadata
> map each time it is used. I suspect that CIDER would need this for
> performance -- I mean indentation requiring ongoing evaluation in
> Clojure is likely to be slow.
> Basically, I am suggesting automatic manual configuration if you will
> excuse the oxymoron.
>
Yes, that's what the current (but unmerged) implementation does. :)

> If this cache were persisted between Emacs sessions then the problem
> largely goes away.
>
Yes, that's very plausible to do.

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-23 Thread Phillip Lord
Artur Malabarba  writes:

> You're right about indentation depending on the code being evaluated, but
> that's still better than nothing. ☺
>
> People who do a significant amount of coding without a live session can
> still manually configure indentation like they currently do, and they're no
> worse off.
>
> The editor can even parse the metadata map present in the defn/defmacro, so
> as to provide some "offline" support (though I don't foresee Cider doing
> that).


It's worth being explicit in the spec, then, about whether there is an
expectation that the indentation declaration is, itself, evaluated or
not.

IIRC, the (declare (indent 1)) forms of Emacs-Lisp are *not* evaluated
by the defun/defmacro macros, so are easy enough to pull out of code. If
there are eval'd then, it becomes impossible to do this with any
accuracy.

Specifically wrt to CIDER, the easier solution is the cache the metadata
map each time it is used. I suspect that CIDER would need this for
performance -- I mean indentation requiring ongoing evaluation in
Clojure is likely to be slow. If this cache were persisted between
Emacs sessions then the problem largely goes away.

Basically, I am suggesting automatic manual configuration if you will
excuse the oxymoron.

Phil

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-22 Thread Artur Malabarba
You're right about indentation depending on the code being evaluated, but
that's still better than nothing. ☺

People who do a significant amount of coding without a live session can
still manually configure indentation like they currently do, and they're no
worse off.

The editor can even parse the metadata map present in the defn/defmacro, so
as to provide some "offline" support (though I don't foresee Cider doing
that).
On 22 Sep 2015 11:31 am, "Phillip Lord" 
wrote:

>
>
>
> Artur Malabarba  writes:
> > 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.
>
>
> One slight disadvantage with this approach is that the indentation can
> change depending on the evaluation status of the code. Consider this set
> of events inside emacs (I'll get back to Clojure -- it's a general
> problem not Emacs specific).
>
>  - I open the file lentic.el
>  - I type M-x indent-buffer
>
> Now, lentic.el depends on m-buffer.el which has some macros with
> "declare" forms (the elisp equivalent to the metadata you are talking
> off). And these are used in lentic.el.
>
> But I haven't loaded m-buffer.el yet. So the declare forms are not
> active, so the m-buffer macros indent according to normal rules. Now, I
> do
>
>  - M-x eval-buffer
>  - M-x indent-buffer
>
> This loads lentic.el which loads m-buffer.el including the macros. So,
> now I get different indentation patterns. Solution in Emacs space: force
> loading on m-buffer.el whenever lentic.el is *opened* rather than loaded.
>
> Using metadata in Clojure the same situation will arise, but will be
> somewhat worse. Indentation will be likely to behave differently
> depending on whether the REPL is open and the evaluation status of any
> macros. Given the slow start up time of the clojure REPL, this is
> perhaps a more significant issue. The interesting question then is what
> percentage of the time do Clojure developers work *without* a repl
> active.
>
> Just a thought.
>
> Phil
>
>

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-22 Thread Phillip Lord
Fluid Dynamics  writes:

> On Tuesday, September 22, 2015 at 6:31:34 AM UTC-4, Phillip Lord wrote:
>>
>> ... The interesting question then is what 
>> percentage of the time do Clojure developers work *without* a repl 
>> active.
>>
>
> Uhhh, zero? :) 

Some I am sure. I do, though. I often write and improve documentation
without a REPL, especially when I am using my old netbook. The REPL
shortens the battery live and isn't that useful when writing English.

Still, the problem is soluable in a number of ways, I guess, and I can't
think of a better alternative (to using metadata).

Phil

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-22 Thread Colin Yates
Do you know about lein figwheel?
On 22 Sep 2015 21:05, "Gary Trakhman"  wrote:

> Sometimes more than 0% when I'm doing something small in clojurescript,
> can't be bothered with the setup, and browser refresh is good enough :-).
> On Tue, Sep 22, 2015 at 4:02 PM Fluid Dynamics  wrote:
>
>> On Tuesday, September 22, 2015 at 6:31:34 AM UTC-4, Phillip Lord wrote:
>>>
>>> ... The interesting question then is what
>>>
>> percentage of the time do Clojure developers work *without* a repl
>>> active.
>>>
>>
>> Uhhh, zero? :)
>>
>> --
>> 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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-22 Thread Gary Trakhman
Sometimes more than 0% when I'm doing something small in clojurescript,
can't be bothered with the setup, and browser refresh is good enough :-).
On Tue, Sep 22, 2015 at 4:02 PM Fluid Dynamics  wrote:

> On Tuesday, September 22, 2015 at 6:31:34 AM UTC-4, Phillip Lord wrote:
>>
>> ... The interesting question then is what
>>
> percentage of the time do Clojure developers work *without* a repl
>> active.
>>
>
> Uhhh, zero? :)
>
> --
> 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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-22 Thread Fluid Dynamics
On Tuesday, September 22, 2015 at 6:31:34 AM UTC-4, Phillip Lord wrote:
>
> ... The interesting question then is what 
> percentage of the time do Clojure developers work *without* a repl 
> active.
>

Uhhh, zero? :) 

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-22 Thread Phillip Lord



Artur Malabarba  writes:
> 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.


One slight disadvantage with this approach is that the indentation can
change depending on the evaluation status of the code. Consider this set
of events inside emacs (I'll get back to Clojure -- it's a general
problem not Emacs specific).

 - I open the file lentic.el
 - I type M-x indent-buffer

Now, lentic.el depends on m-buffer.el which has some macros with
"declare" forms (the elisp equivalent to the metadata you are talking
off). And these are used in lentic.el.

But I haven't loaded m-buffer.el yet. So the declare forms are not
active, so the m-buffer macros indent according to normal rules. Now, I
do

 - M-x eval-buffer
 - M-x indent-buffer

This loads lentic.el which loads m-buffer.el including the macros. So,
now I get different indentation patterns. Solution in Emacs space: force
loading on m-buffer.el whenever lentic.el is *opened* rather than loaded.

Using metadata in Clojure the same situation will arise, but will be
somewhat worse. Indentation will be likely to behave differently
depending on whether the REPL is open and the evaluation status of any
macros. Given the slow start up time of the clojure REPL, this is
perhaps a more significant issue. The interesting question then is what
percentage of the time do Clojure developers work *without* a repl
active.

Just a thought.

Phil

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-19 Thread Artur Malabarba
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 :

> 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 h

Re: Using metadata to specify how calls to a macro should be indented

2015-09-19 Thread Artur Malabarba
Hi Chas,

This is a questionable proposal. It:
>
> * introduces completely orthogonal, transient concerns (presentation) into
> code, ideally a canonical, long-lived source-of-truth
>

Yes, I'm ok with that. No one is better equipped to define a macro's
indentation than it's author, and the metadata is the same place that
carries other info like arglists or docstrings.

Then again, maybe I'm just used to it because emacs-lisp uses a similar
system.


> * sets up a bikeshed at the top of every def* form
>

As bozhidar mentioned, this will only go on defs which deserve special
indentation (which is tipically just macros and not all of them). And even
then, in most cases the spec is just an integer (in my examples above I
used the most complex macros I could find in clojure.core). For instance,
the spec for let, loop, and doseq is 1, the spec for condp and catch is 2.

* 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)
>

Actually, the proposed spec is different from what clojure-mode is
currently using and won't work with the current release. But still, there's
no doubt I may have been influenced by what made more sense for me to
implement, that's precisely why I brought it here. :-)

If there's a better way to define it, I'd like to hear.


> 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
>

The spec does not define how many spaces should be used in indentation. It
just says "the author of this macro declared the first 2 args as special".
Any editor will let the user configure if they want "always 2 spaces" or if
they want "1-2-4".

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-17 Thread Jozef Wagner
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 

Re: Using metadata to specify how calls to a macro should be indented

2015-09-16 Thread Bozhidar Batsov
I'm kind of puzzled by the last couple of responses. Obviously very few
forms (probably only macros) would have indentation specifications and
editors can certainly disregard them, so I don't see the code being
littered with indentation specs any time soon or some indentation being
forced on everyone.

This idea is not something new - in Emacs Lisp there's a way to specify the
indentation of a macro form which is pretty similar (via `declare`). Maybe
there was something similar for CL as well, but right now I'm not 100% sure.

As for things like the one-space indent, I'm not sure how related they are
to Emacs's prominence in the Lisp world. It sounds more plausible that such
conventions were established before the age of `lisp-mode`.

On 17 September 2015 at 08:31, Colin Fleming 
wrote:

> 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  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.
>>
>> *Inte

Re: Using metadata to specify how calls to a macro should be indented

2015-09-16 Thread Colin Fleming
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  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 t

Re: Using metadata to specify how calls to a macro should be indented

2015-09-16 Thread Chas Emerick
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.
  o The first element of this vector is an integer indicating how
many special arguments this function/macro takes.
  o 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).
  o 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

Re: Using metadata to specify how calls to a macro should be indented

2015-09-16 Thread Artur Malabarba
2015-09-15 20:08 GMT+01:00 Josh Tilles :

> I suspect that “Matching Socks” meant that there should be a standard
> namespace, similar to how the recent Socket Server REPL design
> 
>  uses
> a “repl” namespace for its magic keywords.
> It seems natural to me to pick a namespace like “editors” or “editing”,
> but alternatives like :display/indentation or :visual/structure also look
> good.
>

Silly me. Yes, that makes perfect sense. :-)

I like :editors. Other options are :style and :format(ting).

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-16 Thread Artur Malabarba
Hi Colin, it's great to get your thoughts on this.

2015-09-15 22:52 GMT+01:00 Colin Fleming :

> I think it's important that the declaration of the formatting be separated
> from the declaration of the macro itself. This allows forms which the
> editor developer doesn't control to be annotated, e.g. core. Perhaps
> library owners could produce an EDN doc containing these specs? Or perhaps
> we could obey annotations in the functions themselves, but I think that
> some way to additionally annotate external things is essential.
>
I think it's important that this information be in the metadata. When we're
indenting a form, we only need to resolve the var and we'll have its
metadata. That seems simpler than having to resolve the var and then look
it up in the library's doc or something.

Of course, metadata can be added to a var as a separate declaration, so it
does allow us to annotate external macros as in:

(alter-meta! #'clojure.core/cond assoc :editor/indent 1)

Does that cover your point or did I misunderstand something?


> I also think that Mr Dynamics is correct, we should not go down the path
> of special casing anything, even defn - this is a hard rule that I have in
> Cursive that I only break very occasionally :-). The spec should support
> everything we need to do. It will be difficult, though [...]
>

Yes, I agree now as well.


> There are also many more aspects to formatting that this does not address
> that I think we should think about - line indentation is only one part of
> it. What about breaking lines when they're too long? Aligning subforms like
> let-binding values? Do we want to do anything about those? Cursive can
> handle all of that but doesn't expose the knobs right now. clj-fmt does, I
> believe - I think it can take a single line of pr-str output and produce
> nicely formatted code.
> There are also lots of edge cases that need to be thought through.
> Multi-arity function declarations for letfn, proxy etc come to mind.
> extend-type also supports multiple arity declarations. condp is another
> example of a form with variable numbers of elements per "block" (the :>>
> keyword). for-blocks have internal let blocks, etc etc.
>

Indeed the spec should cover some of this stuff. I'd like the spec to cover
as much as possible, but I also don't want to define something so verbose
and complicated that people just don't bother. So hopefully we can figure
out a way to add some essential features while keeping the complexity in
check.

In particular:

   -

   Handling macros that may take different syntaxes I feel is pretty
   important. This is basically the multi-arity case you mention. The `fn`
   could be invoked as `(fn my-func [] 10)` or as `(fn ([] 10) ([x] (inc
   x)))`, and the indentation is different in these cases.
   -

   Another thing I'd like is a way to indicate that there should be a
   line-break between one symbol/value pair and another in let-bindings. So
   the subforms you mention.
   -

   I would like the spec to say things like "this argument should (or
   should not) be on its own line". But I *don't* think the spec should say
   "break the line if it's longer than N chars".

It's hard to tell how far to go with this. One thing that I'm planning in
> Cursive that I'm not doing currently is also to identify forms which are
> part of a do-body-like-thing. This is very useful for refactoring. This
> might not have a place in a spec that is purely for indentation, but
> definitely would in a more general form structure spec.
>

The safest option here is to not go too far right now, but define the spec
in a way that's extensible, so we can still go as far as we want later.
The spec I proposed initially isn't highly extensible. Can we figure out a
reasonable way to add a few of these features?

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-15 Thread Colin Fleming
This is an interesting proposal, and I like it in general. Everything in
Cursive is based on extensions identified by the head form, like this:

(style/register-formatting :clojure.core/def :only-indent)
(style/register-formatting :clojure.core/defn- :only-indent)
(style/register-formatting resolve/fn-forms :only-indent)
(style/register-formatting resolve/local-binding-forms 1)

I think it's important that the declaration of the formatting be separated
from the declaration of the macro itself. This allows forms which the
editor developer doesn't control to be annotated, e.g. core. Perhaps
library owners could produce an EDN doc containing these specs? Or perhaps
we could obey annotations in the functions themselves, but I think that
some way to additionally annotate external things is essential.

I also think that Mr Dynamics is correct, we should not go down the path of
special casing anything, even defn - this is a hard rule that I have in
Cursive that I only break very occasionally :-). The spec should support
everything we need to do. It will be difficult, though - in Cursive I
actually support programmatically organising the blocks that make up the
source, and I'm not sure how to handle many cases without this. I like the
hierarchical nature of this spec, though, I suspect that many of the cases
I currently solve programmatically could be solved using something like
this.

There are also many more aspects to formatting that this does not address
that I think we should think about - line indentation is only one part of
it. What about breaking lines when they're too long? Aligning subforms like
let-binding values? Do we want to do anything about those? Cursive can
handle all of that but doesn't expose the knobs right now. clj-fmt does, I
believe - I think it can take a single line of pr-str output and produce
nicely formatted code.

There are also lots of edge cases that need to be thought through.
Multi-arity function declarations for letfn, proxy etc come to mind.
extend-type also supports multiple arity declarations. condp is another
example of a form with variable numbers of elements per "block" (the :>>
keyword). for-blocks have internal let blocks, etc etc.

It's hard to tell how far to go with this. One thing that I'm planning in
Cursive that I'm not doing currently is also to identify forms which are
part of a do-body-like-thing. This is very useful for refactoring. This
might not have a place in a spec that is purely for indentation, but
definitely would in a more general form structure spec. I also think it
would be very useful to express implicit grouping of elements, e.g. let
binding keys/values, cond forms etc.


On 16 September 2015 at 07:08, Josh Tilles 
wrote:

>
>
> On Sunday, September 13, 2015 at 8:25:42 AM UTC-4, Artur Malabarba wrote:
>>
>>
>> On 13 Sep 2015 12:33 pm, "Matching Socks"  wrote:
>> >
>> > Unless clojure.core itself will carry these annotations, could the
>> keyword be namespaced?
>>
>> Or do you mean it should be ::indent? (i.e., carry the namespace of the
>> var that they're applied on)
>>
> I suspect that “Matching Socks” meant that there should be a standard
> namespace, similar to how the recent Socket Server REPL design
> 
>  uses
> a “repl” namespace for its magic keywords.
> It seems natural to me to pick a namespace like “editors” or “editing”,
> but alternatives like :display/indentation or :visual/structure also look
> good.
>
> --
> 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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-15 Thread Josh Tilles


On Sunday, September 13, 2015 at 8:25:42 AM UTC-4, Artur Malabarba wrote:
>
>
> On 13 Sep 2015 12:33 pm, "Matching Socks"  > wrote:
> >
> > Unless clojure.core itself will carry these annotations, could the 
> keyword be namespaced?
>
> Or do you mean it should be ::indent? (i.e., carry the namespace of the 
> var that they're applied on)
>
I suspect that “Matching Socks” meant that there should be a standard 
namespace, similar to how the recent Socket Server REPL design 

 uses 
a “repl” namespace for its magic keywords.
It seems natural to me to pick a namespace like “editors” or “editing”, but 
alternatives like :display/indentation or :visual/structure also look good.

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Fluid Dynamics
On Sunday, September 13, 2015 at 12:10:00 PM UTC-4, Artur Malabarba wrote:
>
> > This scheme won't play nicely with forms with variable numbers of 
> special 
> > arguments. 
>
> True, but I've never seen anyone indent specially these optional 
> arguments. For instance, every defn I see (including clojure.core), is 
> indented like this: 
>
> (defn foo 
>   [x] 
>   (+ x 3)) 
>
> (defn bar 
>   "Adds four to x." 
>   [x] 
>   (+ x 4)) 
>
> In addition, actually supporting this in a general way will make the 
> indent spec more complicated (you would have to specify predicates or 
> something to determine whether an optional argument is presen or not). 
> This would make it harder for people to write an indent spec and 
> harder for the editors/tools to support it. 
>
> However, there's another option. Instead of supporting optional 
> arguments in a general way, we can say something like this: 
>
> An indent spec can also be the keyword :defn, which means this form 
> should be structured like a defn. 
>

That'll work for defn, and for thin wrappers around defn, but it's a step 
back down the road toward loads of special-casing... 

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Artur Malabarba
> This scheme won't play nicely with forms with variable numbers of special
> arguments.

True, but I've never seen anyone indent specially these optional
arguments. For instance, every defn I see (including clojure.core), is
indented like this:

(defn foo
  [x]
  (+ x 3))

(defn bar
  "Adds four to x."
  [x]
  (+ x 4))

In addition, actually supporting this in a general way will make the
indent spec more complicated (you would have to specify predicates or
something to determine whether an optional argument is presen or not).
This would make it harder for people to write an indent spec and
harder for the editors/tools to support it.

However, there's another option. Instead of supporting optional
arguments in a general way, we can say something like this:

An indent spec can also be the keyword :defn, which means this form
should be structured like a defn.

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Fluid Dynamics
This scheme won't play nicely with forms with *variable numbers of special 
arguments*. Of which one is one of the most common macros to use:

(defn foo
  [x]
  (+ x 3))

(defn bar
  "Adds four to x."
  [x]
  (+ x 4))

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Sean Grove
I also love this idea - the more info we give to tools to provide a uniform
formatting, the less I have to worry about configuring my local editor to
match the project styles.

On Sun, Sep 13, 2015 at 3:15 AM, Colin Yates  wrote:

> My knee-jerk reaction is:
>  - +10
>  - leaving it up to the user is absolutely the right thing to do
>  - the name ‘indent’ and what it is actually capturing are at different
> levels of abstraction. Possibly ‘structure’ might be a better name as that
> is what it is describing?
>
> But don’t listen to a word I say - I am hacking through some of my old
> code which uses :admission-date and :start-date interchangeably *for the
> same data structure* - sigh.
>
> My 1.5 cents.
>
> On 13 Sep 2015, at 11: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 i

Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Artur Malabarba
2015-09-13 11:15 GMT+01:00 Colin Yates :
>  - the name ‘indent’ and what it is actually capturing are at different
> levels of abstraction. Possibly ‘structure’ might be a better name as that
> is what it is describing?

Good point, we should consider this. Though :structure might be a
little too abstract.

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Artur Malabarba
On 13 Sep 2015 1:25 pm, "Artur Malabarba"
> Or do you mean it should be ::indent?
Typo. Ignore the "Or".

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Artur Malabarba
On 13 Sep 2015 12:33 pm, "Matching Socks"  wrote:
>
> Unless clojure.core itself will carry these annotations, could the
keyword be namespaced?

Or do you mean it should be ::indent? (i.e., carry the namespace of the var
that they're applied on)
In this case, I think it would only make things more complicated for the
editor, since the keyword you have to look for won't be the same for all
symbols.

It's still doable, if people think it's important.

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Matching Socks
Unless clojure.core itself will carry these annotations, could the keyword 
be namespaced?  

-- 
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.


Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Bozhidar Batsov
It's probably obvious, but let me say it just in case it isn't - I'm super
supportive of Artur's idea. I've been thinking about something similar for
a while and I believe deciding on something that's going to be used by many
Clojure tools (CIDER, Cursive, fireplace, ccw, cljfmt, etc) will be hugely
beneficial for everyone. As for the spec itself - I'd only suggest using
some keyword instead of `nil`, as it would probably be more intention
revealing.

I have no preference about the name of the metadata key itself.

On 13 September 2015 at 13:15, Colin Yates  wrote:

> My knee-jerk reaction is:
>  - +10
>  - leaving it up to the user is absolutely the right thing to do
>  - the name ‘indent’ and what it is actually capturing are at different
> levels of abstraction. Possibly ‘structure’ might be a better name as that
> is what it is describing?
>
> But don’t listen to a word I say - I am hacking through some of my old
> code which uses :admission-date and :start-date interchangeably *for the
> same data structure* - sigh.
>
> My 1.5 cents.
>
> On 13 Sep 2015, at 11: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 inden

Re: Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Colin Yates
My knee-jerk reaction is:
 - +10
 - leaving it up to the user is absolutely the right thing to do
 - the name ‘indent’ and what it is actually capturing are at different levels 
of abstraction. Possibly ‘structure’ might be a better name as that is what it 
is describing?

But don’t listen to a word I say - I am hacking through some of my old code 
which uses :admission-date and :start-date interchangeably *for the same data 
structure* - sigh.

My 1.5 cents.

> On 13 Sep 2015, at 11: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 r

Using metadata to specify how calls to a macro should be indented

2015-09-13 Thread Artur Malabarba


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