Fork me on GitHub
#joyride
<
2023-03-21
>
Jason Whitlark18:03:34

Is it possible to use core.match in joyride? I’ve not found any references either way, and I’ve not gotten the hang of joyride yet.

pez19:03:38

I don’t think so. At least it’s not included, iirc. Depending on its dependencies you might be able to use it by dropping the library on Joyride’s class path. WDYT, @U04V15CAJ ?

Jason Whitlark19:03:22

BTW, thank you for adding rewrite-clj. Just finished working up my first script for it, and it’s a much nicer way to tweak code in the editor. In Clojure, I use core.match with rewrite-clj to select what rewrite function to call, which is why I was asking.

Jason Whitlark19:03:27

Another thing I’m trying to figure out is how to tell if the current selection is a form, as rw-clj/of-string will only grab the first form.

pez20:03:04

I'm super curious about your Joyride scripts!

pez20:03:33

For checking if the selection is a form, I was about to suggest using the Calva range API to see if (currentForm) will select the same as the selection. But trying the Calva command Calva: Select Current Form with a selection tells me there's a bug there that might affect the API (I don't recall if they use the same implementation, but I think they do). However, if you call currentForm with the just the .-active position from the selection, that should work as well, right? If it selects the same thing as the selection (possibly trimmed) then the current selection is a form.

pez20:03:11

(Not fully sure, just first thing that came to mind.)

Jason Whitlark20:03:23

I just finished my first pass, of the first one. A little fn to help convert midje to clojure.test:

(ns port-arrow-form
  (:require ["vscode" :as vscode]
            [joyride.core :as joyride]
            [promesa.core :as p]
            [rewrite-clj.zip :as z]
            [util.editor :as e]))

(def oc (joyride.core/output-channel))
(defn log [x]
  (.appendLine oc (str x)))

(defn get-arrow-clause [zl]
  (let [lhs (z/sexpr zl)
        arrow (-> zl z/right z/string)
        rhs (-> zl z/right z/right z/sexpr)]
    [lhs arrow rhs]))

(defn main []
  (log "port-arrow-form started")
  (-> (p/let [editor ^js vscode/window.activeTextEditor
              selection (e/current-selection)
              source (str "[ " (e/current-selection-text) " ]")
              zloc (z/of-string source)
              [lhs arrow rhs] (get-arrow-clause (z/down zloc))]
        (e/delete-range! editor selection)
        (e/insert-text!+ (str `(~'is (~'= ~rhs ~lhs)))))))

(when (= (joyride/invoked-script) joyride/*file*)
  (main))

pez20:03:30

Please feel invited to add that to the examples in the Joyride repo!

👍 2
Jason Whitlark20:03:39

Will do! How do you feel about a page in doc/ on manipulating clj code?

👍 2
pez20:03:09

I'd love that!

Jason Whitlark20:03:02

If you see any blunders in the example, please let me know. I’ll start sketching out some docs.

Jason Whitlark20:03:28

One thing I think would be handy for util.editor is a replace-selection! function. I’m never sure if I’m doing it right.

pez20:03:35

Please add it. 😃 It probably looks very similar to insert-text!+.

Jason Whitlark20:03:15

👍 I’ll update my PR.

Jason Whitlark21:03:44

Hmm. I would have expected the following to work, but it seems the delete-range! isn’t being called?

(defn replace-range!
  "Defaults to the current selection."
  ([^js text]
   (replace-range! text vscode/window.activeTextEditor (.-active (current-selection))))
  ([^js text ^js editor ^js position]
   (-> (p/do (delete-range! editor position)
             (insert-text!+ text editor position))
       (p/catch (fn [e]
                  (js/console.error e))))))

pez21:03:26

It takes a range, not a position. However, I think it is better to implement it with .replace of the text builder.

borkdude21:03:36

I noticed I'm mentioned in this thread, but don't have much time to read up. Can you summarize what is important for me?

pez21:03:27

It started with a question about using core.match with Joyride. I guess that's what we want your input on.

borkdude21:03:43

core.match doesn't run from source in SCI, but it can be added via a config, e.g. here it is in bb: https://github.com/babashka/babashka/blob/master/feature-core-match/babashka/impl/match.clj However! The library is fairly macro rich and cause side effects when they run (if I remember correctly), so those macros also have to be copied and made CLJS-runtime compatible. If I remember correctly the core.match library doesn't run in self-hosted:

$ plk -Sdeps '{:deps {org.clojure/core.match {:mvn/version "RELEASE"}}}'
ClojureScript 1.11.60
cljs.user=> (require '[clojure.core.match :as m])
Unexpected error (ExceptionInfo) compiling at (cljs/core/match.clj:9:1).
Only [lib.ns :only (names)] and optionally `:rename {from to}` specs supported in :use / :use-macros; offending spec: [clojure.core.match :exclude [match matchv match-let matchm]] at line 9 cljs/core/match.clj

borkdude21:03:42

I think with some effort it is doable, but not trivial. Hope that answers your question

Jason Whitlark21:03:38

Ok. It was a nice-to-have, but not essential. My cljs is a little too weak to be up to that.

pez21:03:46

Do we want an issue about it, @U04V15CAJ?

Jason Whitlark22:03:49

I wouldn’t mind putting in some work on it, but I’d need a lot of guidance. I used cljs heavily for a couple of years when it first came out, and have barely touched it since.

pez22:03:33

It will depend on that @U04V15CAJ has the bandwidth. I would be a blind leading a blind. 😃

borkdude22:03:08

I think the starting point should be an issue on Github and to collect who else would be interested in core.match in joyride. I have added it to bb at the time (by popular request) but I haven't seen much usage of it, to be honest

👍 2
pez22:03:39

Issue, please, @U03JLSD2F6V. 🙏

Jason Whitlark22:03:23

I’ve used it on occasion in bb. The stuff I’m porting to joyride was used in clj and bb, depending on the situation. Sure. Create an issue in joyride or SCI?

borkdude22:03:42

joyride. thanks for the feedback, maybe core.match is used more than I realize

borkdude22:03:33

as with rewrite-clj we waited a bit until we heard the request often enough to include it in joyride. it does take a bit of extra JS bundle size. eventually I want to make those things lazily loaded, but this requires some internal refactoring

borkdude22:03:31

but feel free to also start an experimental PR and then we can see how much bundle size it actually adds.

Jason Whitlark22:03:25

I use it quite a bit with rewrite-clj, since you just get nils when you move too far on a zipper, and it makes it clean for stuff like the following snippet (incomplete, but you get the idea):

(defn get-next-test [zl]
  (let [lhs (z/node zl)
        arrow (-> zl z/right z/string)
        rhs (-> zl z/right z/right z/node)]
    [lhs arrow rhs]))

(defn fix-fact-clause [l a r]
  (match [l a r]
    ;; Handle exceptions
    [actual '=> (['throws e (patt :guard regex?)] :seq)]  `(~'is (~'thrown-with-msg? ~e ~patt ~actual))
    [actual '=> (['throws (patt :guard regex?)] :seq)] `(~'is (~'thrown-with-msg? ~'Exception ~patt ~actual))
    [actual '=> (['throws e] :seq)] `(~'is (~'thrown? ~e  ~actual))
    ;; Handle regexes
    [actual '=> (patt :guard regex?)] `(~'is (~'re-find ~patt ~actual))
    ;; Handle predicate-fns
    [actual '=> (predicate :guard #(and (symbol? %) (= \? (-> % name last))))] `(~'is (~predicate ~actual))
    [actual '=not=> (predicate :guard #(and (symbol? %) (= \? (-> % name last))))] `(~'is (~'not (~predicate ~actual)))
    ;; Handle simple
    [actual '=> true] `(~'is ~actual)
    [actual '=> (['contains x] :seq)] (do (log :added-subcoll?) `(~'is (~'subcoll? ~x ~actual)))
    [actual '=> 'truthy] `(~'is ~actual)
    [actual '=> 'anything] `(~'is (~'anything ~actual))
    [actual '=> false] `(~'is (~'not ~actual))
    [actual '=> 'falsey] `(~'is (~'not ~actual))
    [actual '=> 0] `(~'is (~'zero? ~actual))
    [actual '=> nil] `(~'is (~'nil? ~actual))
    [actual '=> 'nil?] `(~'is (~'nil? ~actual))
    [actual '=> expected] `(~'is (~'= ~expected ~actual))
    [actual '=not=> expected] `(~'is (~'not (~'= ~expected ~actual)))
    :else  :failed-to-translate))

Jason Whitlark22:03:32

It’s really come in handy. I think of match as my DWIM function. 🙂

borkdude22:03:57

@U03JLSD2F6V I think adding it to sci.configs is a better idea actually, then we can re-use it anywhere we like, e.g. also in nbb https://github.com/babashka/sci.configs

borkdude22:03:30

You can check out the other configs for examples. E.g. the js-interop one also has a couple of macros that had to be lifted from the JVM runtime to the JS runtime

borkdude22:03:09

sci.configs is a different repo

Jason Whitlark23:03:15

I sponsored you through joyride. Not sure how that all works, but I’ll put my money where my mouth is. 😉

❤️ 4
borkdude23:03:33

thanks a lot!

Jason Whitlark23:03:54

Happy to help. I’ve been making money off Clojure since 2010. Sponsored Rich, way back in the day. I’m glad the various funding models are evolving.

Jason Whitlark23:03:38

Hmm. I looked at https://github.com/babashka/sci.configs/blob/main/src/sci/configs/applied_science/js_interop.cljs Not sure where to start. I’ll have to take a look at the sci docs when I get a chance. I’ve used it, but not looked under the hood since the beginning.

Jason Whitlark23:03:35

@U0ETXRFEW, the readme link points to src, but it’s now in scripts. Want another PR, or do you want to just tweak it?

pez23:03:16

I’ll fix it tomorrow. Thanks for heads-up!

pez22:03:47

The Joyride CI pipeline doesn't run... Circle CI says:

Could not find a usable config.yml, you may have revoked the CircleCI OAuth app.
Please sign out of CircleCI and log back in with your VCS before triggering a new pipeline.
I've tried sign out and sign in again with my Github account. But it remains like this. Anyone have experience with something like that on Circle CI?

borkdude22:03:31

you can add the circleci app to github for this repo or org, maybe that helps. I've also done this with bb etc

pez23:03:38

Now the pipeline started to work again. Added the Circle CI Checks things to Github, but I don't think that was what you meant?

👍 2