Skip to content

Commit

Permalink
feat: add alert, confirm, and prompt (#7507)
Browse files Browse the repository at this point in the history
This commit adds "alert", "confirm" and "prompt" functions from web standards.
  • Loading branch information
kt3k authored Oct 13, 2020
1 parent 0bd3cea commit 0dcaea7
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
29 changes: 29 additions & 0 deletions cli/dts/lib.deno.window.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ declare class Window extends EventTarget {
onunload: ((this: Window, ev: Event) => any) | null;
close: () => void;
readonly closed: boolean;
alert: (message?: string) => void;
confirm: (message?: string) => boolean;
prompt: (message?: string, defaultValue?: string) => string | null;
Deno: typeof Deno;
}

Expand All @@ -23,4 +26,30 @@ declare var self: Window & typeof globalThis;
declare var onload: ((this: Window, ev: Event) => any) | null;
declare var onunload: ((this: Window, ev: Event) => any) | null;

/**
* Shows the given message and waits for the enter key pressed.
* If the stdin is not interactive, it does nothing.
* @param message
*/
declare function alert(message?: string): void;

/**
* Shows the given message and waits for the answer. Returns the user's answer as boolean.
* Only `y` and `Y` are considered as true.
* If the stdin is not interactive, it returns false.
* @param message
*/
declare function confirm(message?: string): boolean;

/**
* Shows the given message and waits for the user's input. Returns the user's input as string.
* If the default value is given and the user inputs the empty string, then it returns the given
* default value.
* If the default value is not given and the user inputs the empty string, it returns null.
* If the stdin is not interactive, it returns null.
* @param message
* @param defaultValue
*/
declare function prompt(message?: string, defaultValue?: string): string | null;

/* eslint-enable @typescript-eslint/no-explicit-any */
66 changes: 66 additions & 0 deletions cli/rt/41_prompt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
((window) => {
const { stdin, stdout } = window.__bootstrap.files;
const { isatty } = window.__bootstrap.tty;
const LF = "\n".charCodeAt(0);
const encoder = new TextEncoder();
const decoder = new TextDecoder();

function alert(message = "Alert") {
if (!isatty(stdin.rid)) {
return;
}

stdout.writeSync(encoder.encode(`${message} [Enter] `));

readLineFromStdinSync();
}

function confirm(message = "Confirm") {
if (!isatty(stdin.rid)) {
return false;
}

stdout.writeSync(encoder.encode(`${message} [y/N] `));

const answer = readLineFromStdinSync();

return answer === "Y" || answer === "y";
}

function prompt(message = "Prompt", defaultValue) {
defaultValue ??= null;

if (!isatty(stdin.rid)) {
return null;
}

stdout.writeSync(encoder.encode(`${message} `));

if (defaultValue) {
stdout.writeSync(encoder.encode(`[${defaultValue}] `));
}

return readLineFromStdinSync() || defaultValue;
}

function readLineFromStdinSync() {
const c = new Uint8Array(1);
const buf = [];

while (true) {
const n = stdin.readSync(c);
if (n === 0 || c[0] === LF) {
break;
}
buf.push(c[0]);
}
return decoder.decode(new Uint8Array(buf));
}

window.__bootstrap.prompt = {
alert,
confirm,
prompt,
};
})(this);
4 changes: 4 additions & 0 deletions cli/rt/99_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ delete Object.prototype.__proto__;
const fileReader = window.__bootstrap.fileReader;
const webSocket = window.__bootstrap.webSocket;
const fetch = window.__bootstrap.fetch;
const prompt = window.__bootstrap.prompt;
const denoNs = window.__bootstrap.denoNs;
const denoNsUnstable = window.__bootstrap.denoNsUnstable;
const errors = window.__bootstrap.errors.errors;
Expand Down Expand Up @@ -285,6 +286,9 @@ delete Object.prototype.__proto__;
onunload: util.writable(null),
close: util.writable(windowClose),
closed: util.getterOnly(() => windowIsClosing),
alert: util.writable(prompt.alert),
confirm: util.writable(prompt.confirm),
prompt: util.writable(prompt.prompt),
};

const workerRuntimeGlobalProperties = {
Expand Down
17 changes: 17 additions & 0 deletions cli/tests/066_prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const name0 = prompt("What is your name?", "Jane Doe"); // Answer John Doe
console.log(`Your name is ${name0}.`);
const name1 = prompt("What is your name?", "Jane Doe"); // Answer with default
console.log(`Your name is ${name1}.`);
const input = prompt(); // Answer foo
console.log(`Your input is ${input}.`);
const answer0 = confirm("Question 0"); // Answer y
console.log(`Your answer is ${answer0}`);
const answer1 = confirm("Question 1"); // Answer n
console.log(`Your answer is ${answer1}`);
const answer2 = confirm("Question 2"); // Answer with yes (returns false)
console.log(`Your answer is ${answer2}`);
const answer3 = confirm(); // Answer with default
console.log(`Your answer is ${answer3}`);
alert("Hi");
alert();
console.log("The end of test");
8 changes: 8 additions & 0 deletions cli/tests/066_prompt.ts.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[WILDCARD]What is your name? [Jane Doe] Your name is John Doe.
What is your name? [Jane Doe] Your name is Jane Doe.
Prompt Your input is foo.
Question 0 [y/N] Your answer is true
Question 1 [y/N] Your answer is false
Question 2 [y/N] Your answer is false
Confirm [y/N] Your answer is false
Hi [Enter] Alert [Enter] The end of test
11 changes: 11 additions & 0 deletions cli/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1917,6 +1917,17 @@ itest!(_065_import_map_info {
output: "065_import_map_info.out",
});

#[cfg(unix)]
#[test]
fn _066_prompt() {
let args = "run --unstable 066_prompt.ts";
let output = "066_prompt.ts.out";
// These are answers to prompt, confirm, and alert calls.
let input = b"John Doe\n\nfoo\nY\nN\nyes\n\n\n\n";

util::test_pty(args, output, input);
}

itest!(js_import_detect {
args: "run --quiet --reload js_import_detect.ts",
output: "js_import_detect.ts.out",
Expand Down

0 comments on commit 0dcaea7

Please sign in to comment.