118 lines
3.2 KiB
JavaScript
118 lines
3.2 KiB
JavaScript
// In contrast to `node run <file>`, this opens a shell-like
|
|
// environment that allows faster execution of code since it
|
|
// doesn't have to reload the plugin system. This is mostly
|
|
// done since Clover's primary dev-env is a Windows 7 laptop;
|
|
// It takes her machine 600ms to load the plugin file on it's own.
|
|
import process from "node:process";
|
|
import * as util from "node:util";
|
|
const exts = [".tsx", ".ts", ".js", ".marko"];
|
|
|
|
process.stderr.write("Loading...");
|
|
const { hot } = await import("./run.js"); // get plugins ready
|
|
const { errorAllWidgets } = hot.load("@paperclover/console/Widget");
|
|
process.stderr.write("\r" + " ".repeat("Loading...".length) + "\r");
|
|
const repl = hot.load("node:repl").start({
|
|
prompt: "% ",
|
|
eval(code, _global, _id, done) {
|
|
evaluate(code)
|
|
.catch((err) => {
|
|
// TODO: improve @paperclover/console's ability to print AggregateError
|
|
// and errors with extra random properties
|
|
console.error(util.inspect(err));
|
|
})
|
|
.then((result) => done(null, result));
|
|
},
|
|
ignoreUndefined: true,
|
|
//completer,
|
|
});
|
|
repl.setupHistory(".clover/repl-history.txt", () => {});
|
|
|
|
setTimeout(() => {
|
|
hot.reloadRecursive("./framework/generate.ts");
|
|
}, 100);
|
|
|
|
async function evaluate(code) {
|
|
code = code.trim();
|
|
|
|
if (code === "clear" || code === "cls") {
|
|
return console.clear();
|
|
}
|
|
|
|
if (code[0] === "=") {
|
|
try {
|
|
const result = await eval(code[1]);
|
|
console.info(inspect(result));
|
|
} catch (err) {
|
|
if (err instanceof SyntaxError) {
|
|
const result = await eval("(async() => { return " + code + " })()");
|
|
console.info(inspect(result));
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
let split = code.split(/\s+/);
|
|
if (split.length === 0) return;
|
|
|
|
// Shell commands
|
|
const cliPassthrough = [
|
|
"deno",
|
|
"explorer",
|
|
"git",
|
|
"iexplore",
|
|
"node",
|
|
"npm",
|
|
"open",
|
|
"rg",
|
|
"start",
|
|
"vi",
|
|
];
|
|
if (cliPassthrough.includes(split[0]) || split[0].startsWith("$")) {
|
|
if (split[0].startsWith("$")) {
|
|
if ((split[0] = split[0].slice(1)).trim() === "") split.shift();
|
|
}
|
|
if (process.platform === "win32" && split[0] === "open") split[0] = "start";
|
|
if (split[0] === "explorer" || split[0] === "start") {
|
|
split[1] = split[1]?.replaceAll("/", "\\");
|
|
}
|
|
try {
|
|
child_process.execSync(split.join(" "), {
|
|
stdio: "inherit",
|
|
env: { EDITOR: "vi", ...process.env },
|
|
});
|
|
} catch (err) {
|
|
const { status, signalCode } = err;
|
|
console.error(
|
|
`Exited with ${status ? "code " + status : "signal " + signalCode}`,
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
let found;
|
|
for (const base of [".", "framework"]) {
|
|
for (const e of exts) {
|
|
const file = path.join(base, split[0] + e);
|
|
if (fs.existsSync(file)) {
|
|
found = file;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
console.error("\x1b[33mNo file matches: " + split[0] + "\x1b[0m");
|
|
return;
|
|
}
|
|
|
|
const m = hot.reloadRecursive(found);
|
|
await m.main?.();
|
|
errorAllWidgets(
|
|
path.basename(found, path.extname(found)) + ".main() returning",
|
|
);
|
|
}
|
|
|
|
import * as fs from "node:fs";
|
|
import * as path from "node:path";
|
|
import * as child_process from "node:child_process";
|