Something went wrong. Try again.
fork of prime agent with changes i want but are not upstreamable probqbly (and some fixes)
Something went wrong. Try again.
3.4 kB · 133 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134import { spawnSync } from "node:child_process";import * as fs from "node:fs";import * as os from "node:os";import * as path from "node:path";import { Container, Editor, type EditorOptions, type Focusable, getKeybindings, Spacer, Text, type TUI,} from "@earendil-works/pi-tui";import type { KeybindingsManager } from "../../../core/keybindings.js";import { getEditorTheme, theme } from "../theme/theme.js";import { DynamicBorder } from "./dynamic-border.js";import { keyHint } from "./keybinding-hints.js";
export class ExtensionEditorComponent extends Container implements Focusable { private editor: Editor; private onSubmitCallback: (value: string) => void; private onCancelCallback: () => void; private tui: TUI; private keybindings: KeybindingsManager;
private _focused = false; get focused(): boolean { return this._focused; } set focused(value: boolean) { this._focused = value; this.editor.focused = value; }
constructor( tui: TUI, keybindings: KeybindingsManager, title: string, prefill: string | undefined, onSubmit: (value: string) => void, onCancel: () => void, options?: EditorOptions, ) { super();
this.tui = tui; this.keybindings = keybindings; this.onSubmitCallback = onSubmit; this.onCancelCallback = onCancel;
this.addChild(new DynamicBorder()); this.addChild(new Spacer(1));
this.addChild(new Text(theme.fg("accent", title), 1, 0)); this.addChild(new Spacer(1));
this.editor = new Editor(tui, getEditorTheme(), options); if (prefill) { this.editor.setText(prefill); } this.editor.onSubmit = (text: string) => { this.onSubmitCallback(text); }; this.addChild(this.editor);
this.addChild(new Spacer(1));
const hasExternalEditor = !!(process.env.VISUAL || process.env.EDITOR); const hint = keyHint("tui.select.confirm", "submit") + " " + keyHint("tui.input.newLine", "newline") + " " + keyHint("tui.select.cancel", "cancel") + (hasExternalEditor ? ` ${keyHint("app.editor.external", "external editor")}` : ""); this.addChild(new Text(hint, 1, 0));
this.addChild(new Spacer(1));
this.addChild(new DynamicBorder()); }
handleInput(keyData: string): void { const kb = getKeybindings(); if (kb.matches(keyData, "tui.select.cancel")) { this.onCancelCallback(); return; }
if (this.keybindings.matches(keyData, "app.editor.external")) { this.openExternalEditor(); return; }
this.editor.handleInput(keyData); }
private openExternalEditor(): void { const editorCmd = process.env.VISUAL || process.env.EDITOR; if (!editorCmd) { return; }
const currentText = this.editor.getText(); const tmpFile = path.join(os.tmpdir(), `pi-extension-editor-${Date.now()}.md`);
try { fs.writeFileSync(tmpFile, currentText, "utf-8"); this.tui.stop();
const [editor, ...editorArgs] = editorCmd.split(" "); const result = spawnSync(editor, [...editorArgs, tmpFile], { stdio: "inherit", shell: process.platform === "win32", });
if (result.status === 0) { const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, ""); this.editor.setText(newContent); } } finally { try { fs.unlinkSync(tmpFile); } catch { // Ignore cleanup errors } this.tui.start(); // Force full re-render since external editor uses alternate screen this.tui.requestRender(true); } }}