diff --git a/README.md b/README.md index 976ebcc..fd31a29 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Making VS Code Hackable +# Making VS Code Hackable since 2022 -Modify your editor while it is running by executing ClojureScript code via the Joyride REPL and/or run scripts via keyboard shortcuts you choose. The Visual Studio Code API, as well as the APIs of its extensions, are at your command! +Modify your editor while it is running by executing ClojureScript code via the Joyride REPL and/or run scripts via keyboard shortcuts you choose. The Visual Studio Code API, as well as the APIs of its extensions, are at your command! Joyride makes VS Code scriptable in a very similar way to how how Emacs users can hack their editor. Complete with Interactive Programming. https://user-images.githubusercontent.com/30010/165934412-ffeb5729-07be-4aa5-b291-ad991d2f9f6c.mp4 @@ -8,7 +8,7 @@ https://user-images.githubusercontent.com/30010/165934412-ffeb5729-07be-4aa5-b29 Joyride is Powered by [SCI](https://github.com/babashka/sci) (Small Clojure Interpreter). -The default language of Joyride is [Clojure](https://clojure.org), but you can also use JavaScript for hacking your VS Code environment. +You can use both JavaScript and ClojureScript with Joyride. You will only get to enjoy Interactive Programming using ClojureScript, because JavaScript does not support it. Also the JavaScript support in Joyride is new and not yet fully at par with the ClojureScript support. See [doc/api.md](https://github.com/BetterThanTomorrow/joyride/blob/master/doc/api.md) for documentation about the Joyride API. @@ -28,15 +28,109 @@ You can run or open the scripts using commands provided (search the command pale * **Joyride Run Workspace Script...**, default keybinding `ctrl+alt+j w` * **Joyride Open Workspace Script...** -**Note, about namespaces**: Joyride effectively has a classpath that is `user:workspace`. A file `/foo_bar.cljs`, will establish/use a namespace `foo-bar`. As will a file `/foo_bar.cljs`. Any symbols in these files will be shared/overwritten, as the files are loaded and reloaded. There are probably ways to use this as a power. Please treat it as a super power, because you might also hurt yourself with it. +**Note, about Clojure namespaces**: Used with ClojureScript, Joyride effectively has a classpath that is `user/scripts:user/src:workspace/scripts:workspace/src`. A file `/foo_bar.cljs`, will establish/use a namespace `foo-bar`. As will a file `/foo_bar.cljs`. Any symbols in these files will be shared/overwritten, as the files are loaded and reloaded. There are probably ways to use this as a power. Please treat it as a super power, because you might also hurt yourself with it. -## Quickest Start 1 - Install Joyride +## Quickest Start - Start Here - Install Joyride Installing Joyride will also install, and run, a sample `user_activate.cljs` User script. You can use this script as a base for init/activation stuff of your VS Code environment. -Joyride installs a "regular” User script as well. You can run either of these with the commands mentioned above. +Joyride installs two "regular” User scripts: -## Quickest Start 2 - Run some Code +* `/.config/joyride/scripts/hello_joyride_user_script.cljs` +* `/.config/joyride/scripts/hello_joyride_user_script.js` + +You can run these scripts with the commands mentioned above. + +Also: In the **Joyride: Run Workspace Script** menu, there is a command for downloading and installing some default/example workspace scripts. + +## Quick Start - Start your Scripts Library + +Joyride lets you bind keyboard shortcuts to its User and Workspace scripts. + +* User Scripts: `/.config/joyride/scripts` +* Workspace scripts: `/.joyride/scripts` + +Let's go with a Workspace script: Create a folder and open it in VS Code. + +Both the scripts here do almost the same thing: They show an information message and writes to a file in +the root of the workspace. Create both, why don't ya? + +### Using JavaScript + +Create the file `.joyride/scripts/example/write-a-file.js`: + +```javascript +const fs = require("fs"); +const path = require("path"); +const vscode = require("vscode"); + +function info(...xs) { + vscode.window.showInformationMessage(xs.join(" ")); +} + +const rootPath = vscode.workspace.workspaceFolders[0].uri.fsPath; +info("The root path of this workspace:", rootPath); +fs.writeFileSync( + path.resolve(rootPath, "test-from-js-script.txt"), + "Written from a Workspace JavaScript Script!" +); +``` + +### Using ClojureScript + +Create the file `.joyride/scripts/example/write_a_file.cljs`: + +``` clojure +(ns example.write-a-file + (:require ["fs" :as fs] + ["path" :as path] + ["vscode" :as vscode] + [clojure.string :as str])) + +(defn info [& xs] + (vscode/window.showInformationMessage (str/join " " xs))) + +(def root-path (-> (first vscode/workspace.workspaceFolders) .-uri .-fsPath)) +(info "The root path of this workspace:" root-path) +(fs/writeFileSync (path/resolve root-path "test-from-cljs-script.txt") + "Written from a Workspace ClojureScript Script!") +``` + +### Bind the scripts to a keyboard shortcut. + +You can run the scripts from the **Joyride: Run Workspace Script..** menu. But for the exercise we'll create keyboard shortcuts too: + +In your keyboard shortcuts JSON file, add: + +``` json + { + "key": "shift+ctrl+alt+j 1", + "command": "joyride.runWorkspaceScript", + "args": "example/write-a-file.js" + } + { + "key": "shift+ctrl+alt+j 2", + "command": "joyride.runWorkspaceScript", + "args": "example/write_a_file.cljs" + } +``` + +Now you can run the scripts from the keyboard shortcuts! + +Note: Because of how VS Code renders the command palette it is good to add the default `joyride.runWorkspaceScript` keybinding as the last bindings in the JSON file: + +```json + { + "command": "joyride.runWorkspaceScript", + "key": "ctrl+alt+j w", + } +``` + +See [doc/configuration.md](https://github.com/BetterThanTomorrow/joyride/blob/master/doc/configuration.md) for full configuration options. + +## Quickest Start - Run some Code + +This currently only works with ClojureScript code: 1. Bring up the VS Code Command Palette (`cmd/ctrl+shift+p`) 2. Execute **Joyride: Run Clojure Code...** @@ -46,7 +140,9 @@ Joyride installs a "regular” User script as well. You can run either of these ``` 4. Submit -## Quickest Start 3 - Evaluate the selection +## Quickest Start - Evaluate the selection + +Only works with ClojureScript code: 1. Select some code (e.g. the code some lines above in this markdown file, even if in Preview.) 2. Execute **Joyride: Evaluate Selection**, (ctrl+alt+j, enter) @@ -82,49 +178,6 @@ The demo ”project” used here is only a directory with this file `hello_joyri "Hello World" ``` -## Quick Start - Start your Scripts Library - -Joyride lets you bind keyboard shortcuts to its User and Workspace scripts. - -* User Scripts: `/.config/joyride/scripts` -* Workspace scripts: `/.joyride/scripts` - -Let's go with a Workspace script: - -Create a script in your workspace, e.g `.joyride/scripts/example.cljs`: - -``` clojure -(ns example - (:require ["fs" :as fs] - ["path" :as path] - ["vscode" :as vscode] - [clojure.string :as str])) - -(defn info [& xs] - (vscode/window.showInformationMessage (str/join " " xs))) - -(info "The root path of this workspace:" vscode/workspace.rootPath) - -(fs/writeFileSync (path/resolve vscode/workspace.rootPath "test.txt") "written!") -``` - -This script gives one information message and writes to a file `test.txt` in -your workspace. - -Then in your keyboard shortcuts, add: - -``` json - { - "key": "cmd+1", - "command": "joyride.runWorkspaceScript", - "args": "example.cljs" - } -``` - -Now you can run the `example.cljs` script by just hitting Cmd+1! - -See [doc/configuration.md](https://github.com/BetterThanTomorrow/joyride/blob/master/doc/configuration.md) for full configuration options. - ## Examples See the [examples](./examples) for examples including: diff --git a/vscode-test-runner/workspace-1/.joyride/scripts/example/write-a-file.js b/vscode-test-runner/workspace-1/.joyride/scripts/example/write-a-file.js new file mode 100644 index 0000000..9db8284 --- /dev/null +++ b/vscode-test-runner/workspace-1/.joyride/scripts/example/write-a-file.js @@ -0,0 +1,14 @@ +const fs = require("fs"); +const path = require("path"); +const vscode = require("vscode"); + +function info(...xs) { + vscode.window.showInformationMessage(xs.join(" ")); +} + +const rootPath = vscode.workspace.workspaceFolders[0].uri.fsPath; +info("The root path of this workspace:", rootPath); +fs.writeFileSync( + path.resolve(rootPath, "test-from-js-script.txt"), + "Written from a Workspace JavaScript Script!" +); diff --git a/vscode-test-runner/workspace-1/.joyride/scripts/example/write_a_file.cljs b/vscode-test-runner/workspace-1/.joyride/scripts/example/write_a_file.cljs new file mode 100644 index 0000000..f9dd115 --- /dev/null +++ b/vscode-test-runner/workspace-1/.joyride/scripts/example/write_a_file.cljs @@ -0,0 +1,13 @@ +(ns example.write-a-file + (:require ["fs" :as fs] + ["path" :as path] + ["vscode" :as vscode] + [clojure.string :as str])) + +(defn info [& xs] + (vscode/window.showInformationMessage (str/join " " xs))) + +(def root-path (-> (first vscode/workspace.workspaceFolders) .-uri .-fsPath)) +(info "The root path of this workspace:" root-path) +(fs/writeFileSync (path/resolve root-path "test-from-cljs-script.txt") + "Written from a Workspace ClojureScript Script!") \ No newline at end of file diff --git a/vscode-test-runner/workspace-1/.joyride/src/integration_test/runner.cljs b/vscode-test-runner/workspace-1/.joyride/src/integration_test/runner.cljs index 167b3ef..4bd5d2b 100644 --- a/vscode-test-runner/workspace-1/.joyride/src/integration_test/runner.cljs +++ b/vscode-test-runner/workspace-1/.joyride/src/integration_test/runner.cljs @@ -37,7 +37,7 @@ (let [{:keys [running pass fail error]} @db/!state passed-minimum-threshold 20 fail-reason (cond - (> 0 (+ fail error)) "FAILURE: Some tests failed or errored" + (< 0 (+ fail error)) "FAILURE: Some tests failed or errored" (< pass passed-minimum-threshold) (str "FAILURE: Less than " passed-minimum-threshold " assertions passed") :else nil)] (println "Runner: tests run, results:" (select-keys @db/!state [:pass :fail :error])) diff --git a/vscode-test-runner/workspace-1/.joyride/src/integration_test/scripts_test.cljs b/vscode-test-runner/workspace-1/.joyride/src/integration_test/scripts_test.cljs index d18e9cc..b20aa7b 100644 --- a/vscode-test-runner/workspace-1/.joyride/src/integration_test/scripts_test.cljs +++ b/vscode-test-runner/workspace-1/.joyride/src/integration_test/scripts_test.cljs @@ -7,6 +7,16 @@ ["vscode" :as vscode] ["util" :as util])) +(def access (util/promisify fs.access)) +(def read-file (util/promisify fs.readFile)) +(def write-file (util/promisify fs.writeFile)) +(def append-file (util/promisify fs.appendFile)) +(def rm (util/promisify fs.rm)) + +(def ws-root-path (-> (first vscode/workspace.workspaceFolders) + .-uri + .-fsPath)) + (deftest-async run-a-user-script (testing "Runs a user script" (p/let [result (vscode/commands.executeCommand "joyride.runUserScript" "hello_joyride_user_script.cljs")] @@ -25,25 +35,30 @@ (is (= :a-ws-script result))))) -(deftest-async run-a-ws-javascript-script-dashes - (testing "Runs a workspace script written in JavaScript, named with dash separators" - (p/let [result (vscode/commands.executeCommand "joyride.runWorkspaceScript" "a-ws-script.js")] - (is (= 42 - (.-fortytwo result)))))) +(deftest-async run-a-ws-cljs-script-from-subdir + (testing "Runs a workspace ClojureScript script from a subdirectory" + (p/let [script "example/write_a_file.cljs" + _ (vscode/commands.executeCommand "joyride.runWorkspaceScript" script) + written-file (path/join ws-root-path "test-from-cljs-script.txt") + content (read-file written-file #js {:encoding "utf8"})] + (is (= "Written from a Workspace ClojureScript Script!" + content)) + (rm written-file)))) + +(deftest-async run-a-ws-js-script-from-subdir + (testing "Runs a workspace JavaScript script from a subdirectory" + (p/let [script "example/write-a-file.js" + _ (vscode/commands.executeCommand "joyride.runWorkspaceScript" script) + written-file (path/join ws-root-path "test-from-js-script.txt") + content (read-file written-file #js {:encoding "utf8"})] + (is (= "Written from a Workspace JavaScript Script!" + content)) + (rm written-file)))) (deftest-async run-a-javascript-script-reloads (testing "Runs a workspace script written in JavaScript, reloading changes" - (p/let [write-file (util/promisify fs.writeFile) - append-file (util/promisify fs.appendFile) - access (util/promisify fs.access) - rm (util/promisify fs.rm) - script "reloaded-script.js" - script-path (path/join (-> (first vscode/workspace.workspaceFolders) - .-uri - .-fsPath) - ".joyride" - "scripts" - script) + (p/let [script "reloaded-script.js" + script-path (path/join ws-root-path ".joyride" "scripts" script) _ (-> (access script-path fs/constants.F_OK) (p/then #(rm script-path)) (p/catch #()))] @@ -60,6 +75,12 @@ (.-forty2 result)))) (rm script-path))))) +(deftest-async run-a-ws-javascript-script-dashes + (testing "Runs a workspace script written in JavaScript, named with dash separators" + (p/let [result (vscode/commands.executeCommand "joyride.runWorkspaceScript" "a-ws-script.js")] + (is (= 42 + (.-fortytwo result)))))) + (deftest-async run-a-ws-javascript-script-underscores (testing "Runs a workspace script written in JavaScript, named with undercore separators" (p/let [result (vscode/commands.executeCommand "joyride.runWorkspaceScript" "a_ws_script.js")]