Add support for Shift and Ctrl input

Careful: Ctrl-4 and ctrl-\ currently make ncurses crash.
Also some letters combine with Ctrl to make other codes. Run stty -a to
see some mappings.
Basically, you'll have issues with:
C,I,J,M,Q,S,Z
and non-letters.
This commit is contained in:
Alexandre Bury 2015-05-28 14:44:10 -07:00
parent 37e54b3598
commit 3adb95c7ab
4 changed files with 43 additions and 21 deletions

View File

@ -26,10 +26,10 @@ pub enum Key {
Enter, Enter,
/// Tabulation key /// Tabulation key
Tab, Tab,
ArrowLeft, Left,
ArrowRight, Right,
ArrowUp, Up,
ArrowDown, Down,
PageUp, PageUp,
PageDown, PageDown,
Backspace, Backspace,
@ -57,6 +57,14 @@ pub enum Key {
F13, F13,
F14, F14,
F15, F15,
// Left arrow while shift is pressed
ShiftLeft,
ShiftRight,
CtrlLeft,
CtrlRight,
CtrlUp,
CtrlDown,
CtrlChar(char),
Unknown(i32), Unknown(i32),
} }
@ -67,13 +75,19 @@ impl Key {
// Treat Return and the numpad Enter the same // Treat Return and the numpad Enter the same
10 | ncurses::KEY_ENTER => Key::Enter, 10 | ncurses::KEY_ENTER => Key::Enter,
27 => Key::Esc, 27 => Key::Esc,
127 => Key::Backspace, 127 | ncurses::KEY_BACKSPACE => Key::Backspace,
330 => Key::Del, 330 => Key::Del,
331 => Key::Ins, 331 => Key::Ins,
ncurses::KEY_LEFT => Key::ArrowLeft, 521 => Key::CtrlDown,
ncurses::KEY_RIGHT => Key::ArrowRight, 541 => Key::CtrlLeft,
ncurses::KEY_UP => Key::ArrowUp, 556 => Key::CtrlRight,
ncurses::KEY_DOWN => Key::ArrowDown, 562 => Key::CtrlUp,
ncurses::KEY_SLEFT => Key::ShiftLeft,
ncurses::KEY_SRIGHT => Key::ShiftRight,
ncurses::KEY_LEFT => Key::Left,
ncurses::KEY_RIGHT => Key::Right,
ncurses::KEY_UP => Key::Up,
ncurses::KEY_DOWN => Key::Down,
ncurses::KEY_PPAGE => Key::PageUp, ncurses::KEY_PPAGE => Key::PageUp,
ncurses::KEY_NPAGE => Key::PageDown, ncurses::KEY_NPAGE => Key::PageDown,
ncurses::KEY_HOME => Key::Home, ncurses::KEY_HOME => Key::Home,
@ -93,6 +107,7 @@ impl Key {
ncurses::KEY_F13 => Key::F13, ncurses::KEY_F13 => Key::F13,
ncurses::KEY_F14 => Key::F14, ncurses::KEY_F14 => Key::F14,
ncurses::KEY_F15 => Key::F15, ncurses::KEY_F15 => Key::F15,
c @ 1 ... 7 | c @ 11 ... 25 => Key::CtrlChar(('a' as u8 + (c-1) as u8) as char),
_ => Key::Unknown(ch), _ => Key::Unknown(ch),
} }
} }
@ -102,11 +117,18 @@ impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
Key::Unknown(ch) => write!(f, "Unknown: {}", ch), Key::Unknown(ch) => write!(f, "Unknown: {}", ch),
Key::CtrlChar(ch) => write!(f, "Ctrl-{}", ch),
key => write!(f, "{}", match key { key => write!(f, "{}", match key {
Key::ArrowLeft => "Left", Key::Left => "Left",
Key::ArrowRight => "Right", Key::Right => "Right",
Key::ArrowDown => "Down", Key::Down => "Down",
Key::ArrowUp => "Up", Key::Up => "Up",
Key::ShiftLeft => "Shift-Left",
Key::ShiftRight => "Shift-Right",
Key::CtrlLeft => "Ctrl-Left",
Key::CtrlRight => "Ctrl-Right",
Key::CtrlUp => "Ctrl-Up",
Key::CtrlDown => "Ctrl-Down",
Key::PageUp => "PageUp", Key::PageUp => "PageUp",
Key::PageDown => "PageDown", Key::PageDown => "PageDown",
Key::Home => "Home", Key::Home => "Home",

View File

@ -168,7 +168,7 @@ impl View for Dialog {
// If we are on the content, we can only go down. // If we are on the content, we can only go down.
Focus::Content => match self.content.on_event(event) { Focus::Content => match self.content.on_event(event) {
EventResult::Ignored if !self.buttons.is_empty() => match event { EventResult::Ignored if !self.buttons.is_empty() => match event {
Event::KeyEvent(Key::ArrowDown) => { Event::KeyEvent(Key::Down) => {
// Default to leftmost button when going down. // Default to leftmost button when going down.
self.focus = Focus::Button(0); self.focus = Focus::Button(0);
EventResult::Consumed(None) EventResult::Consumed(None)
@ -181,7 +181,7 @@ impl View for Dialog {
Focus::Button(i) => match self.buttons[i].on_event(event) { Focus::Button(i) => match self.buttons[i].on_event(event) {
EventResult::Ignored => match event { EventResult::Ignored => match event {
// Up goes back to the content // Up goes back to the content
Event::KeyEvent(Key::ArrowUp) => { Event::KeyEvent(Key::Up) => {
if self.content.take_focus() { if self.content.take_focus() {
self.focus = Focus::Content; self.focus = Focus::Content;
EventResult::Consumed(None) EventResult::Consumed(None)
@ -190,11 +190,11 @@ impl View for Dialog {
} }
}, },
// Left and Right move to other buttons // Left and Right move to other buttons
Event::KeyEvent(Key::ArrowRight) if i+1 < self.buttons.len() => { Event::KeyEvent(Key::Right) if i+1 < self.buttons.len() => {
self.focus = Focus::Button(i+1); self.focus = Focus::Button(i+1);
EventResult::Consumed(None) EventResult::Consumed(None)
}, },
Event::KeyEvent(Key::ArrowRight) if i > 0 => { Event::KeyEvent(Key::Right) if i > 0 => {
self.focus = Focus::Button(i-1); self.focus = Focus::Button(i-1);
EventResult::Consumed(None) EventResult::Consumed(None)
}, },

View File

@ -89,8 +89,8 @@ impl View for EditView {
Event::KeyEvent(key) => match key { Event::KeyEvent(key) => match key {
Key::Home => self.cursor = 0, Key::Home => self.cursor = 0,
Key::End => self.cursor = self.content.len(), Key::End => self.cursor = self.content.len(),
Key::ArrowLeft if self.cursor > 0 => self.cursor -= 1, Key::Left if self.cursor > 0 => self.cursor -= 1,
Key::ArrowRight if self.cursor < self.content.len() => self.cursor += 1, Key::Right if self.cursor < self.content.len() => self.cursor += 1,
Key::Backspace if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); }, Key::Backspace if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); },
Key::Del if self.cursor < self.content.len() => { self.content.remove(self.cursor); }, Key::Del if self.cursor < self.content.len() => { self.content.remove(self.cursor); },
_ => return EventResult::Ignored, _ => return EventResult::Ignored,

View File

@ -198,8 +198,8 @@ impl View for TextView {
} }
match event { match event {
Event::KeyEvent(Key::ArrowUp) if self.start_line > 0 => self.start_line -= 1, Event::KeyEvent(Key::Up) if self.start_line > 0 => self.start_line -= 1,
Event::KeyEvent(Key::ArrowDown) if self.start_line+self.view_height < self.rows.len() => self.start_line += 1, Event::KeyEvent(Key::Down) if self.start_line+self.view_height < self.rows.len() => self.start_line += 1,
Event::KeyEvent(Key::PageUp) => self.start_line = min(self.start_line+10, self.rows.len()-self.view_height), Event::KeyEvent(Key::PageUp) => self.start_line = min(self.start_line+10, self.rows.len()-self.view_height),
Event::KeyEvent(Key::PageDown) => self.start_line -= min(self.start_line, 10), Event::KeyEvent(Key::PageDown) => self.start_line -= min(self.start_line, 10),
_ => return EventResult::Ignored, _ => return EventResult::Ignored,