Fork me on GitHub

New Joyride out: It reduces the amount of boilerplate when consuming the exported API of an extension. See attached snippet for some code exercising the new require API. • Updated API docs: • Updated Calva Extension API wrapper example:

🎉 2

Looking good :)


@U0ETXRFEW I have an idea for this

(p/then (fn [v]
                (.appendLine oc (.-result v)))
stuff. Would it be an idea to be able to set *print-fn* to (.appendLine oc ....)?


Then you can just use:

(println v)


Or perhaps we can set prn / println by default to go to joyride's output channel? Bad idea?


Or ... joyride could offer a function for printing to the output channel 💡


joyride/prn + joyride/println


(p/then joyride/println)


I like the idea to make it a joyride.core facility. I think many shadow-cljs users will expect println to go to the console/the repl output.


joyride API function it is


The user space solution you suggested, can I do it without wrapping the code in binding stuff?


And people can do:

(binding [*print-fn* joyride/println] ...) 
in their scripts, yes


Yes, you can use alter-var-root to permanently set it


hmm, that might not work


anyway, we can make that work ;)


> hmm, that might not work clj-kondo complains 😃

Unresolved symbol: alter-var-rootclj-kondo(unresolved-symbol)
And also I get weird results:
ERROR: Run User Script... Failed: my_lib.cljs No protocol method IVar.getRawRoot defined for type function: function shadow$cljs$devtools$client$env$set_print_fns_BANG__$_repl_print_fn(s){
(msg_fn.cljs$core$IFn$_invoke$arity$2 ? msg_fn.cljs$core$IFn$_invoke$arity$2(new cljs.core.Keyword(null,"stdout","stdout",-531490018),s) :,new cljs.core.Keyword(null,"stdout","stdout",-531490018),s));

if(cljs.core.truth_((function (){var and__4251__auto__ = original_print_fn;
return cljs.core.not_EQ_.cljs$core$IFn$_invoke$arity$2(s,"\n");
} else {
return and__4251__auto__;
return (original_print_fn.cljs$core$IFn$_invoke$arity$1 ? original_print_fn.cljs$core$IFn$_invoke$arity$1(s) :,s));
} else {
return null;


You need to write (alter-var-root #'*print-fn* ...)


clj-kondo assumes that CLJS has no alter-var-root which is true for normal CLJS ;)


We can maybe hide this behind joyride.core/set-print-fn


I updated my Joyride scripts in my vscode-calva-setup repo to take advantage of this simpler approach -- very nice!!


I was thinking that when the order becomes a problem, maybe the alias + refers could act lazily and will look themselves up in the extension on the first call. But so far I haven't heard a report that this was a problem.


order as in: joyride gets loaded before any other extension you are requiring


☝️:skin-tone-2: Hmm, I hadn't considered that order of requires might be problematic... I like to keep mine strictly alpha order which would put all the string imports above the actual namespaces, and "ext://.." above "vscode"...


(ns javadoc
  (:require ["$v0.repl" :refer [evaluateCode]]
            ["vscode" :as vscode]
            [clojure.edn :as edn]
            [clojure.string :as str]
            [promesa.core :as p]))
Are you saying there are potential problems doing ☝️:skin-tone-2: that @U04V15CAJ?


(I'm not even requiring any joyride namespaces, I just realized)


@U04V70XH6 I don't know in what order joyride is loaded compared to calva. So if joyride is loaded first and this is in your activation script, the calva extension may not be there yet. The order in joyride scripts does not matter.


I'm still wondering if this is a problem or not, I'm not sure


Ah, OK, then I won't worry. My activation script is pretty much empty. Does the activate.cljs even need to require "vscode", joyride.core, or promesa.core?


(I've deleted everything except that :require for now)


I don't know what people will typically need in their activation scripts. But if you only load extension functions while everything is up and running, then there is nothing to worry about


So far I have never seen Calva not being loaded when Joyride runs the activate.cljs scripts. I recall something about that * activation event being necessary to stop VS Code from switching to the Joyride output channel. That * event is called StartUp in the VS Code docs. > The * activation event is emitted and interested extensions will be activated whenever VS Code starts up. Which is a bit confusing, because it seems to guarantee that Joyride will be active before most other extensions. At least those that are slower to start, which Calva is.


We'll see if we run into problems or not with this. Maybe we should debug log from both Calva and Joyride at activation time to see what that gives. I could debug log from Paste Replace as well, since it is super lightweight and quick to start.


You don't need any activation script at all, @U04V70XH6, but you probably know that. 😃


Yeah, but if there's no script, it'll create one, right? So I guess the minimal script to prevent that is (ns activate) 🙂


I just wasn't sure if, in adding the auto-creation of activate.cljs, you were relying on Joyride actually executing it to set something up in Joyride itself these days.


I tried to talk @U0ETXRFEW out of auto-creating things and stealing focus of the output window but to no avail ;P


Yes, you're right, @U04V70XH6, a minimal script is needed to not trigger the Getting Started stuff.


We should probably create a more useful activate.cljs skeleton. Like the one in one of the examples.


Haha, @U04V15CAJ, you were the only one suggesting that, and since you are not a VS Code user anyway, it shouldn't be bothering you. 😃


@U04V70XH6, good that you also moved your use of evaluateCode to the repl submodule. I'll be getting rid of the top level one soon.


I don't think I was the only one suggesting that, but I could be wrong ;-)

borkdude20:05:57 Yeah, I just don't like tools that steal focus of other tools, I get a bit annoyed by it, even if you can turn it off. And it's not true that I'm not using VSCode, I do use it, just not as my primary editor.


Yes, some other people requested a way to turn it off, and we provided that. I think it's fine with one seldom-user who is still annoyed that he had to switch it off. 😃


I think I complained about stealing focus? 🙂


Yes, you were one of the people asking for a way to turn it off.


I wouldn't go so far as to say I was "annoyed" that I had to switch it off but, perhaps, "somewhat miffed"? :rolling_on_the_floor_laughing:

😆 1

Personally I would have taken that as a hint that people don't like that behavior by default, but we have different opinions and that's fine.


I see it as a trade-off. A demo and a getting-started point on one side, some miff/annoyance on the other.


I also see it as a trade-off but my trade-off would be on the side of not creating noise/files in a project. E.g. a link to examples in the output window (while not stealing focus, VSCode users know how to find that window?) would be another solution. But it's not a big deal, I can live with it ;)


> VSCode users know how to find that window I don't think that's true for beginners. Heck, I open the output/log window so rarely I still go through the command palette because I can never remember the hot key! 🙂


To my experience tons of VS Code users do not know how to find output channels. Others do not realize they should look for it. I've had the output channel of Calva not default pop open for long periods enough not to consider going back to such a default again. A whole category of support questions are almost completely removed by the current default.


Fair enough


Re not needing an activation script, don't I need one to require my library and use fn invocations in my commands?


I prefer that to user scripts


@U7PBP4UVA I also prefer to invoke functions rather than scripts from my keyboard shortcuts. So that's a good use for the activation script for me too.


Why do you need an activation script for that?


So that something has required the namespace from where I invoke the functions. Like with this example:


I don't think you have to require namespaces ahead of time for this, they can be just in time loaded


It would be possible if we could pass in a function as a namespaced symbol, then it could be required-resolved. Right now you pass a form to be evaluated. I don't know if sci supports require-resolve though?


It does right now, but when we move to async eval then require becomes async. Supporting a function symbol + args seems like a more robust approach


However if you take into account now that requiring-resolve becomes async, then you can also start using it now


But if you just write a top level require followed by the function expression this should work either way


Yes, if you also put the require in the shortcut, then that works as well.


Ah, that's nice to know. I'll try out the new APIs and this later today.


I like to keep my shortcut definitions short, though, so adding (require ...) to all of them is not up my alley. 😃


A small price to pay when it comes to extension loading order troubles but whatever you fancy ;-) (and you can always migrate to explicit require later when you have such troubles)


This convenience require is just a small thing. But not being able to use extension APIs from my activate.cljs would be a big problem. Still haven't seen it happen, which is a bit strange.


This has been a great thread! I think I might overhaul my current Calva/Joyride config to work more like a library that gets required in activate.cljs and switch over to the joyride.runCode approach, even for a lot of my custom REPL command snippets -- because it'll be easier to build complex code strings in Joyride/sci that just having big blobs in my settings.json file:


I guess it also makes it less likely that people's Joyride scripts will collide since they can be namespaced (I'll probably split mine up into seancorfield.test, seancorfield.portal, etc).


Yes, just note that requiring early vs requiring on demand may cause some friction with extension order. But you can deal with that when that happens


You could of course define a macro in your library code which requires just in time ;)