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
|
||||
this.keypressHandler = (char: string, key: readline.Key) => {
|
||||
if (this.activePromptCancel && this.isEscapeKey(char, key)) {
|
||||
this.activePromptCancel();
|
||||
if (this.isEscapeKey(char, key)) {
|
||||
if (this.activePromptCancel) {
|
||||
this.activePromptCancel();
|
||||
return;
|
||||
}
|
||||
if (this.rl) {
|
||||
try {
|
||||
this.rl.write(null, { ctrl: true, name: 'u' });
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -520,6 +530,30 @@ export class MinimalTui {
|
||||
stdoutMuted?: boolean;
|
||||
_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._writeToOutput = (s: string) => {
|
||||
if (!rlAny.stdoutMuted) {
|
||||
@@ -532,8 +566,40 @@ export class MinimalTui {
|
||||
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;
|
||||
cleanup();
|
||||
rl.close();
|
||||
process.stdout.write('\n');
|
||||
return answer.trim();
|
||||
|
||||
Reference in New Issue
Block a user