fix(tui): make Esc clear line and cancel hidden prompts in minimal mode
This commit is contained in:
@@ -163,8 +163,18 @@ export class MinimalTui {
|
|||||||
|
|
||||||
// Listen for line changes to show hints
|
// Listen for line changes to show hints
|
||||||
this.keypressHandler = (char: string, key: readline.Key) => {
|
this.keypressHandler = (char: string, key: readline.Key) => {
|
||||||
if (this.activePromptCancel && this.isEscapeKey(char, key)) {
|
if (this.isEscapeKey(char, key)) {
|
||||||
this.activePromptCancel();
|
if (this.activePromptCancel) {
|
||||||
|
this.activePromptCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.rl) {
|
||||||
|
try {
|
||||||
|
this.rl.write(null, { ctrl: true, name: 'u' });
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,6 +530,30 @@ export class MinimalTui {
|
|||||||
stdoutMuted?: boolean;
|
stdoutMuted?: boolean;
|
||||||
_writeToOutput?: (s: string) => void;
|
_writeToOutput?: (s: string) => void;
|
||||||
};
|
};
|
||||||
|
const stdin = process.stdin as NodeJS.ReadStream & {
|
||||||
|
isRaw?: boolean;
|
||||||
|
setRawMode?: (mode: boolean) => void;
|
||||||
|
};
|
||||||
|
const wasRaw = Boolean(stdin.isRaw);
|
||||||
|
let enabledRawForPrompt = false;
|
||||||
|
let dataListener: ((chunk: Buffer) => void) | null = null;
|
||||||
|
let settled = false;
|
||||||
|
|
||||||
|
if (stdin.isTTY && stdin.setRawMode && !wasRaw) {
|
||||||
|
stdin.setRawMode(true);
|
||||||
|
enabledRawForPrompt = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
if (dataListener) {
|
||||||
|
stdin.removeListener('data', dataListener);
|
||||||
|
dataListener = null;
|
||||||
|
}
|
||||||
|
if (enabledRawForPrompt && stdin.setRawMode) {
|
||||||
|
stdin.setRawMode(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
rlAny.stdoutMuted = true;
|
rlAny.stdoutMuted = true;
|
||||||
rlAny._writeToOutput = (s: string) => {
|
rlAny._writeToOutput = (s: string) => {
|
||||||
if (!rlAny.stdoutMuted) {
|
if (!rlAny.stdoutMuted) {
|
||||||
@@ -532,8 +566,40 @@ export class MinimalTui {
|
|||||||
process.stdout.write('*');
|
process.stdout.write('*');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
|
const answer = await new Promise<string>((resolve) => {
|
||||||
|
dataListener = (chunk: Buffer) => {
|
||||||
|
if (settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (chunk.length === 1 && chunk[0] === 0x1b) {
|
||||||
|
settled = true;
|
||||||
|
rl.close();
|
||||||
|
resolve('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stdin.on('data', dataListener);
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
if (settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settled = true;
|
||||||
|
resolve('');
|
||||||
|
};
|
||||||
|
if (typeof rl.once === 'function') {
|
||||||
|
rl.once('close', onClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.question(question, (value) => {
|
||||||
|
if (settled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settled = true;
|
||||||
|
resolve(value);
|
||||||
|
});
|
||||||
|
});
|
||||||
rlAny.stdoutMuted = false;
|
rlAny.stdoutMuted = false;
|
||||||
|
cleanup();
|
||||||
rl.close();
|
rl.close();
|
||||||
process.stdout.write('\n');
|
process.stdout.write('\n');
|
||||||
return answer.trim();
|
return answer.trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user