diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2024-01-12 02:35:55 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-11 22:05:55 +0100 |
commit | 9268df5f3405103214b4e39d82e5ab1b465475a0 (patch) | |
tree | 76336155130a2e751a9509df370d0060020473ac | |
parent | d8f86c8b9cf327db4d246c20cf60467cafe2ba64 (diff) |
fix(web): use rustyline for prompt (#21893)
Workaround until https://github.com/kkawakam/rustyline/pull/759
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | cli/Cargo.toml | 2 | ||||
-rw-r--r-- | cli/tests/integration/run_tests.rs | 9 | ||||
-rw-r--r-- | cli/tests/testdata/run/066_prompt.ts | 4 | ||||
-rw-r--r-- | runtime/Cargo.toml | 1 | ||||
-rw-r--r-- | runtime/js/41_prompt.js | 18 | ||||
-rw-r--r-- | runtime/ops/tty.rs | 43 |
8 files changed, 56 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock index c6490b776..dd8cdf338 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index 9d4af489d..7372f4046 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 0e887abc6..8c6932e4a 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -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 diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 36eee1100..2a349a5f2 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -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"); }); } diff --git a/cli/tests/testdata/run/066_prompt.ts b/cli/tests/testdata/run/066_prompt.ts index e3daa7ac0..f059be685 100644 --- a/cli/tests/testdata/run/066_prompt.ts +++ b/cli/tests/testdata/run/066_prompt.ts @@ -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)}`); diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 223c42ffb..52149357f 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -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" diff --git a/runtime/js/41_prompt.js b/runtime/js/41_prompt.js index 4e2f0fffc..e9f10e244 100644 --- a/runtime/js/41_prompt.js +++ b/runtime/js/41_prompt.js @@ -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() { diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs index 3227ee562..6cc129883 100644 --- a/runtime/ops/tty.rs +++ b/runtime/ops/tty.rs @@ -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()), + } +} |