joyride

dumrat 2022-10-11T10:04:22.436029Z

Hi, I'm just curious. Is it possible to edit text in the editor with joyride? What I want is to type English and to convert that text to a different language (On a keypress - like space/tab/enter, etc).

borkdude 2022-10-11T10:08:02.183069Z

Is there a VSCode API for translating text? Or perhaps you can call an API? cc @pez

pez 2022-10-11T10:12:36.624909Z

Yes, entirely possible to edit text. Check out https://github.com/BetterThanTomorrow/joyride/blob/master/examples/.joyride/scripts/ignore_form.cljs for some inspiration. It uses https://github.com/BetterThanTomorrow/joyride/blob/master/examples/.joyride/scripts/z_joylib/editor_utils.cljs which also should be regarded as inspiration. (I think I would use .change on the edit builder rather than combining delete and insert.)

๐Ÿ‘ 1
dumrat 2022-10-11T10:14:10.804799Z

@pez Thanks will check it out

pez 2022-10-11T10:16:28.527419Z

If you want to update the examples with something that changes text, please do! I think this is on of the most general usages of Joyride there is.

๐Ÿ‘ 1
pez 2022-10-11T10:20:38.973229Z

Also, if it is Clojure code you want to edit, consider using Calva's editor.replace API: https://calva.io/api/#editorreplace Where it could be good to know that the editor.currentForm API call gives the selection if there is one. (Calva treats any selection as the current form). https://calva.io/api/#rangescurrentform

dumrat 2022-10-11T10:23:34.508829Z

@pez No, I do not want to edit Clojure code. All I want to do is transliterate English to Sinhala. It should work in the background replacing word by word without any key commands. Let me go through the samples. Looks promising. I was afraid I would have to write a VS extension. If I can get it done without that, I'd be happy.

๐ŸŽ‰ 2
dumrat 2022-10-11T12:36:59.454579Z

@pez Is it possible to add other libs and use within the user script? I would like to use instaparse - otherwise I'd have to write the parser by hand.

pez 2022-10-11T12:44:17.469019Z

I think our reach into the Clojure ecosystem is a bit limited. @borkdude knows more about this.

dumrat 2022-10-11T12:45:36.920479Z

@pez, makes sense. Can I invoke a http request from a script then? That's the second option.

borkdude 2022-10-11T12:45:41.254579Z

?

borkdude 2022-10-11T12:46:32.757999Z

you can do anything that the VSCode API (and Node.js) allows you to do

dumrat 2022-10-11T12:47:21.555549Z

ok let me dig more then

pez 2022-10-11T12:47:41.341919Z

Maybe npm has a parser you can use?

borkdude 2022-10-11T12:49:52.174359Z

@pez I don't think we have solved "loading a library from npm in joyride" yet?

pez 2022-10-11T12:50:47.144389Z

Haha, maybe not. I haven't tried, tbh.

pez 2022-10-11T12:55:08.232449Z

Can nbb do it?

borkdude 2022-10-11T12:55:47.893129Z

yes

pez 2022-10-11T12:56:19.522489Z

So that should mean we know how to solve it in Joyride, right?

borkdude 2022-10-11T12:57:02.462889Z

I think so. For workspace scripts, the joyride script should be able to load npm deps from the workspace.

borkdude 2022-10-11T12:58:31.455519Z

We might first want to move to sci.async though since loading those deps happens asynchronously

borkdude 2022-10-11T12:58:47.588409Z

although you could do it async with promesa as well

borkdude 2022-10-11T12:58:53.188099Z

in user space

borkdude 2022-10-11T12:59:16.935939Z

hmm, electron and ES6, this makes it more complicated though

borkdude 2022-10-11T12:59:46.661849Z

it's at least worth a try, first in user space, then in joyride itself

borkdude 2022-10-11T13:01:48.793439Z

so it seems we don't have to move to sci.async probably since es6 modules aren't supported in electron anyway

borkdude 2022-10-11T13:02:01.280969Z

We could just load libraries via js/require synchronously

borkdude 2022-10-11T13:04:44.768279Z

@pez What I do in nbb is use createRequire which receives the path of the script and then I call .resolve on that which returns the JS file of the library and then I load that using js/require

borkdude 2022-10-11T13:05:04.149029Z

(well, I used to do that, now it's a bit more complicated, but this is how it should work in joyride / electron I think)

borkdude 2022-10-11T13:07:54.813469Z

So in user space:

$ nbb
Welcome to nbb v1.0.136!
user=> (require '["module" :as m])
nil
user=> (require '["path" :as p])
nil
user=> (def req (m/createRequire (p/resolve "./script.cljs")))
#'user/req
user=> (.resolve req "squint-cljs")
"/Users/borkdude/dev/squint/index.js"

borkdude 2022-10-11T13:08:13.852589Z

And then you can do (js/require resolved) iff the resolved file is not an ES6 module ;)

borkdude 2022-10-11T13:08:57.851129Z

In joyride we have joyride.core/**file** which you can use as the script location

borkdude 2022-10-11T13:09:13.182729Z

if I remember correctly

pez 2022-10-11T13:10:30.324499Z

This would make Joyride close the gap to full extensions quite considerably, I think.

borkdude 2022-10-11T13:11:04.065259Z

That should already work today

borkdude 2022-10-11T13:11:37.886889Z

I'll try it locally

borkdude 2022-10-11T13:13:18.742759Z

how do I make a top level folder in vscode in that left pane... dang, it creates it in a subfolder

borkdude 2022-10-11T13:13:56.707789Z

I'll just use the terminal... fucking guis ;)

borkdude 2022-10-11T13:15:37.064299Z

When I print in a joyride script, where do I see the output?

borkdude 2022-10-11T13:17:30.442449Z

of course, in the developer tools

borkdude 2022-10-11T13:23:50.577659Z

Hmm, it seems vscode itself doesn't expose require?

(js/eval "require")

borkdude 2022-10-11T13:23:57.548589Z

=> require is not defined

borkdude 2022-10-11T13:24:53.376599Z

Perhaps we can fix that in joyride to begin with

borkdude 2022-10-11T13:33:24.847769Z

Success!

borkdude 2022-10-11T13:33:52.476809Z

(with a local build of joyride)

pez 2022-10-11T13:34:51.980899Z

OMG

borkdude 2022-10-11T13:37:22.540499Z

I think we can support this in our load-fn

borkdude 2022-10-11T13:37:27.165859Z

let me try

borkdude 2022-10-11T14:00:43.381839Z

@pez I have one problem that you might be able to help with. joyride.core/*file* isn't bound in the REPL, but it should. I've tried a bunch of things but I'm getting stackoverflows presumably due to debug logs in the nREPL or so

borkdude 2022-10-11T14:00:56.106509Z

let me put my work in a branch

borkdude 2022-10-11T14:02:27.248769Z

ok, wait, it works :))))

borkdude 2022-10-11T14:15:51.608539Z

https://github.com/BetterThanTomorrow/joyride/pull/91

pez 2022-10-11T14:36:12.966079Z

Sorry for being so irresponsive. Been in a meeting (in a #calva meeting as it happens ๐Ÿ˜„ )

pez 2022-10-11T15:54:33.822429Z

So amazing and fantastic! joyride

dumrat 2022-10-11T17:59:45.786809Z

@pez Ended up using vscode.WorkspaceEdit . It plays nicer than vscode.window.activeTextEditor the latter creating selections after editing which makes it not good for on the fly replacement. I have a lot of bug fixing to do, but managed to call a REST endpoint upon space/tab/newline and replace previous word with the transliteration. Loving calva btw. I can't use Clojure at my day job. But really enjoy the experience in VSCode. Thanks for all the effort you put in.

borkdude 2022-10-11T15:08:17.480069Z

^ loading npm libraries in joyride. This needs a new release with the open PR which I'm sure @pez will merge somewhere this week ;)

borkdude 2022-10-11T16:00:32.581519Z

@pez There have been some improvements to the promesa config in sci.configs. We could bump that + the promesa lib itself

โž• 1
borkdude 2022-10-11T16:00:45.762139Z

E.g. there is now a p/doseq macro

pez 2022-10-11T16:05:01.418919Z

๐Ÿ‘ 2
2
2
dumrat 2022-10-11T18:04:12.642429Z

This requires me first installing the relevant package with npm where the script resides is it?

pez 2022-10-11T18:41:53.573309Z

We should document this. Packages can be installed either in ~/.config/joyride/ or in the workspace root.

seancorfield 2022-10-11T16:37:35.005339Z

Can you explain how such modules would be declared as dependencies for the installation process? (I've never used npm and have avoided Node.js like the plague)

pez 2022-10-11T16:38:57.142009Z

nodejs is no plague! ๐Ÿ˜ƒ

seancorfield 2022-10-11T16:40:11.736429Z

I'm allergic to JavaScript ๐Ÿ˜›

pez 2022-10-11T16:41:26.705679Z

To use the example you need to have node. Then, in the workspace, you do:

$ npm init -y
$ npm install moment axios
BOOM.

seancorfield 2022-10-11T16:43:18.391599Z

Ah, since it can require ["vscode" :as vscode] I was wondering how/where it would find such other modules -- is "vscode" treated specially?

pez 2022-10-11T16:43:21.480429Z

npm init creates a minimum package.json for you. npm install create a node-modules directory which is similar to the .m2 maven thing, but local.

pez 2022-10-11T16:43:36.985709Z

Yes, "vscode" is special.

seancorfield 2022-10-11T16:44:07.208179Z

And there's a "global" (user-level) option? Since my Joyride scripts are user-level, not workspace-level.

pez 2022-10-11T16:44:31.858939Z

But it still tricked me into forgetting that we didn't support npm requires yet. Until I uttered that we should and @borkdude just made it work.

pez 2022-10-11T16:44:49.842279Z

Let me check up on the user level thing...

pez 2022-10-11T16:50:25.808889Z

It seems to work to run those ^ commands in ~/.config/joyride. Maybe @borkdude can explain why it works. ๐Ÿ˜ƒ

seancorfield 2022-10-11T16:51:50.267969Z

OK, cool. So I can keep the rest of my system free of nodejs pollution then... Perhaps a note in the docs/readme about that?

pez 2022-10-11T16:58:03.060079Z

My test might not have been sufficient. I just removed the dependency from my test workspace and ran the commands in the global folder. Then reloaded the vscode window and tried the examples in a user script. But youโ€™ll find out, I guess.

borkdude 2022-10-11T17:38:46.726159Z

The node modules are resolved relative to the script in question

borkdude 2022-10-11T17:39:03.551419Z

so user level should work with user level node_modules

pez 2022-10-11T20:16:45.589059Z

> The node modules are resolved relative to the script in question It seems, from my testing of createRequire and .resolve, that this should be read as that the first node_modules found from the script and up through it's directory ancestors... Hmmm, that got very hard to read. Anyway, I wonder if something like this in Joyride docs would describe it correctly and well enough: > npm packages that your scripts require should be npm installed in a node_modules/ directory somewhere in the requiring script's path. E.g. if you have node_modules in your system / (this is not a recommendation), then all Joyride scripts will be able to require packages from there. If you have node_modules side-by-side with a Joyride script, then only that script, sibling scripts and scripts in sub folders will be able to require from there. Some locations to consider are: > โ€ข For Workspace scripts: The workspace root. The .joyride/ folder in the workspace. > โ€ข For User scripts: ~/.config/joyride (or any subfolder there, if that makes sense for how you organize your user scripts)

pez 2022-10-11T20:20:36.931669Z

Actually that with the system root folder doesn't seem to be true...

borkdude 2022-10-11T20:27:55.497349Z

I think the suggestion should be that the node_modules should live as sibling of the script's directory or any of its parent directories.

borkdude 2022-10-11T20:28:27.798099Z

Typically: the root of a project as dev dependencies (`npm install --save-dev`) (or one level higher, .joyride )or indeed the joyride user directory for user script

pez 2022-10-11T20:32:01.868589Z

That's what I tried to suggest. ๐Ÿ˜ƒ

borkdude 2022-10-11T20:32:27.497039Z

very good then :)

pez 2022-10-11T20:32:52.771099Z

Well, I'm a bit unsure if I succeeded. Haha.

pez 2022-10-11T20:33:20.365049Z

And the example with the system root node_modules actually held true. I was making some mistakes testing it.

borkdude 2022-10-11T20:35:14.031369Z

It's exactly the same with the .clj-kondo directory :)

pez 2022-10-11T20:35:55.972929Z

But there it could even be a recommendation. ๐Ÿ˜ƒ

borkdude 2022-10-11T20:31:27.722549Z

I'm giving a CLJS-related presentation soon and joyride will also be appearing in it. If you have some nice example of how you are using it, please link it in the thread. A screenshot of the script in action which I can fit in a slide will also do.

1
borkdude 2022-10-11T20:31:32.972859Z

๐Ÿงต

borkdude 2022-10-11T20:32:08.626789Z

@seancorfield Wanna share/screenshot your clojuredocs example?

pez 2022-10-11T20:40:17.207679Z

I use this example quite a lot: https://github.com/BetterThanTomorrow/joyride/tree/master/examples#find-in-file-with-regexp-toggled-on Should be how VS Code works to begin with, but anyway. ๐Ÿ˜ƒ

๐Ÿ‘ 1
pez 2022-10-11T20:46:33.749529Z

Another one. Pasting the contents of the current file in a new, untitled, file/buffer:

{
        "key": "alt+ctrl+o p",
        "command": "joyride.runCode",
        "args": "(require '[promesa.core :as p]) (p/let [text (vscode/window.activeTextEditor.document.getText)\n doc (vscode/workspace.openTextDocument\n #js {:language \"clojure\", :content text})]\n (vscode/window.showTextDocument doc #js {:preview false, :preserveFocus false}))"
    },
It's good when I want to modify a library function, since VS Code won't let me edit the buffer when its showing a file from a jar file.

๐Ÿ‘ 1
seancorfield 2022-10-11T20:48:17.610989Z

@borkdude Not sure what's to share -- it's this https://github.com/seancorfield/vscode-calva-setup/blob/develop/joyride/scripts/javadoc.cljs bound to a hot key ๐Ÿ™‚

๐Ÿ‘ 1
borkdude 2022-10-11T20:48:21.755349Z

lol. ok. if you continue, we will have enough material for the London Clojurians meeting

seancorfield 2022-10-11T20:51:11.320419Z

Oh, that's the Java Docs version -- which is more complex. The ClojureDocs one just uses the current form as a selection to look up a URL on http://clojuredocs.org and open the Simple Browser. The Java Docs one requires you select a class name or expression (which will be eval'd) and then it gets the type/class of the result and gets the java docs URL and opens the Browser.

seancorfield 2022-10-11T20:51:53.207189Z

What do y'all use for doing screencasts/recordings? @borkdude @pez

pez 2022-10-11T20:54:35.523529Z

If I am recording VS Code I use an extension, Chronicler.

pez 2022-10-11T20:55:15.980579Z

Then I narrate in Final Cut Pro.

borkdude 2022-10-11T21:04:03.609549Z

Screencast: licecap or cmd-shift-5 (built into macOS which I know you're not using ;))

borkdude 2022-10-11T21:07:55.072359Z

I've also used OBS when I want to record my screen and voice / webcam

seancorfield 2022-10-11T21:25:51.454449Z

I tried OBS. It was horrible. Final Cut Pro is macOS @pez? I guess I could just use our Zoom account at work to create an ad hoc meeting, share my screen and record it ๐Ÿ™‚ But editing afterward is still a pain (I have used YouTube's "studio" to post-edit videos after upload but... ugh! nasty!)

borkdude 2022-10-11T21:28:48.510959Z

I just used OBS to record, but not edit and it worked for that. There are probably better (paid) solutions. I hate editing too. I found a program that let me cut out parts of the video. So I do everything in one take and when I make a mistake or want to do stuff over, I just cut out stuff from the 1 big take

borkdude 2022-10-11T21:31:42.999059Z

I think I've also used Screenflow like almost a decode ago (on mac), a really polished product, but I think my license long expired

seancorfield 2022-10-11T21:32:08.995839Z

I keep meaning try StreamYard to see if it's any better than other streaming/recording options... I created an account ages ago and did a couple of test casts but never got around to doing anything publishable...

borkdude 2022-10-11T21:33:34.529199Z

Oh, I think Martin (@mkvlr)mentioned an online solution to me a while back. I'll ask him

borkdude 2022-10-11T21:40:24.679409Z

It might be loom but I'm not sure: https://www.loom.com/share/72ee26ab1f2c4843aec9194ac7d8714e

borkdude 2022-10-11T21:42:12.700149Z

Probably recording in Zoom works just as well but then you will have to upload the video to youtube (or similar) and edit in some other program (if you want to edit)

skylize 2022-10-11T22:51:02.089959Z

If on Linux, and you can put up with alpha-version bugs and glitches, I suggest trying Olive for editing.

dumrat 2022-10-12T01:58:51.440969Z

Here's mine:

(ns hello-joyride-user-script
  (:require
   [joyride.core :as joyride]
   ["vscode" :as vscode]
   ["http" :as http]
   [promesa.core :as p]
   [clojure.string :as str]))

(defn current-line []
  (-> vscode/window .-activeTextEditor .-selection .-active .-line)) 

(defn current-language []
  (-> vscode/window .-activeTextEditor .-document .-languageId)) 

(defn get-current-line-text [line]
  (let [activeEditor (.-activeTextEditor vscode/window)
        selection-is-empty? (-> activeEditor .-selection .-isEmpty)]
    (if selection-is-empty?
      (.lineAt (.-document activeEditor) 
               line)
      nil)))

(defn get-last-word-info [ch]
  (let [line# (current-line)
        line# (if (= \newline ch) (dec line#) line#)
        line (.-_text (get-current-line-text line#))
        last-word (last (str/split line #"\s+"))]
    {:word last-word
     :line line#
     :length (count last-word)
     :start (- (count line) (count last-word))}))

(defn transliterate [word completion-fn]
  (let [data (atom "")]
    (http/get (str "" word) #js {}
               (fn [^js res]
                 (.on res "data" (fn [chunk]
                                   (swap! data str (.toString chunk))))
                 (.on res "end" (fn [] (completion-fn @data)))))))

(comment
  (vscode/workspace.onDidChangeTextDocument
   (fn [^js change]
     (when (and (= (current-language) "markdown")
                (= (.-document change) (-> vscode/window .-activeTextEditor .-document)))
       ; I don't know, does tab come as tab or spaces?
       (let [ch (#{\space \tab \newline "  " "    "} (-> change .-contentChanges (get 0) .-text))]
         (when ch
           (let [{:keys [word line start length]} (get-last-word-info ch)]
             (transliterate word
                            (fn [data]
                              (let [edit (vscode/WorkspaceEdit.)]
                                (.replace edit
                                          (-> change .-document .-uri)
                                          (vscode/Range. line (dec start) line (+ start length -1))
                                          data)
                                (.applyEdit vscode/workspace edit))))))))))
  )
And this at work below:

dumrat 2022-10-12T01:59:00.038149Z

pez 2022-10-12T05:10:58.203049Z

Awesome, @dumrat! Is transliterating from one script representation (latin/english letters) to some other?

dumrat 2022-10-12T05:37:41.538719Z

@pez Yes. The screencast above is transliteration from English to Sinhalese. Because it's a language only 16 million people use (and of a relatively poor people), there wasn't good support for Sinhalese for a long time so people used to just type whatever they wanted to say using the English alphabet although Sinhalese has it's own alphabet. The tools are getting better now, but the method of typing Sinhalese words using the English alphabet has remained. Hence, transliteration is a good choice for most people (myself included) when they don't want to memorize a new keyboard.

pez 2022-10-12T06:07:19.579549Z

Thanks! What's the rationale behind the choice to transliterate word-for-word instead of character by character? I'm guessing it is not a 1->1 mapping?

borkdude 2022-10-12T06:13:48.525709Z

This is awesome @dumrat

โค๏ธ 1
pez 2022-10-12T06:36:53.502269Z

@dumrat: In Typist (a VS Code extension) there is a mode where it simulates writing by pasting it in character by character. I have commands for toggling this on and off. Thinking you could do the something similar toggling that transliteration on and off via keyboard shortcuts. In Typist, I use an atom https://github.com/PEZ/paste-replaced/blob/master/src/paste_replaced/replacer.cljs For your script the commands could just install and uninstall the onchange handler. (If this is a desirable feature, but it seems to me that it would be.)

โค๏ธ 1
pez 2022-10-12T06:41:11.371269Z

@borkdude Typist is another example of how I use Joyride. I use it for prototyping when writing extensions. And for tweaking.

๐ŸŽ‰ 1
dumrat 2022-10-12T07:55:10.178249Z

@pez You are right, it's not a 1 to 1 character mapping. A simple grammar I use with instaparse for transliteration now is below:

S=word (whitespace word)*;
word=(any|vowel|pureconsonant|consonant)+
vowel='e'|'E'|'a'|'U'|'O'|'i'|'u'|'A'|'I'|'o'|'aa'|'ii'|'ei'|'AA'|'ou'|'au'|'sru'|'srU';
pureconsonant='T'|'d'|'n'|'K'|'w'|'s'|'f'|'L'|'p'|'j'|'G'|'J'|'v'|'B'|'P'|'t'|'k'|'b'|'r'|'y'|'g'|'l'|'N'|'h'|'m'|'D'|'dh'|'ch'|'Dh'|'xd'|'xj'|'Sh'|'xb'|'sh'|'xg'|'Ch'|'Th'|'th'|'thh'|'xmb'|'chh'|'xdh'|'xgdh'|'xkdh';
consonant=pureconsonant,vowel;
any=#'.*';
whitespace=#'(\s|\n|\t)+'
But this doesn't capture all. For example a run of characters like wyaa should ideally map to เท€เทŠโ€เถบเท while the simple grammar above will map it to เท€เทŠเถบเท. While not incorrect, this is considered uncultured ๐Ÿ˜„

dumrat 2022-10-12T08:01:41.333679Z

@pez I haven't come to enabling/disabling the transliteration yet but yes. That's a must. So I will take a look at what you mentioned. Thanks. I was thinking I can just add and remove the listener to the text changed event on some key combo. Or is that impossible to do?

dumrat 2022-10-12T08:11:02.608059Z

@pez As mentioned here: https://code.visualstudio.com/api/references/vscode-api#events All we'd need to do is have two key combinations referring to the same script and an atom to hold the callback for the event right? Or am I mistaken?

pez 2022-10-12T08:19:15.837249Z

Yes, you can do it like that, similar to what we do in this example: https://github.com/BetterThanTomorrow/joyride/blob/master/examples/.joyride/scripts/workspace_activate.cljs Or you could have your handler check the status and be a noop if transcibation is not enabled.

borkdude 2022-10-12T09:08:07.641249Z

(I realized I derailed my own thread here, but @seancorfield: this is what @mkvlr uses, https://www.descript.com/, let's continue video editing tools in another thread from now on)

pez 2022-10-13T22:55:03.338449Z

I might be presenting at a meetup next week. Preparing, I remember that I have made an extension (unpublished) that helps me step through Markdown Previews in VS Code. These are my slides, so that I can stay in VS Code as much as possible. Last time I presented anything there was no Joyride. Now that there is, I don't want to use a bloaty extension. ๐Ÿ˜ƒ So ported my extension to Joyride. The script:

(ns next-slide
  (:require ["vscode" :as vscode]
            [promesa.core :as p]
            [clojure.edn :as edn]))

(def ^:private !state (atom {:active? false
                             :active-slide 0}))

(defn- ws-root []
  (if (not= js/undefined
            vscode/workspace.workspaceFolders)
    (.-uri (first vscode.workspace.workspaceFolders))
    (vscode/Uri.parse ".")))

(defn next!
  ([]
   (next! true))
  ([forward?]
   (p/let [config-uri (vscode/Uri.joinPath (ws-root) "slides.edn")
           config-data (vscode/workspace.fs.readFile config-uri)
           config-text (-> (js/Buffer.from config-data) (.toString "utf-8"))
           config (edn/read-string config-text)
           slides (:slides config)
           next (if forward?
                  #(min (inc %) (dec (count slides)))
                  #(max (dec %) 0))]
     (swap! !state update :active-slide next)
     (vscode/commands.executeCommand "markdown.showPreview"
                                     (vscode/Uri.joinPath (ws-root)
                                                          (nth slides (:active-slide @!state)))))))

(defn toggle-active! []
  (swap! !state update :active? not)
  (vscode/commands.executeCommand "setContext" "next-slide:active" (:active? @!state))
  (vscode/window.showInformationMessage (str "next-slide:" (if (:active? @!state)
                                                             "activated"
                                                             "deactivated"))))
Keyboard shortcuts:
{
        "key": "ctrl+alt+cmd+space n",
        "command": "joyride.runCode",
        "args": "(next-slide/toggle-active!)"       
    },
    {
        "key": "right",
        "command": "joyride.runCode",
        "args": "(next-slide/next! true)",
        "when": "next-slide:active && !editorTextFocus"       
    },
    {
        "key": "left",
        "command": "joyride.runCode",
        "args": "(next-slide/next! false)",
        "when": "next-slide:active && !editorTextFocus"       
    },
Then I stick a file like this in my workspace:
{:slides ["hello.md",
          "vic-20.md",
          "brooks.md",
          "plotter.md",
          "clojure.md",
          "thanks.md"]}
This assumes those files are in the workspace root as well. Then when presenting, I: 1. Load the next_slide.cljs script (I have it as a User script). 2. ctrl+alt+cmd+space n to activate next-slide. 3. Flick back and forth through the slides with right and left.

pez 2022-10-13T22:55:30.671699Z

I'll add this as an example to Joyride when I have some time.

pez 2022-10-13T22:56:36.578799Z

The script would get simpler if we supported (slurp), btw. ๐Ÿ˜ƒ I think I'll add that some day soon too.

borkdude 2022-10-14T08:45:47.476629Z

nbb also has slurp in nbb.core (which returns a promise)