Merge pull request #3272 from abmclin/windows_improve_notty_stdin_support
Windows improve notty stdin support to resolve issue 3264
This commit is contained in:
1417
Cargo.lock
generated
1417
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -68,9 +68,7 @@ use cpu_time::ProcessTime;
|
|||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
#[cfg(feature = "repl")]
|
#[cfg(feature = "repl")]
|
||||||
use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
use crate::read::user_interaction::{get_key, KeyCode, KeyModifiers};
|
||||||
#[cfg(feature = "repl")]
|
|
||||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
|
||||||
|
|
||||||
use blake2::{Blake2b512, Blake2s256};
|
use blake2::{Blake2b512, Blake2s256};
|
||||||
|
|
||||||
@@ -147,28 +145,6 @@ impl ModuleQuantification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "repl")]
|
|
||||||
pub(crate) fn get_key() -> KeyEvent {
|
|
||||||
let key;
|
|
||||||
enable_raw_mode().expect("failed to enable raw mode");
|
|
||||||
loop {
|
|
||||||
let key_ = read();
|
|
||||||
if let Ok(Event::Key(key_)) = key_ {
|
|
||||||
if key_.kind != KeyEventKind::Release {
|
|
||||||
match key_.code {
|
|
||||||
KeyCode::Char(_) | KeyCode::Enter | KeyCode::Tab => {
|
|
||||||
key = key_;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disable_raw_mode().expect("failed to disable raw mode");
|
|
||||||
key
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usize) {
|
fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usize) {
|
||||||
let char_iter = heap.char_iter(pstr_loc);
|
let char_iter = heap.char_iter(pstr_loc);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
#[cfg(feature = "repl")]
|
||||||
|
pub mod fallback_mode;
|
||||||
|
#[cfg(feature = "repl")]
|
||||||
|
pub mod user_interaction;
|
||||||
|
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::parser::lexer::Lexer;
|
use crate::parser::lexer::Lexer;
|
||||||
use crate::parser::parser::*;
|
use crate::parser::parser::*;
|
||||||
|
|||||||
46
src/read/fallback_mode.rs
Normal file
46
src/read/fallback_mode.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
|
||||||
|
use std::io::{Error, ErrorKind, Read};
|
||||||
|
|
||||||
|
// Provide graceful degradation limited support mode if reading from stdin that does not
|
||||||
|
// support terminal features.
|
||||||
|
//
|
||||||
|
// Retrieve a single byte from stdin, does not support full Unicode decoding; only convert
|
||||||
|
// byte to KeyEvent char if it falls within the ASCII subset of UTF-8.
|
||||||
|
// Does not support passing through Ctrl-C as a KeyEvent.
|
||||||
|
//
|
||||||
|
// We are not supporting multibyte UTF-8 encodings because we are only
|
||||||
|
// interested in single ASCII characters which are 1-byte UTF-8 characters.
|
||||||
|
// Multibyte non-ASCII characters would be ignored anyway, so it's not worth the effort.
|
||||||
|
//
|
||||||
|
// It is expected that `limited_support_read` will only be used when prompting for user
|
||||||
|
// input during solution enumeration and the available commands are single ASCII characters.
|
||||||
|
pub(crate) fn limited_support_read() -> std::io::Result<KeyEvent> {
|
||||||
|
#[allow(
|
||||||
|
clippy::unbuffered_bytes,
|
||||||
|
reason = "We are aware of `bytes()` performance pitfall but don't expect it to be relevant here, we are doing single byte user input I/O."
|
||||||
|
)]
|
||||||
|
let byte_or_none = std::io::stdin().bytes().next();
|
||||||
|
|
||||||
|
match byte_or_none {
|
||||||
|
Some(byte) => match byte {
|
||||||
|
Ok(b) => {
|
||||||
|
if b.is_ascii() {
|
||||||
|
Ok(map_ascii_to_keyevent(b as char))
|
||||||
|
} else {
|
||||||
|
Err(Error::new(ErrorKind::Unsupported, "not supported input"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
},
|
||||||
|
None => Err(Error::new(ErrorKind::UnexpectedEof, "EOF")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_ascii_to_keyevent(c: char) -> KeyEvent {
|
||||||
|
KeyEvent {
|
||||||
|
code: KeyCode::Char(c),
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
kind: KeyEventKind::Press,
|
||||||
|
state: KeyEventState::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/read/user_interaction.rs
Normal file
43
src/read/user_interaction.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
use crossterm::event::{read, Event, KeyEventKind};
|
||||||
|
pub(crate) use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||||
|
use crossterm::tty::IsTty;
|
||||||
|
|
||||||
|
use crate::read::fallback_mode;
|
||||||
|
|
||||||
|
pub(crate) fn get_key() -> KeyEvent {
|
||||||
|
let key;
|
||||||
|
if supported_terminal() {
|
||||||
|
enable_raw_mode().expect("failed to enable raw mode");
|
||||||
|
loop {
|
||||||
|
let key_ = read();
|
||||||
|
if let Ok(Event::Key(key_)) = key_ {
|
||||||
|
if key_.kind != KeyEventKind::Release {
|
||||||
|
match key_.code {
|
||||||
|
KeyCode::Char(_) | KeyCode::Enter | KeyCode::Tab => {
|
||||||
|
key = key_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disable_raw_mode().expect("failed to disable raw mode");
|
||||||
|
} else {
|
||||||
|
// stdin is not supported terminal type, fallback to limited support mode.
|
||||||
|
loop {
|
||||||
|
let key_ = fallback_mode::limited_support_read();
|
||||||
|
if let Ok(key_) = key_ {
|
||||||
|
key = key_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_terminal() -> bool {
|
||||||
|
// If OS is Windows and stdin is not a tty, it's either a pipe or an unsupported terminal configuration.
|
||||||
|
cfg!(not(windows)) || std::io::stdin().is_tty()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user