sitegen/repl.js

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");
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,
});
setTimeout(() => {
hot.reloadRecursive("./framework/engine/ssr.ts");
hot.reloadRecursive("./framework/bundle.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.log(inspect(result));
} catch (err) {
if (err instanceof SyntaxError) {
const result = await eval("(async() => { return " + code + " })()");
console.log(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";