37 lines
1.6 KiB
JavaScript
37 lines
1.6 KiB
JavaScript
import { spawn } from "node:child_process";
|
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
export async function editInExternalEditor(options) {
|
|
const directory = mkdtempSync(join(tmpdir(), "pi-editor-"));
|
|
const filePath = join(directory, "prompt.md");
|
|
try {
|
|
writeFileSync(filePath, options.content, "utf-8");
|
|
const [editor, ...editorArgs] = options.command.split(" ");
|
|
process.stdout.write(`Launching external editor: ${options.command}\nPi will resume when the editor exits.\n`);
|
|
// Do not use spawnSync here. On Windows, synchronous child_process calls can keep
|
|
// Node/libuv's console input read active after the parent pauses stdin, racing
|
|
// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.
|
|
const exitCode = await new Promise((resolve) => {
|
|
const child = spawn(editor, [...editorArgs, filePath], {
|
|
stdio: "inherit",
|
|
shell: process.platform === "win32",
|
|
});
|
|
child.on("error", () => resolve(null));
|
|
child.on("close", (code) => resolve(code));
|
|
});
|
|
if (exitCode !== 0) {
|
|
return { status: "failed" };
|
|
}
|
|
return { status: "complete", content: readFileSync(filePath, "utf-8").replace(/\n$/, "") };
|
|
}
|
|
finally {
|
|
try {
|
|
rmSync(directory, { recursive: true, force: true });
|
|
}
|
|
catch {
|
|
// Cleanup is best effort.
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=external-editor.js.map
|