cursive-ide / cursive

Cursive: The IDE for beautiful Clojure code
587 stars 7 forks source link

hylang support #2329

Open darwin opened 4 years ago

darwin commented 4 years ago

I started working on a Blender live-coding project: https://github.com/darwin/blender-hylang-live-code

Blender embeds Python and offers an API for automation. I want to write Clojure and ideally use IntelliJ+Cursive.

Hy is a language similar to Clojure which compiles to Python bytecode.

What if we could use Cursive to write Hy to do Blender live coding via nREPL?

I have a proof of concept working and Cursive works suprisingly well with hy.

The good parts:

  1. I was able to implement nREPL support in my project (thanks to HyREPL) and make it to talk to lein repl :connect and Cursive's remote nREPL client.
  2. I associated *.hy file pattern as Clojure files in IntelliJ, via Preferences -> Editor > File Types
  3. I disabled Preferences -> Languages & Frameworks > Clojure > Highlight unresolved symbols

With this I have pretty usable code editing and code reformatting. Also "Go to Declaration and Usages" works most of the time. Also nREPL works pretty well:

A sneak peek

The workarounds:

  1. Cursive offers "Configure indentation..." and "Resolve ... as". That's helpful and I was able to set intentation for many symbols I needed. Unfortunately this does not work if symbol is unresolved. I had to employ this hack to make Cursive belive those symbols exist: https://github.com/darwin/blender-hylang-live-code/blob/c6ad9bb603a5570f4fadcf5c47bacf99666f4422/src/shared/cursive.hy#L7-L17

  2. hylang developers decided to use forward slashes in some of their library function names. For Cursive to play nicely I had to work around it by definig my own macro and rewriting their names in my code: https://github.com/darwin/blender-hylang-live-code/blob/c6ad9bb603a5570f4fadcf5c47bacf99666f4422/src/shared/cursive.hy#L3-L5 I understand that Clojure uses forward slashes for namespaces. So this might be illegal in Clojure but it might be perfectly ok in other lisps. It would be nice if Cursive could attempt to relax this for indentation registy and allow forward slashes as part of the names.

The bad parts:

  1. Cursive does not understand arity of some functions. Read about their &optional and &rest special arguments: https://docs.hylang.org/en/stable/tutorial.html#functions-classes-and-modules
    (defn test [a b &optional c [d "x"] &rest e]
    [a b c d e])
    (print (test 1 2))            ; => [1, 2, None, 'x', ()]
    (print (test 1 2 3 4 5 6 7))  ; => [1, 2, 3, 4, (5, 6, 7)]

    I would need Cursive to treat all args after &optional or &rest as optional. So arity of the above function is 2 or more. Also note how they specify default arguments - it looks like destructuring but it is not.


@cursive-ide I understand that officially supporting hy is almost definitely out of Cursive's scope. But as you can see it is not far from being nicely usable for my workflow (please try to open my project and see how it well works with Cursive). Workarounds on my side would be prefectly fine. Maybe you have some ideas...

Also maybe we can leave this open for future Hy users to learn and share their own hacks/workarounds.

Wild ideas:

Let us rewrite our non-clojure lisp code to look more like clojure at cursive-analysis-time:

This would be pretty flexible solution for all future needs. In this particular case I would rewrite the above defn form to:

(defn test [a b & _rest_gensym_123]
  (let [c (get _rest_gensym_123 0)
        d (or (get _rest_gensym_123 1) "x")
        e (drop 2 _rest_gensym_123)]
    [a b c d e])
darwin commented 4 years ago

I retract this request. I made quite substantial progress on the project in darwin/blender-clojure repo.

I ended up embedding V8 into Python and was able to implemented a subset of DOM APIs to make shadow-cljs work (in browser mode). This enabled me to use normal cljs (on shadow-cljs based project) to automate Blender. It seems to work well, including REPL and hot code loading.

This means that I no longer need Cursive to work with hylang code.

przemub commented 3 years ago

Well, I could very much use it.