@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed Windows external editor handoff so vim/nvim can receive input after opening from the TUI ([#4612](https://github.com/earendil-works/pi/issues/4612)).
|
||||||
- Fixed Windows npm self-updates to move loaded native dependency packages out of the active install before reinstalling pi ([#4157](https://github.com/earendil-works/pi/issues/4157)).
|
- Fixed Windows npm self-updates to move loaded native dependency packages out of the active install before reinstalling pi ([#4157](https://github.com/earendil-works/pi/issues/4157)).
|
||||||
- Fixed `pi update --self` detection for pnpm v11 global installs whose package path resolves through the pnpm store ([#4647](https://github.com/earendil-works/pi/issues/4647)).
|
- Fixed `pi update --self` detection for pnpm v11 global installs whose package path resolves through the pnpm store ([#4647](https://github.com/earendil-works/pi/issues/4647)).
|
||||||
- Fixed Windows pnpm self-updates to resolve pnpm command shims and run through pnpm instead of requiring manual updates ([#4157](https://github.com/earendil-works/pi/issues/4157)).
|
- Fixed Windows pnpm self-updates to resolve pnpm command shims and run through pnpm instead of requiring manual updates ([#4157](https://github.com/earendil-works/pi/issues/4157)).
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Supports Ctrl+G for external editor.
|
* Supports Ctrl+G for external editor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { spawnSync } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
import * as fs from "node:fs";
|
import * as fs from "node:fs";
|
||||||
import * as os from "node:os";
|
import * as os from "node:os";
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
@@ -110,7 +110,7 @@ export class ExtensionEditorComponent extends Container implements Focusable {
|
|||||||
this.editor.handleInput(keyData);
|
this.editor.handleInput(keyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private openExternalEditor(): void {
|
private async openExternalEditor(): Promise<void> {
|
||||||
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
||||||
if (!editorCmd) {
|
if (!editorCmd) {
|
||||||
return;
|
return;
|
||||||
@@ -124,12 +124,21 @@ export class ExtensionEditorComponent extends Container implements Focusable {
|
|||||||
this.tui.stop();
|
this.tui.stop();
|
||||||
|
|
||||||
const [editor, ...editorArgs] = editorCmd.split(" ");
|
const [editor, ...editorArgs] = editorCmd.split(" ");
|
||||||
const result = spawnSync(editor, [...editorArgs, tmpFile], {
|
process.stdout.write(`Launching external editor: ${editorCmd}\nPi will resume when the editor exits.\n`);
|
||||||
stdio: "inherit",
|
|
||||||
shell: process.platform === "win32",
|
// Do not use spawnSync here. On Windows, synchronous child_process calls can keep
|
||||||
|
// Node/libuv's console input read active after tui.stop() pauses stdin, racing
|
||||||
|
// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.
|
||||||
|
const status = await new Promise<number | null>((resolve) => {
|
||||||
|
const child = spawn(editor, [...editorArgs, tmpFile], {
|
||||||
|
stdio: "inherit",
|
||||||
|
shell: process.platform === "win32",
|
||||||
|
});
|
||||||
|
child.on("error", () => resolve(null));
|
||||||
|
child.on("close", (code) => resolve(code));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.status === 0) {
|
if (status === 0) {
|
||||||
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
||||||
this.editor.setText(newContent);
|
this.editor.setText(newContent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3497,7 +3497,7 @@ export class InteractiveMode {
|
|||||||
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private openExternalEditor(): void {
|
private async openExternalEditor(): Promise<void> {
|
||||||
// Determine editor (respect $VISUAL, then $EDITOR)
|
// Determine editor (respect $VISUAL, then $EDITOR)
|
||||||
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
const editorCmd = process.env.VISUAL || process.env.EDITOR;
|
||||||
if (!editorCmd) {
|
if (!editorCmd) {
|
||||||
@@ -3518,14 +3518,22 @@ export class InteractiveMode {
|
|||||||
// Split by space to support editor arguments (e.g., "code --wait")
|
// Split by space to support editor arguments (e.g., "code --wait")
|
||||||
const [editor, ...editorArgs] = editorCmd.split(" ");
|
const [editor, ...editorArgs] = editorCmd.split(" ");
|
||||||
|
|
||||||
// Spawn editor synchronously with inherited stdio for interactive editing
|
process.stdout.write(`Launching external editor: ${editorCmd}\nPi will resume when the editor exits.\n`);
|
||||||
const result = spawnSync(editor, [...editorArgs, tmpFile], {
|
|
||||||
stdio: "inherit",
|
// Do not use spawnSync here. On Windows, synchronous child_process calls can keep
|
||||||
shell: process.platform === "win32",
|
// Node/libuv's console input read active after ui.stop() pauses stdin, racing
|
||||||
|
// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.
|
||||||
|
const status = await new Promise<number | null>((resolve) => {
|
||||||
|
const child = spawn(editor, [...editorArgs, tmpFile], {
|
||||||
|
stdio: "inherit",
|
||||||
|
shell: process.platform === "win32",
|
||||||
|
});
|
||||||
|
child.on("error", () => resolve(null));
|
||||||
|
child.on("close", (code) => resolve(code));
|
||||||
});
|
});
|
||||||
|
|
||||||
// On successful exit (status 0), replace editor content
|
// On successful exit (status 0), replace editor content
|
||||||
if (result.status === 0) {
|
if (status === 0) {
|
||||||
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
const newContent = fs.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
|
||||||
this.editor.setText(newContent);
|
this.editor.setText(newContent);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user