Skip to content

Commit

Permalink
fix(cli/prompt_secret): fix backspace handling
Browse files Browse the repository at this point in the history
  • Loading branch information
lambdalisue committed Nov 19, 2023
1 parent 205935c commit 91d5fd1
Showing 1 changed file with 17 additions and 8 deletions.
25 changes: 17 additions & 8 deletions cli/prompt_secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ const input = Deno.stdin;
const output = Deno.stdout;
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const LF = "\n".charCodeAt(0);
const CR = "\r".charCodeAt(0);
const LF = "\n".charCodeAt(0); // ^J - Enter on Linux
const CR = "\r".charCodeAt(0); // ^M - Enter on macOS and Windows (CRLF)
const BS = "\b".charCodeAt(0); // ^H - Backspace on Linux and Windows
const DEL = 0x7f; // ^? - Backspace on macOS
const CLR = encoder.encode("\r\u001b[K"); // Clear the current line

/**
* Shows the given message and waits for the user's input. Returns the user's input as string.
Expand All @@ -20,16 +23,18 @@ export function promptSecret(
return null;
}

const maskChar = encoder.encode(mask);
const callback = mask === "" ? undefined : () => {
output.writeSync(maskChar);
const callback = mask === "" ? undefined : (n: number) => {
// Clear the current line
output.writeSync(CLR);
output.writeSync(encoder.encode(`${message}${mask.repeat(n)}`));
};
output.writeSync(encoder.encode(message));

Deno.stdin.setRaw(true, { cbreak: true });
try {
return readLineFromStdinSync(callback);
} finally {
output.writeSync(CLR);
Deno.stdin.setRaw(false);
}
}
Expand All @@ -38,7 +43,7 @@ export function promptSecret(
// This implementation immediately break on CR or LF and accept callback.
// The original version waits LF when CR is received.
// https://github.com/denoland/deno/blob/e4593873a9c791238685dfbb45e64b4485884174/runtime/js/41_prompt.js#L52-L77
function readLineFromStdinSync(callback?: () => void): string {
function readLineFromStdinSync(callback?: (n: number) => void): string {
const c = new Uint8Array(1);
const buf = [];

Expand All @@ -50,8 +55,12 @@ function readLineFromStdinSync(callback?: () => void): string {
if (c[0] === CR || c[0] === LF) {
break;
}
buf.push(c[0]);
if (callback) callback();
if (c[0] === BS || c[0] === DEL) {
buf.pop();
} else {
buf.push(c[0]);
}
if (callback) callback(buf.length);
}
return decoder.decode(new Uint8Array(buf));
}

0 comments on commit 91d5fd1

Please sign in to comment.