Fork me on GitHub
#joyride
<
2022-06-01
>
pez08:06:56

My first attempt to lazy load Calva in user space failed: https://clojurians.slack.com/archives/C03S1KBA2/p1654070707175239

pez08:06:46

This is what I tried with:

(defn- my-main []
  (println "Hello World, from my-main in user activate.cljs script")
  (clear-disposables!)
  (-> (vscode/extensions.getExtension "betterthantomorrow.calva")
      (.activate)
      (p/then (fn [_api]
                (.appendLine (joyride/output-channel) "Calva activated. Requiring dependent namespaces.")
                (require '[my-lib]) ; See this script for why we require it
                (require '[z-joylib.clojure-symbols :as clojure-symbols])
                (push-disposable (clojure-symbols/register-provider!))))
      (p/catch (fn [error]
                 (vscode/window.showErrorMessage (str "Requiring Calva failed: " error))))))

pez08:06:51

So, I got my answers to this here: https://clojurians.slack.com/archives/C03S1KBA2/p1654070707175239 and the code now looks like so:

(defn- my-main []
  (println "Hello World, from my-main in user_activate.cljs script")
  (clear-disposables!) ;; Any disposables add with `push-disposable!`
                       ;; will be cleared now. You can push them anew.

  ;;; MARK require VS Code extensions
  ;; In an activation.cljs script it can't be guaranteed that a
  ;; particular extension is active, so we can't safely `(:require ..)`
  ;; in the `ns` form. Here's what you can do instead, using Calva
  ;; as the example. To try it for real, copy the example scripts from:
  ;;  
  ;; Then un-ignore the forms in the promise handler and run
  ;;   *Joyride; Run User Script* -> activate.cljs
  ;; (Or reload the VS Code window.)
  (-> (vscode/extensions.getExtension "betterthantomorrow.calva")
      ;; Force the Calva extension to activate 
      (.activate)
      ;; The promise will resolve with the extension's API as the result
      (p/then (fn [_api]
                (.appendLine (joyride/output-channel) "Calva activated. Requiring dependent namespaces.")
                ;; In `my-lib` and  `z-joylib.calva-api` the Calva extension
                ;; is required, which will work fine since now Calva is active.
                (require '[my-lib])
                #_(require '[z-joylib.calva-api])
                ;; Code in your keybindings can now use the `my-lib` and/or
                ;; `z-joylib.calva-api` namespace(s)

                ;; Registering a symbols provider
                (require '[z-joylib.clojure-symbols :as clojure-symbols])
                ;; Entering the Gilardi scenario. 
                (push-disposable! ((resolve 'clojure-symbols/register-provider!)))))
      (p/catch (fn [error]
                 (vscode/window.showErrorMessage (str "Requiring Calva failed: " error))))))
Where the relevant part is (push-disposable! ((resolve 'clojure-symbols/register-provider!))). @borkdude, you said this will stop working once we have ❤️ sci-async ❤️ in place. Is there a way I can prepare this script for that future, or is it something I need to wait with doing?

borkdude08:06:58

Yes! Use (p/let [_ (require '[the-ns]) var (resolve 'the-ns/foo)] ...)

🙏 1
pez13:06:27

When a user has a script with the same name in both workspace and user areas. They will write to the same namespace, won't they? This will currently always happen with the activate.cljs scripts, right?

pez13:06:43

I guess what I want to do is write something in the docs about it. But first I need to understand the implications a bit better. For instance, right now I have a (defonce !db (atom {:disposables []})) in both my activate.cljs files. I'm struggling a bit with figuring out if this is a problem.

borkdude13:06:19

Yes, we discussed that before, it's a classpath: user:workspace But if you load both files explicitly (as happens with activation.cljs), then those namespaces will be "merged", as in, side effects will happen in the same namespace

borkdude13:06:05

So if user/activation.cljs has (ns foo) and project/activation.cljs also has (ns foo) , and you have vars with the same name, this will conflict

pez13:06:23

In this !db case it will become a problem. 1. User activate.cljs loads and pushes some disposables and swaps them into the db. 2. Workspace activate.cljs does the same. Swapping into the same db. 3. The user reloads one of these. All disposables are cleared. Only one set of disposables are re-created. So the user needs to use different names for these, right?

borkdude13:06:01

Yes, it's safest to require unique namespace names from our activation.cljs scripts, I think

pez13:06:48

I'm thinking about the activate namespace itself here.

borkdude13:06:12

Yes. That doesn't matter, but your !db var has to live in a unique namespace to not conflict

borkdude13:06:50

So put that in my_project/db.cljs and then require that from your activation

pez13:06:46

Ah, yes. There are several possible projects that use the namespace as well.

borkdude13:06:14

Maybe the global and local "activation" scripts should have different names?

borkdude13:06:40

user_activate.cljs
project_activate.cljs

pez13:06:29

Oh, wow. Using clojure-lsp refactor-rename on the !db symbol in my workspace activate script to !workspace-db renamed it in my user activate script as well.

pez13:06:15

For now the naming scheme you suggest would solve this. But as soon as we fix the problem with allowing joyride to work for all projects in the VS Code window...

pez16:06:59

Dear Joyriders. Please note that the change in v0.0.15 means you'll need to copy any custom things you might have in your current activate.cljs scripts over to user_activate.cljs and/or workspace_activate.cljs. Please also note that the user_activate.cljs file will again be auto-created for you. The silver lining here is that it is a more useful activation script skeleton, with facilities for registering VS Code disposables in a REPL reloadable manner. It also has a recipe for safely requiring VS Code extensions, and you should start using that instead of any non-lazy requiring you might be doing today

pez16:06:59
replied to a thread:

Dear Joyriders. Please note that the change in v0.0.15 means you'll need to copy any custom things you might have in your current activate.cljs scripts over to user_activate.cljs and/or workspace_activate.cljs. Please also note that the user_activate.cljs file will again be auto-created for you. The silver lining here is that it is a more useful activation script skeleton, with facilities for registering VS Code disposables in a REPL reloadable manner. It also has a recipe for safely requiring VS Code extensions, and you should start using that instead of any non-lazy requiring you might be doing today

mauricio.szabo17:06:09

Joyride friends: in Clover, I expose multiple APIs that expect or return EDN. I'm currently translating them to JS, but it can be tricky: for example, one API is (eval-and-present <text> <range>). The range, in this case, is #js [ #js [1 2] #js [1 3]], for example - it's quite hard to write and we have to remember to use #js before, or use clj->js. Maybe this is also an SCI version, but maybe there's a way to make this conversion either semi-automatic, or at least somehow on ClojureScript side I can detect that it was a "SCI Vector" and convert back to JS... WDYT? I know all of the problems that SCI needs to face (advanced compilation renaming the methods, etc) but I don't know, maybe there's some way to at least preserve some method name that I can call on Clover side... :thinking_face:

borkdude17:06:58

@mauricio.szabo Do you mean, you would call an extension function on joyride to convert to JS?

mauricio.szabo18:06:23

Or expose this to the objects that come from Joyride side

borkdude18:06:59

I'm not sure if I follow

borkdude18:06:07

Can you paint more context?

borkdude18:06:24

What objects come from the joyride side and why, as a result of doing what?

mauricio.szabo18:06:29

Sure - this is what happens right now: https://gitlab.com/clj-editors/clover/-/blob/master/src/clover/joyride.cljs#L20-25 All code that expects parameters from Joyride call norm-range, that basically checks if the object is what we expect (a Javascript array of arrays) and if it's not, it will simply ignore the parameter and prepare a default value.

borkdude18:06:14

So if users want to call your extension function, then they would have to convert to JS, is that what you mean?

mauricio.szabo18:06:05

I wanted to check if I detect that the object is not a Javascript array of arrays, if I could convert it to JS - that way, people could call my extension with (do-something "a-text" [[1 1] [1 2]]), without needing to convert the second parameter

borkdude18:06:43

That probably doesn't work since your extension is compiled in a different project than joyride

mauricio.szabo18:06:56

On my extension side I could use something like (if-let [as-js-obj (.-as_js_object param)) ...

borkdude18:06:54

I think it's not unreasonable to expect that users should call extension functions using JS types

pez08:06:51

So, I got my answers to this here: https://clojurians.slack.com/archives/C03S1KBA2/p1654070707175239 and the code now looks like so:

(defn- my-main []
  (println "Hello World, from my-main in user_activate.cljs script")
  (clear-disposables!) ;; Any disposables add with `push-disposable!`
                       ;; will be cleared now. You can push them anew.

  ;;; MARK require VS Code extensions
  ;; In an activation.cljs script it can't be guaranteed that a
  ;; particular extension is active, so we can't safely `(:require ..)`
  ;; in the `ns` form. Here's what you can do instead, using Calva
  ;; as the example. To try it for real, copy the example scripts from:
  ;;  
  ;; Then un-ignore the forms in the promise handler and run
  ;;   *Joyride; Run User Script* -> activate.cljs
  ;; (Or reload the VS Code window.)
  (-> (vscode/extensions.getExtension "betterthantomorrow.calva")
      ;; Force the Calva extension to activate 
      (.activate)
      ;; The promise will resolve with the extension's API as the result
      (p/then (fn [_api]
                (.appendLine (joyride/output-channel) "Calva activated. Requiring dependent namespaces.")
                ;; In `my-lib` and  `z-joylib.calva-api` the Calva extension
                ;; is required, which will work fine since now Calva is active.
                (require '[my-lib])
                #_(require '[z-joylib.calva-api])
                ;; Code in your keybindings can now use the `my-lib` and/or
                ;; `z-joylib.calva-api` namespace(s)

                ;; Registering a symbols provider
                (require '[z-joylib.clojure-symbols :as clojure-symbols])
                ;; Entering the Gilardi scenario. 
                (push-disposable! ((resolve 'clojure-symbols/register-provider!)))))
      (p/catch (fn [error]
                 (vscode/window.showErrorMessage (str "Requiring Calva failed: " error))))))
Where the relevant part is (push-disposable! ((resolve 'clojure-symbols/register-provider!))). @borkdude, you said this will stop working once we have ❤️ sci-async ❤️ in place. Is there a way I can prepare this script for that future, or is it something I need to wait with doing?