Event::Unknown now carries the unknown bytes rather than a i32

And termion has been updated to use termion::Event::Unsupported
This commit is contained in:
Alexandre Bury 2017-03-25 11:01:25 -07:00
parent 79212d4be6
commit 2cd2787119
10 changed files with 75 additions and 57 deletions

View File

@ -50,7 +50,7 @@ version = "0.8"
[dependencies.termion]
optional = true
version = "1.1.1"
version = "1.3.0"
[dev-dependencies]
rand = "0.3"

View File

@ -1,9 +1,9 @@
extern crate ncurses;
use backend;
use event::{Event, Key};
use self::super::find_closest;
use backend;
use event::{Event, Key};
use theme::{Color, ColorStyle, Effect};
use utf8;
@ -94,7 +94,7 @@ impl backend::Backend for Concrete {
if 32 <= ch && ch <= 255 && ch != 127 {
Event::Char(utf8::read_char(ch as u8,
|| Some(ncurses::getch() as u8))
.unwrap())
.unwrap())
} else {
parse_ncurses_char(ch)
}
@ -226,6 +226,11 @@ fn parse_ncurses_char(ch: i32) -> Event {
// Values 8-10 (H,I,J) are used by other commands,
// so we probably won't receive them. Meh~
c @ 1...25 => Event::CtrlChar((b'a' + (c - 1) as u8) as char),
_ => Event::Unknown(ch),
other => {
// Split the i32 into 4 bytes
Event::Unknown((0..4)
.map(|i| ((other >> (8 * i)) & 0xFF) as u8)
.collect())
}
}
}

View File

@ -1,10 +1,10 @@
extern crate pancurses;
use backend;
use event::{Event, Key};
use self::super::find_closest;
use backend;
use event::{Event, Key};
use theme::{Color, ColorStyle, Effect};
use utf8;
@ -23,9 +23,7 @@ impl backend::Backend for Concrete {
pancurses::curs_set(0);
window.bkgd(pancurses::ColorPair(ColorStyle::Background.id() as u8));
Concrete {
window: window,
}
Concrete { window: window }
}
fn screen_size(&self) -> (usize, usize) {
@ -88,25 +86,39 @@ impl backend::Backend for Concrete {
// TODO: wait for a very short delay. If more keys are
// pipelined, it may be an escape sequence.
pancurses::Input::Character('\u{7f}') |
pancurses::Input::Character('\u{8}') => Event::Key(Key::Backspace),
pancurses::Input::Character('\u{8}') => {
Event::Key(Key::Backspace)
}
pancurses::Input::Character('\u{9}') => Event::Key(Key::Tab),
pancurses::Input::Character('\u{1b}') => Event::Key(Key::Esc),
pancurses::Input::Character(c) if 32 <= (c as u32) &&
(c as u32) <= 255 => {
Event::Char(utf8::read_char(c as u8, || {
self.window.getch().and_then(|i| match i {
self.window.getch().and_then(|i| match i {
pancurses::Input::Character(c) => {
Some(c as u8)
}
_ => None,
})
})
.unwrap())
})
.unwrap())
}
pancurses::Input::Character(c) => {
let mut bytes = [0u8; 4];
Event::Unknown(c.encode_utf8(&mut bytes)
.as_bytes()
.to_vec())
}
pancurses::Input::Character(c) => Event::Unknown(c as i32),
// TODO: Some key combos are not recognized by pancurses,
// but are sent as Unknown. We could still parse them here.
pancurses::Input::Unknown(i) => Event::Unknown(i),
pancurses::Input::Unknown(other) => {
Event::Unknown((0..4)
.map(|i| {
((other >> (8 * i)) & 0xFF) as
u8
})
.collect())
}
// TODO: I honestly have no fucking idea what KeyCodeYes is
pancurses::Input::KeyCodeYes => Event::Refresh,
pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),

View File

@ -2,22 +2,22 @@ extern crate termion;
extern crate chan_signal;
use ::backend;
use chan;
use ::event::{Event, Key};
use self::termion::color as tcolor;
use self::termion::event::Event as TEvent;
use self::termion::event::Key as TKey;
use self::termion::input::TermRead;
use self::termion::raw::IntoRawMode;
use self::termion::style as tstyle;
use backend;
use chan;
use event::{Event, Key};
use std::cell::Cell;
use std::collections::BTreeMap;
use std::fmt;
use std::io::Write;
use std::thread;
use std::time;
use ::theme;
use theme;
pub struct Concrete {
terminal: termion::raw::RawTerminal<::std::io::Stdout>,
@ -84,11 +84,11 @@ impl backend::Backend for Concrete {
let terminal = ::std::io::stdout().into_raw_mode().unwrap();
let (sender, receiver) = chan::async();
thread::spawn(move || for key in ::std::io::stdin().keys() {
if let Ok(key) = key {
sender.send(map_key(key))
}
});
thread::spawn(move || for key in ::std::io::stdin().events() {
if let Ok(key) = key {
sender.send(map_key(key))
}
});
let backend = Concrete {
terminal: terminal,
@ -185,29 +185,30 @@ impl backend::Backend for Concrete {
}
}
fn map_key(key: TKey) -> Event {
match key {
TKey::Esc => Event::Key(Key::Esc),
TKey::Backspace => Event::Key(Key::Backspace),
TKey::Left => Event::Key(Key::Left),
TKey::Right => Event::Key(Key::Right),
TKey::Up => Event::Key(Key::Up),
TKey::Down => Event::Key(Key::Down),
TKey::Home => Event::Key(Key::Home),
TKey::End => Event::Key(Key::End),
TKey::PageUp => Event::Key(Key::PageUp),
TKey::PageDown => Event::Key(Key::PageDown),
TKey::Delete => Event::Key(Key::Del),
TKey::Insert => Event::Key(Key::Ins),
TKey::F(i) if i < 12 => Event::Key(Key::from_f(i)),
TKey::F(j) => Event::Unknown(-(j as i32)),
TKey::Char('\n') => Event::Key(Key::Enter),
TKey::Char('\t') => Event::Key(Key::Tab),
TKey::Char(c) => Event::Char(c),
TKey::Ctrl('c') => Event::Exit,
TKey::Ctrl(c) => Event::CtrlChar(c),
TKey::Alt(c) => Event::AltChar(c),
_ => Event::Unknown(-1),
fn map_key(event: TEvent) -> Event {
match event {
TEvent::Unsupported(bytes) => Event::Unknown(bytes),
TEvent::Key(TKey::Esc) => Event::Key(Key::Esc),
TEvent::Key(TKey::Backspace) => Event::Key(Key::Backspace),
TEvent::Key(TKey::Left) => Event::Key(Key::Left),
TEvent::Key(TKey::Right) => Event::Key(Key::Right),
TEvent::Key(TKey::Up) => Event::Key(Key::Up),
TEvent::Key(TKey::Down) => Event::Key(Key::Down),
TEvent::Key(TKey::Home) => Event::Key(Key::Home),
TEvent::Key(TKey::End) => Event::Key(Key::End),
TEvent::Key(TKey::PageUp) => Event::Key(Key::PageUp),
TEvent::Key(TKey::PageDown) => Event::Key(Key::PageDown),
TEvent::Key(TKey::Delete) => Event::Key(Key::Del),
TEvent::Key(TKey::Insert) => Event::Key(Key::Ins),
TEvent::Key(TKey::F(i)) if i < 12 => Event::Key(Key::from_f(i)),
TEvent::Key(TKey::F(j)) => Event::Unknown(vec![j]),
TEvent::Key(TKey::Char('\n')) => Event::Key(Key::Enter),
TEvent::Key(TKey::Char('\t')) => Event::Key(Key::Tab),
TEvent::Key(TKey::Char(c)) => Event::Char(c),
TEvent::Key(TKey::Ctrl('c')) => Event::Exit,
TEvent::Key(TKey::Ctrl(c)) => Event::CtrlChar(c),
TEvent::Key(TKey::Alt(c)) => Event::AltChar(c),
_ => Event::Unknown(vec![]),
}
}

View File

@ -186,7 +186,7 @@ impl Key {
}
/// Represents an event as seen by the application.
#[derive(PartialEq,Eq,Clone,Copy,Hash,Debug)]
#[derive(PartialEq,Eq,Clone,Hash,Debug)]
pub enum Event {
/// Event fired when the window is resized.
WindowResize,
@ -217,7 +217,7 @@ pub enum Event {
CtrlAlt(Key),
/// An unknown event was received.
Unknown(i32),
Unknown(Vec<u8>),
#[doc(hidden)]
/// The application is about to exit.

View File

@ -594,7 +594,7 @@ impl Cursive {
if self.menubar.receive_events() {
self.menubar.on_event(event).process(self);
} else {
match self.screen_mut().on_event(event) {
match self.screen_mut().on_event(event.clone()) {
// If the event was ignored,
// it is our turn to play with it.
EventResult::Ignored => self.on_event(event),

View File

@ -316,7 +316,7 @@ impl View for Dialog {
match self.focus {
// If we are on the content, we can only go down.
Focus::Content => {
match self.content.on_event(event) {
match self.content.on_event(event.clone()) {
EventResult::Ignored if !self.buttons.is_empty() => {
match event {
Event::Key(Key::Down) |
@ -334,7 +334,7 @@ impl View for Dialog {
}
// If we are on a button, we have more choice
Focus::Button(i) => {
match self.buttons[i].on_event(event) {
match self.buttons[i].on_event(event.clone()) {
EventResult::Ignored => {
match event {
// Up goes back to the content

View File

@ -46,7 +46,7 @@ impl<T: View> ViewWrapper for KeyEventView<T> {
wrap_impl!(self.content: T);
fn wrap_on_event(&mut self, event: Event) -> EventResult {
match self.content.on_event(event) {
match self.content.on_event(event.clone()) {
EventResult::Ignored => {
match self.callbacks.get(&event) {
None => EventResult::Ignored,

View File

@ -353,7 +353,7 @@ impl View for LinearLayout {
}
fn on_event(&mut self, event: Event) -> EventResult {
match self.children[self.focus].view.on_event(event) {
match self.children[self.focus].view.on_event(event.clone()) {
EventResult::Ignored => {
match event {
Event::Shift(Key::Tab) if self.focus > 0 => {

View File

@ -255,7 +255,7 @@ impl View for ListView {
}
if let Child::Row(_, ref mut view) = self.children[self.focus] {
let result = view.on_event(event);
let result = view.on_event(event.clone());
if result.is_consumed() {
return result;
}