summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-01-12 02:35:55 +0530
committerGitHub <noreply@github.com>2024-01-11 22:05:55 +0100
commit9268df5f3405103214b4e39d82e5ab1b465475a0 (patch)
tree76336155130a2e751a9509df370d0060020473ac
parentd8f86c8b9cf327db4d246c20cf60467cafe2ba64 (diff)
fix(web): use rustyline for prompt (#21893)
Workaround until https://github.com/kkawakam/rustyline/pull/759
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml1
-rw-r--r--cli/Cargo.toml2
-rw-r--r--cli/tests/integration/run_tests.rs9
-rw-r--r--cli/tests/testdata/run/066_prompt.ts4
-rw-r--r--runtime/Cargo.toml1
-rw-r--r--runtime/js/41_prompt.js18
-rw-r--r--runtime/ops/tty.rs43
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()),
+ }
+}