There's a bunch of clojure.core macros that will need to be given their own specific layout algorithms to make Flense's rendering consistent with idiomatic textual Clojure source code. These seem to fall into several loose "families":
if, if-not, if-some, etc – the macro's name, then a form to test for truthiness, then a consequent and perhaps an alternate clause.
when, when-not, when-some, etc – the macro's name, then a form to test for truthiness, then a body of one or more forms.
let, loop, etc – the macro's name, then a vector of binding pairs, then a body of one or more forms.
def, defn, defn-, defmacro, etc – a fixed header containing the macro's name, a symbol naming the var to define, and perhaps a docstring, followed by a body of one or more forms. Generally found at the top level. Most of these also bear some resemblance to fn.
defrecord, deftype, etc – a fixed header containing the macro's name, a symbol naming the type to define, and a vector of symbols naming the type's fields, followed by an optional body of protocol implementations. Typically found, like the def family, at the top level. defprotocol is similar but in a class of its own.
case, cond, condp, etc – a fixed header containing the macro's name and one or more forms describing what is to be tested, then a series of one or more condition-body pairs possibly followed by a default.
->, ->>, as->, cond->, some->, etc – the macro's name, then an argument to "thread through" the following forms, then a series of forms through which to do the threading.
Of course, some core macros (if-let and when-let come to mind) share traits from two or more of these families, but generally speaking this loose classification should be sufficient to guide the implementation of most of the necessary layout algorithms.
Commits a70577895eab3b657526636acce142e170a48bd8 through 7d4dad80ac8af84ea0b1953446d2707cb2259092 implement better layout algorithms for most clojure.core macros.
There's a bunch of clojure.core macros that will need to be given their own specific layout algorithms to make Flense's rendering consistent with idiomatic textual Clojure source code. These seem to fall into several loose "families":
if
,if-not
,if-some
, etc – the macro's name, then a form to test for truthiness, then a consequent and perhaps an alternate clause.when
,when-not
,when-some
, etc – the macro's name, then a form to test for truthiness, then a body of one or more forms.let
,loop
, etc – the macro's name, then a vector of binding pairs, then a body of one or more forms.def
,defn
,defn-
,defmacro
, etc – a fixed header containing the macro's name, a symbol naming the var to define, and perhaps a docstring, followed by a body of one or more forms. Generally found at the top level. Most of these also bear some resemblance tofn
.defrecord
,deftype
, etc – a fixed header containing the macro's name, a symbol naming the type to define, and a vector of symbols naming the type's fields, followed by an optional body of protocol implementations. Typically found, like thedef
family, at the top level.defprotocol
is similar but in a class of its own.case
,cond
,condp
, etc – a fixed header containing the macro's name and one or more forms describing what is to be tested, then a series of one or more condition-body pairs possibly followed by a default.->
,->>
,as->
,cond->
,some->
, etc – the macro's name, then an argument to "thread through" the following forms, then a series of forms through which to do the threading.Of course, some core macros (
if-let
andwhen-let
come to mind) share traits from two or more of these families, but generally speaking this loose classification should be sufficient to guide the implementation of most of the necessary layout algorithms.