nrepl: add command to send current form to jacked in REPL (#358)

This commit is contained in:
Tyler Wilding 2024-06-01 13:00:27 -04:00 committed by GitHub
parent aaa3a4dbed
commit 49cd23a525
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 1009 additions and 15 deletions

26
copy-static-assets.js Normal file
View file

@ -0,0 +1,26 @@
const fs = require("fs");
const path = require("path");
// Function to copy a file
function copyFile(source, targetDir) {
// Create the target directory if it doesn't exist
fs.mkdir(targetDir, { recursive: true }, (err) => {
if (err) {
return console.error(`Failed to create directory: ${err.message}`);
}
// Define the target file path
const targetFile = path.join(targetDir, path.basename(source));
// Copy the file
fs.copyFile(source, targetFile, (err) => {
if (err) {
return console.error(`Failed to copy file: ${err.message}`);
}
console.log(`File copied to ${targetFile}`);
});
});
}
copyFile("./tree-sitter-opengoal.wasm", "./dist/");
copyFile("./node_modules/web-tree-sitter/tree-sitter.wasm", "./dist/");

View file

@ -21,11 +21,13 @@
"format": "npx prettier --write .",
"format:check": "npx prettier --check .",
"postinstall": "patch-package",
"vscode:prepublish": "esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --minify",
"esbuild": "esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --sourcemap",
"dev": "esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --sourcemap --watch"
"wasm-update": "node ./copy-static-assets.js",
"vscode:prepublish": "npm run wasm-update && esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --minify",
"esbuild": "npm run wasm-update && esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --sourcemap",
"dev": "npm run wasm-update && esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node --sourcemap --watch"
},
"devDependencies": {
"@electron/rebuild": "^3.6.0",
"@types/follow-redirects": "^1.14.4",
"@types/glob": "^8.1.0",
"@types/node": "^20.12.12",
@ -36,6 +38,7 @@
"esbuild": "^0.21.4",
"patch-package": "^8.0.0",
"prettier": "3.2.5",
"tree-sitter-cli": "^0.22.6",
"typescript": "^5.4.5"
},
"dependencies": {
@ -44,7 +47,9 @@
"follow-redirects": "^1.15.6",
"parinfer": "^3.13.1",
"promise-socket": "^7.0.0",
"vscode-languageclient": "^9.0.1"
"tree-sitter-opengoal": "^1.0.1",
"vscode-languageclient": "^9.0.1",
"web-tree-sitter": "^0.22.6"
},
"activationEvents": [],
"contributes": {
@ -180,6 +185,10 @@
{
"command": "opengoal.nrepl.unjack",
"title": "OpenGOAL - nREPL - Un-jack"
},
{
"command": "opengoal.nrepl.evalCurrentForm",
"title": "OpenGOAL - nREPL - Eval Current Form"
}
],
"configuration": [

View file

@ -4,6 +4,7 @@ import PromiseSocket from "promise-socket";
import * as vscode from "vscode";
import { getConfig } from "../../../config/config";
import { updateStatusBar } from "../../../context";
import Parser from "web-tree-sitter";
let jackedIn = false;
let socket: PromiseSocket<Socket> | undefined = undefined;
@ -82,10 +83,68 @@ export async function reloadFile(fileName: string) {
}
}
export async function evalCurrentForm() {
if (getConfig().autoReplJackIn && socket === undefined) {
await jackIn();
}
if (!jackedIn || socket === undefined) {
return;
}
try {
// Find the current form
const currDocument = vscode.window.activeTextEditor?.document;
const currPosition = vscode.window.activeTextEditor?.selection.start;
const documentText = currDocument?.getText();
if (documentText === undefined || currPosition === undefined) {
return;
}
// Parse the document
await Parser.init();
const opengoalParser = new Parser();
const opengoalLang = await Parser.Language.load(
path.join(__dirname, "tree-sitter-opengoal.wasm"),
);
opengoalParser.setLanguage(opengoalLang);
const tree = opengoalParser.parse(documentText);
let foundNode = tree.rootNode.descendantForPosition({
row: currPosition.line,
column: currPosition.character,
});
// Walk back up the tree until we find a `list_lit` node, this is a bit limiting in some ways but is good enough for now
// this prevents you from sending symbol names to the repl
while (foundNode.type !== "list_lit" && foundNode.parent) {
foundNode = foundNode.parent;
}
const form = foundNode.text;
// Define your data
const headerLength = 8;
// Create a buffer
const headerBuffer = Buffer.alloc(headerLength);
// Pack the data into the buffer
headerBuffer.writeUInt32LE(Buffer.byteLength(form), 0);
headerBuffer.writeUInt32LE(10, 4);
const formBuffer = Buffer.from(form, "utf8");
await socket.writeAll(Buffer.concat([headerBuffer, formBuffer]));
} catch (e) {
console.error(e);
}
}
export function registerNReplCommands(context: vscode.ExtensionContext): void {
context.subscriptions.push(
vscode.commands.registerCommand("opengoal.nrepl.jackin", jackIn),
vscode.commands.registerCommand("opengoal.nrepl.unjack", unJack),
vscode.commands.registerCommand(
"opengoal.nrepl.evalCurrentForm",
evalCurrentForm,
),
);
}

BIN
tree-sitter-opengoal.wasm Normal file

Binary file not shown.

922
yarn.lock

File diff suppressed because it is too large Load diff