fix(web): use rustyline for prompt (#21893)

Workaround until https://github.com/kkawakam/rustyline/pull/759
This commit is contained in:
Divy Srivastava 2024-01-12 02:35:55 +05:30 committed by Bartek Iwańczuk
parent 140ef53b26
commit 87e954f54c
No known key found for this signature in database
GPG Key ID: 0C6BCDDC3B3AD750
8 changed files with 56 additions and 24 deletions

2
Cargo.lock generated
View File

@ -1655,6 +1655,7 @@ dependencies = [
"once_cell",
"regex",
"ring",
"rustyline",
"serde",
"signal-hook-registry",
"termcolor",
@ -5035,6 +5036,7 @@ dependencies = [
"cfg-if",
"clipboard-win",
"fd-lock",
"home",
"libc",
"log",
"memchr",

View File

@ -138,6 +138,7 @@ rustls = "0.21.8"
rustls-pemfile = "1.0.0"
rustls-tokio-stream = "=0.2.17"
rustls-webpki = "0.101.4"
rustyline = "=13.0.0"
webpki-roots = "0.25.2"
scopeguard = "1.2.0"
saffron = "=0.1.0"

View File

@ -117,7 +117,7 @@ quick-junit = "^0.3.5"
rand = { workspace = true, features = ["small_rng"] }
regex.workspace = true
ring.workspace = true
rustyline = { version = "=13.0.0", default-features = false, features = ["custom-bindings", "with-file-history"] }
rustyline.workspace = true
rustyline-derive = "=0.7.0"
serde.workspace = true
serde_repr.workspace = true

View File

@ -2823,12 +2823,10 @@ mod permissions {
.new_command()
.args_vec(["run", "--quiet", "--unstable", "run/066_prompt.ts"])
.with_pty(|mut console| {
console.expect("What is your name? [Jane Doe] ");
console.write_line_raw("John Doe");
console.expect("Your name is John Doe.");
console.expect("What is your name? [Jane Doe] ");
console.expect("What is your name? Jane Doe");
console.write_line_raw("");
console.expect("Your name is Jane Doe.");
console.expect("Prompt ");
console.write_line_raw("foo");
console.expect("Your input is foo.");
@ -2852,9 +2850,6 @@ mod permissions {
console.expect("Alert [Enter] ");
console.write_line("");
console.expect("The end of test");
console.expect("What is EOF? ");
console.write_line("");
console.expect("Your answer is null");
});
}

View File

@ -1,5 +1,3 @@
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
@ -17,5 +15,3 @@ console.log(`Your answer is ${JSON.stringify(windows)}`);
alert("Hi");
alert();
console.log("The end of test");
const eof = prompt("What is EOF?");
console.log(`Your answer is ${JSON.stringify(eof)}`);

View File

@ -112,6 +112,7 @@ notify.workspace = true
once_cell.workspace = true
regex.workspace = true
ring.workspace = true
rustyline = { workspace = true, features = ["custom-bindings"] }
serde.workspace = true
signal-hook-registry = "1.4.0"
termcolor = "1.1.3"

View File

@ -9,6 +9,8 @@ const {
import { isatty } from "ext:runtime/40_tty.js";
import { stdin } from "ext:deno_io/12_io.js";
const ops = core.ops;
const LF = StringPrototypeCharCodeAt("\n", 0);
const CR = StringPrototypeCharCodeAt("\r", 0);
@ -35,22 +37,16 @@ function confirm(message = "Confirm") {
}
function prompt(message = "Prompt", defaultValue) {
defaultValue ??= null;
defaultValue ??= "";
if (!isatty(stdin.rid)) {
return null;
}
if (defaultValue) {
message += ` [${defaultValue}]`;
}
message += " ";
// output in one shot to make the tests more reliable
core.print(message, false);
return readLineFromStdinSync() || defaultValue;
return ops.op_read_line_prompt(
`${message} `,
`${defaultValue}`,
);
}
function readLineFromStdinSync() {

View File

@ -5,6 +5,13 @@ use std::io::Error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use rustyline::config::Configurer;
use rustyline::error::ReadlineError;
use rustyline::Cmd;
use rustyline::Editor;
use rustyline::KeyCode;
use rustyline::KeyEvent;
use rustyline::Modifiers;
#[cfg(unix)]
use deno_core::ResourceId;
@ -43,7 +50,12 @@ use winapi::um::wincon;
deno_core::extension!(
deno_tty,
ops = [op_stdin_set_raw, op_isatty, op_console_size],
ops = [
op_stdin_set_raw,
op_isatty,
op_console_size,
op_read_line_prompt
],
state = |state| {
#[cfg(unix)]
state.put(TtyModeStore::default());
@ -320,3 +332,32 @@ mod tests {
);
}
}
#[op2]
#[string]
pub fn op_read_line_prompt(
#[string] prompt_text: &str,
#[string] default_value: &str,
) -> Result<Option<String>, AnyError> {
let mut editor = Editor::<(), rustyline::history::DefaultHistory>::new()
.expect("Failed to create editor.");
editor.set_keyseq_timeout(1);
editor
.bind_sequence(KeyEvent(KeyCode::Esc, Modifiers::empty()), Cmd::Interrupt);
let read_result =
editor.readline_with_initial(prompt_text, (default_value, ""));
match read_result {
Ok(line) => Ok(Some(line)),
Err(ReadlineError::Interrupted) => {
// SAFETY: Disable raw mode and raise SIGINT.
unsafe {
libc::raise(libc::SIGINT);
}
Ok(None)
}
Err(ReadlineError::Eof) => Ok(None),
Err(err) => Err(err.into()),
}
}