lilactown / helix

A simple, easy to use library for React development in ClojureScript.
Eclipse Public License 2.0
624 stars 52 forks source link

indent metadata on helix.dom macros #142

Closed rome-user closed 10 months ago

rome-user commented 1 year ago

The CIDER plugin for Emacs allows one to use metadata to express indentation of macros and functions in a portable manner. It seems that this is already done for some macros, such as defcomponent and $. We should consider using an indent metadata.

At the moment, here is an example of current indentation in Emacs.

(d/table
 (d/thead
  (d/tr {:scope "row"}
        (d/th "one")
        (d/th "two")))
 (d/body
  (d/tr
   (d/td "1")
   (d/td "2"))))

By using :style/indent [:defn] metadata on the declared vars, we can achieve the following indentation.

(d/table
  (d/thead
    (d/tr {:scope "row"}
      (d/th "one")
      (d/th "two")))
  (d/body
    (d/tr
      (d/td "1")
      (d/td "2"))))

Implementing this is tricky, since we need a macro that can declare vars with the appropriate metadata in both Clojure and ClojureScript. Since the helix.dom namespace currently reserves a few symbols, I made a macro in a separate namespace. It looks like this.

(defmacro declare-indented [& syms]
  `(do 
     ~@(map (fn [sym]
              `(declare ~(vary-meta sym assoc :style/indent [:defn])))
            syms)))
lilactown commented 1 year ago

Personally, I don't mind the normal indentation and I make do by always putting the props map on a new line if an element also takes children, e.g.

(d/table
 (d/thead
  (d/tr
   {:scope "row"}
   (d/th "one")
   (d/th "two")))
 (d/body
  (d/tr
   (d/td "1")
   (d/td "2"))))

We've been using that as an informal style requirement at my work for awhile.

I'm also not sure that all editors consume these style metadata the same way; I know I've seen special casing having to be done in IntelliJ.

I can think about if this is something I want to change for us internally and try and get adoption in non-Emacs editors. In the meantime, if you prefer the way it's indented in your second snippet, could that be something configurable on a per-project basis?

rome-user commented 1 year ago

I'm not sure. The reason I filed this issue is due to seeing the $ macro indentation changing. For some reason, my Emacs now indents as follows.

($ component
  {:foo bar :& baz}
  children)

Previously, it would indent like this

($ component
   {:foo bar :& baz}
   children)

I know that CIDER had some issues with style metadata in CLJS macros for a while. But I was unable to find any indent metadata on $, so I do not know what caused this change. In any case, it led me to believe Helix macros were moving towards this indentation style.

lilactown commented 12 months ago

that's very strange. I'm using clojure-mode from 2023-06-26 and I don't see this.