Skip to content

Commit

Permalink
fix(web): use rustyline for prompt (#21893)
Browse files Browse the repository at this point in the history
Workaround until kkawakam/rustyline#759
  • Loading branch information
littledivy authored Jan 11, 2024
1 parent d8f86c8 commit 9268df5
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 24 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 2 additions & 7 deletions cli/tests/integration/run_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand All @@ -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");
});
}

Expand Down
4 changes: 0 additions & 4 deletions cli/tests/testdata/run/066_prompt.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)}`);
1 change: 1 addition & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
18 changes: 7 additions & 11 deletions runtime/js/41_prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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() {
Expand Down
43 changes: 42 additions & 1 deletion runtime/ops/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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()),
}
}

0 comments on commit 9268df5

Please sign in to comment.