mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
fix: ESC/Ctrl-C in picker falls back to numbered list instead of cancelling (#2390)
The TTY key loop treated explicit user cancellation (ESC/Ctrl-C) the same as a TTY failure — both called fallback() which renders a numbered-list picker. Now the key loop distinguishes between the two: cancel() exits cleanly, fallback() is only used when /dev/tty is unavailable. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b8ca943592
commit
d9a25a4720
2 changed files with 10 additions and 3 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@openrouter/spawn",
|
||||
"version": "0.15.29",
|
||||
"version": "0.15.30",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"spawn": "cli.js"
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ type WriteFn = (s: string) => void;
|
|||
|
||||
interface KeyLoopCallbacks<T> {
|
||||
fallback: () => T;
|
||||
cancel: () => T;
|
||||
init: (w: WriteFn, cols: number) => void;
|
||||
handleKey: (
|
||||
key: string,
|
||||
|
|
@ -223,6 +224,7 @@ function withTTYKeyLoop<T>(callbacks: KeyLoopCallbacks<T>): T {
|
|||
// ── key loop ────────────────────────────────────────────────────────────
|
||||
const buf = Buffer.alloc(8);
|
||||
let finalResult: T | undefined;
|
||||
let cancelled = false;
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
|
|
@ -238,8 +240,9 @@ function withTTYKeyLoop<T>(callbacks: KeyLoopCallbacks<T>): T {
|
|||
|
||||
const key = buf.slice(0, n).toString("binary");
|
||||
|
||||
// Ctrl-C / Escape — universal cancel
|
||||
// Ctrl-C / Escape — explicit user cancel (not a TTY failure)
|
||||
if (key === "\x03" || key === "\x1b") {
|
||||
cancelled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +256,10 @@ function withTTYKeyLoop<T>(callbacks: KeyLoopCallbacks<T>): T {
|
|||
restore();
|
||||
}
|
||||
|
||||
return finalResult !== undefined ? finalResult : callbacks.fallback();
|
||||
if (finalResult !== undefined) {
|
||||
return finalResult;
|
||||
}
|
||||
return cancelled ? callbacks.cancel() : callbacks.fallback();
|
||||
}
|
||||
|
||||
// ── TTY picker ────────────────────────────────────────────────────────────────
|
||||
|
|
@ -316,6 +322,7 @@ export function pickToTTYWithActions(config: PickConfig): PickResult {
|
|||
|
||||
return withTTYKeyLoop<PickResult>({
|
||||
fallback,
|
||||
cancel: () => cancel,
|
||||
|
||||
init(w, cols) {
|
||||
maxW = cols - 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue