Fix bug on multiple simultaneous input + tests
This commit is contained in:
parent
494f89daef
commit
0c8c6d4f0c
@ -418,82 +418,3 @@ impl_display!(for Show);
|
|||||||
impl_display!(for EnableBlinking);
|
impl_display!(for EnableBlinking);
|
||||||
impl_display!(for DisableBlinking);
|
impl_display!(for DisableBlinking);
|
||||||
impl_display!(for SetCursorStyle);
|
impl_display!(for SetCursorStyle);
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
#[cfg(feature = "events")]
|
|
||||||
mod tests {
|
|
||||||
use std::io::{self, stdout};
|
|
||||||
|
|
||||||
use crate::execute;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
sys::position, MoveDown, MoveLeft, MoveRight, MoveTo, MoveUp, RestorePosition, SavePosition,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_move_to() {
|
|
||||||
let (saved_x, saved_y) = position().unwrap();
|
|
||||||
|
|
||||||
execute!(stdout(), MoveTo(saved_x + 1, saved_y + 1)).unwrap();
|
|
||||||
assert_eq!(position().unwrap(), (saved_x + 1, saved_y + 1));
|
|
||||||
|
|
||||||
execute!(stdout(), MoveTo(saved_x, saved_y)).unwrap();
|
|
||||||
assert_eq!(position().unwrap(), (saved_x, saved_y));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_move_right() {
|
|
||||||
let (saved_x, saved_y) = position().unwrap();
|
|
||||||
execute!(io::stdout(), MoveRight(1)).unwrap();
|
|
||||||
assert_eq!(position().unwrap(), (saved_x + 1, saved_y));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_move_left() {
|
|
||||||
execute!(stdout(), MoveTo(2, 0), MoveLeft(2)).unwrap();
|
|
||||||
assert_eq!(position().unwrap(), (0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_move_up() {
|
|
||||||
execute!(stdout(), MoveTo(0, 2), MoveUp(2)).unwrap();
|
|
||||||
assert_eq!(position().unwrap(), (0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_move_down() {
|
|
||||||
execute!(stdout(), MoveTo(0, 0), MoveDown(2)).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(position().unwrap(), (0, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_save_restore_position() {
|
|
||||||
let (saved_x, saved_y) = position().unwrap();
|
|
||||||
|
|
||||||
execute!(
|
|
||||||
stdout(),
|
|
||||||
SavePosition,
|
|
||||||
MoveTo(saved_x + 1, saved_y + 1),
|
|
||||||
RestorePosition
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (x, y) = position().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(x, saved_x);
|
|
||||||
assert_eq!(y, saved_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
110
src/event.rs
110
src/event.rs
@ -928,6 +928,41 @@ impl Display for KeyCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TerminalState {
|
||||||
|
char_buffer: VecDeque<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerminalState {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
char_buffer: VecDeque::<u8>::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn events_for_input(&mut self, input: &[u8]) -> std::io::Result<Vec<Event>> {
|
||||||
|
let mut result: Vec<Event> = Vec::new();
|
||||||
|
|
||||||
|
self.char_buffer.extend(input);
|
||||||
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match self.char_buffer.pop_front() {
|
||||||
|
None => return Ok(result),
|
||||||
|
Some(c) => {
|
||||||
|
buf.push(c);
|
||||||
|
match parse_event(&buf, true)? {
|
||||||
|
None => continue,
|
||||||
|
Some(e) => {
|
||||||
|
result.push(e);
|
||||||
|
buf.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
@ -1035,36 +1070,51 @@ mod tests {
|
|||||||
assert_eq!(format!("{}", Modifier(RightAlt)), "Right Alt");
|
assert_eq!(format!("{}", Modifier(RightAlt)), "Right Alt");
|
||||||
assert_eq!(format!("{}", Modifier(RightSuper)), "Right Super");
|
assert_eq!(format!("{}", Modifier(RightSuper)), "Right Super");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TerminalState {
|
#[test]
|
||||||
char_buffer: VecDeque<u8>,
|
pub fn terminalstate_event_parser_works() {
|
||||||
}
|
let mut ts = TerminalState::new();
|
||||||
|
use KeyEventKind::*;
|
||||||
impl TerminalState {
|
assert_eq!(
|
||||||
pub fn new() -> Self {
|
ts.events_for_input(b"Hello\n").unwrap(),
|
||||||
Self {
|
vec![
|
||||||
char_buffer: VecDeque::<u8>::new(),
|
Event::Key(KeyEvent {
|
||||||
}
|
code: Char('H'),
|
||||||
}
|
modifiers: KeyModifiers::SHIFT,
|
||||||
|
kind: Press,
|
||||||
pub fn events_for_input(&mut self, input: &[u8]) -> std::io::Result<Vec<Event>> {
|
state: KeyEventState::NONE
|
||||||
let mut result: Vec<Event> = Vec::new();
|
}),
|
||||||
|
Event::Key(KeyEvent {
|
||||||
self.char_buffer.extend(input);
|
code: Char('e'),
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
modifiers: KeyModifiers::NONE,
|
||||||
|
kind: Press,
|
||||||
loop {
|
state: KeyEventState::NONE
|
||||||
match self.char_buffer.pop_front() {
|
}),
|
||||||
None => return Ok(result),
|
Event::Key(KeyEvent {
|
||||||
Some(c) => {
|
code: Char('l'),
|
||||||
buf.push(c);
|
modifiers: KeyModifiers::NONE,
|
||||||
match parse_event(&buf, true)? {
|
kind: Press,
|
||||||
None => continue,
|
state: KeyEventState::NONE
|
||||||
Some(e) => result.push(e),
|
}),
|
||||||
}
|
Event::Key(KeyEvent {
|
||||||
}
|
code: Char('l'),
|
||||||
}
|
modifiers: KeyModifiers::NONE,
|
||||||
}
|
kind: Press,
|
||||||
|
state: KeyEventState::NONE
|
||||||
|
}),
|
||||||
|
Event::Key(KeyEvent {
|
||||||
|
code: Char('o'),
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
kind: Press,
|
||||||
|
state: KeyEventState::NONE
|
||||||
|
}),
|
||||||
|
Event::Key(KeyEvent {
|
||||||
|
code: Char('j'),
|
||||||
|
modifiers: KeyModifiers::CONTROL,
|
||||||
|
kind: Press,
|
||||||
|
state: KeyEventState::NONE
|
||||||
|
})
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,19 +52,19 @@ impl Filter for EventFilter {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
super::Event, CursorPositionFilter, Event, EventFilter, Filter, InternalEventFilter,
|
super::Event, CursorPositionFilter, EventFilter, Filter, KeyboardEnhancementFlagsFilter,
|
||||||
KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter,
|
PrimaryDeviceAttributesFilter,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cursor_position_filter_filters_cursor_position() {
|
fn test_cursor_position_filter_filters_cursor_position() {
|
||||||
assert!(!CursorPositionFilter.eval(&Event::Event(Event::Resize(10, 10))));
|
assert!(!CursorPositionFilter.eval(&Event::Resize(10, 10)));
|
||||||
assert!(CursorPositionFilter.eval(&Event::CursorPosition(0, 0)));
|
assert!(CursorPositionFilter.eval(&Event::CursorPosition(0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_keyboard_enhancement_status_filter_filters_keyboard_enhancement_status() {
|
fn test_keyboard_enhancement_status_filter_filters_keyboard_enhancement_status() {
|
||||||
assert!(!KeyboardEnhancementFlagsFilter.eval(&Event::Event(Event::Resize(10, 10))));
|
assert!(!KeyboardEnhancementFlagsFilter.eval(&Event::Resize(10, 10)));
|
||||||
assert!(
|
assert!(
|
||||||
KeyboardEnhancementFlagsFilter.eval(&Event::KeyboardEnhancementFlags(
|
KeyboardEnhancementFlagsFilter.eval(&Event::KeyboardEnhancementFlags(
|
||||||
crate::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
|
crate::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
|
||||||
@ -75,19 +75,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_primary_device_attributes_filter_filters_primary_device_attributes() {
|
fn test_primary_device_attributes_filter_filters_primary_device_attributes() {
|
||||||
assert!(!PrimaryDeviceAttributesFilter.eval(&Event::Event(Event::Resize(10, 10))));
|
assert!(!PrimaryDeviceAttributesFilter.eval(&Event::Resize(10, 10)));
|
||||||
assert!(PrimaryDeviceAttributesFilter.eval(&Event::PrimaryDeviceAttributes));
|
assert!(PrimaryDeviceAttributesFilter.eval(&Event::PrimaryDeviceAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_event_filter_filters_events() {
|
fn test_event_filter_filters_events() {
|
||||||
assert!(EventFilter.eval(&Event::Event(Event::Resize(10, 10))));
|
assert!(EventFilter.eval(&Event::Resize(10, 10)));
|
||||||
assert!(!EventFilter.eval(&Event::CursorPosition(0, 0)));
|
assert!(EventFilter.eval(&Event::CursorPosition(0, 0)));
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_event_filter_filters_internal_events() {
|
|
||||||
assert!(InternalEventFilter.eval(&Event::Event(Event::Resize(10, 10))));
|
|
||||||
assert!(InternalEventFilter.eval(&Event::CursorPosition(0, 0)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,49 +125,6 @@ impl fmt::Display for Colored {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::style::{Color, Colored};
|
use crate::style::{Color, Colored};
|
||||||
|
|
||||||
fn check_format_color(colored: Colored, expected: &str) {
|
|
||||||
Colored::set_ansi_color_disabled(true);
|
|
||||||
assert_eq!(colored.to_string(), "");
|
|
||||||
Colored::set_ansi_color_disabled(false);
|
|
||||||
assert_eq!(colored.to_string(), expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_fg_color() {
|
|
||||||
let colored = Colored::ForegroundColor(Color::Red);
|
|
||||||
check_format_color(colored, "38;5;9");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_bg_color() {
|
|
||||||
let colored = Colored::BackgroundColor(Color::Red);
|
|
||||||
check_format_color(colored, "48;5;9");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_reset_fg_color() {
|
|
||||||
let colored = Colored::ForegroundColor(Color::Reset);
|
|
||||||
check_format_color(colored, "39");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_reset_bg_color() {
|
|
||||||
let colored = Colored::BackgroundColor(Color::Reset);
|
|
||||||
check_format_color(colored, "49");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_fg_rgb_color() {
|
|
||||||
let colored = Colored::BackgroundColor(Color::Rgb { r: 1, g: 2, b: 3 });
|
|
||||||
check_format_color(colored, "48;2;1;2;3");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_fg_ansi_color() {
|
|
||||||
let colored = Colored::ForegroundColor(Color::AnsiValue(255));
|
|
||||||
check_format_color(colored, "38;5;255");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_ansi_fg() {
|
fn test_parse_ansi_fg() {
|
||||||
test_parse_ansi(Colored::ForegroundColor)
|
test_parse_ansi(Colored::ForegroundColor)
|
||||||
@ -274,16 +231,4 @@ mod tests {
|
|||||||
test("48;2;0;2;25;");
|
test("48;2;0;2;25;");
|
||||||
test("48;2;0;2;25;3");
|
test("48;2;0;2;25;3");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_no_color() {
|
|
||||||
std::env::set_var("NO_COLOR", "1");
|
|
||||||
assert!(Colored::ansi_color_disabled());
|
|
||||||
std::env::set_var("NO_COLOR", "XXX");
|
|
||||||
assert!(Colored::ansi_color_disabled());
|
|
||||||
std::env::set_var("NO_COLOR", "");
|
|
||||||
assert!(!Colored::ansi_color_disabled());
|
|
||||||
std::env::remove_var("NO_COLOR");
|
|
||||||
assert!(!Colored::ansi_color_disabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -405,63 +405,3 @@ impl_display!(for ScrollUp);
|
|||||||
impl_display!(for ScrollDown);
|
impl_display!(for ScrollDown);
|
||||||
impl_display!(for SetSize);
|
impl_display!(for SetSize);
|
||||||
impl_display!(for Clear);
|
impl_display!(for Clear);
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::{io::stdout, thread, time};
|
|
||||||
|
|
||||||
use crate::execute;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
// Test is disabled, because it's failing on Travis CI
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn test_resize_ansi() {
|
|
||||||
let (width, height) = size().unwrap();
|
|
||||||
|
|
||||||
execute!(stdout(), SetSize(35, 35)).unwrap();
|
|
||||||
|
|
||||||
// see issue: https://github.com/eminence/terminal-size/issues/11
|
|
||||||
thread::sleep(time::Duration::from_millis(30));
|
|
||||||
|
|
||||||
assert_eq!((35, 35), size().unwrap());
|
|
||||||
|
|
||||||
// reset to previous size
|
|
||||||
execute!(stdout(), SetSize(width, height)).unwrap();
|
|
||||||
|
|
||||||
// see issue: https://github.com/eminence/terminal-size/issues/11
|
|
||||||
thread::sleep(time::Duration::from_millis(30));
|
|
||||||
|
|
||||||
assert_eq!((width, height), size().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_mode() {
|
|
||||||
// check we start from normal mode (may fail on some test harnesses)
|
|
||||||
assert!(!is_raw_mode_enabled().unwrap());
|
|
||||||
|
|
||||||
// enable the raw mode
|
|
||||||
if enable_raw_mode().is_err() {
|
|
||||||
// Enabling raw mode doesn't work on the ci
|
|
||||||
// So we just ignore it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check it worked (on unix it doesn't really check the underlying
|
|
||||||
// tty but rather check that the code is consistent)
|
|
||||||
assert!(is_raw_mode_enabled().unwrap());
|
|
||||||
|
|
||||||
// enable it again, this should not change anything
|
|
||||||
enable_raw_mode().unwrap();
|
|
||||||
|
|
||||||
// check we're still in raw mode
|
|
||||||
assert!(is_raw_mode_enabled().unwrap());
|
|
||||||
|
|
||||||
// now let's disable it
|
|
||||||
disable_raw_mode().unwrap();
|
|
||||||
|
|
||||||
// check we're back to normal mode
|
|
||||||
assert!(!is_raw_mode_enabled().unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user