From 99046d10c33e02caf913e755a23e8ac5e8718868 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Tue, 20 Feb 2018 15:44:07 -0800 Subject: [PATCH] Use special key detection for pancurses Shared with the ncurses backend code --- Cargo.toml | 4 +-- src/backend/curses/mod.rs | 47 +++++++++++++++++++++++++ src/backend/curses/n.rs | 41 +--------------------- src/backend/curses/pan.rs | 74 ++++++++++++++------------------------- src/lib.rs | 2 +- 5 files changed, 77 insertions(+), 91 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c1ee33f..5e7b18b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ version = "5.91.0" [dependencies.pancurses] features = ["wide"] optional = true -version = "0.13" +version = "0.14" [dependencies.pulldown-cmark] default-features = false @@ -67,7 +67,7 @@ blt-backend = ["bear-lib-terminal"] default = ["ncurses-backend"] markdown = ["pulldown-cmark"] ncurses-backend = ["ncurses", "maplit"] -pancurses-backend = ["pancurses"] +pancurses-backend = ["pancurses", "maplit"] termion-backend = ["termion", "chan", "chan-signal"] [lib] diff --git a/src/backend/curses/mod.rs b/src/backend/curses/mod.rs index f441150..d97e4a9 100644 --- a/src/backend/curses/mod.rs +++ b/src/backend/curses/mod.rs @@ -1,4 +1,6 @@ use theme::{BaseColor, Color}; +use event::{Event, Key}; +use std::collections::HashMap; #[cfg(feature = "ncurses")] mod n; @@ -14,6 +16,51 @@ fn split_i32(code: i32) -> Vec { (0..4).map(|i| ((code >> (8 * i)) & 0xFF) as u8).collect() } +fn fill_key_codes(target: &mut HashMap, f: F) +where + F: Fn(i32) -> Option, +{ + let key_names = hashmap!{ + "DC" => Key::Del, + "DN" => Key::Down, + "END" => Key::End, + "HOM" => Key::Home, + "IC" => Key::Ins, + "LFT" => Key::Left, + "NXT" => Key::PageDown, + "PRV" => Key::PageUp, + "RIT" => Key::Right, + "UP" => Key::Up, + }; + + for code in 512..1024 { + let name = match f(code) { + Some(name) => name, + None => continue, + }; + + if !name.starts_with('k') { + continue; + } + + let (key_name, modifier) = name[1..].split_at(name.len() - 2); + let key = match key_names.get(key_name) { + Some(&key) => key, + None => continue, + }; + let event = match modifier { + "3" => Event::Alt(key), + "4" => Event::AltShift(key), + "5" => Event::Ctrl(key), + "6" => Event::CtrlShift(key), + "7" => Event::CtrlAlt(key), + _ => continue, + }; + target.insert(code, event); + } + +} + fn find_closest(color: &Color) -> i16 { match *color { Color::TerminalDefault => -1, diff --git a/src/backend/curses/n.rs b/src/backend/curses/n.rs index 9624a89..ad88f9e 100644 --- a/src/backend/curses/n.rs +++ b/src/backend/curses/n.rs @@ -13,7 +13,6 @@ use vec::Vec2; pub struct Concrete { current_style: Cell, - pairs: RefCell>, key_codes: HashMap, @@ -446,45 +445,7 @@ fn initialize_keymap() -> HashMap { add_fn(313, Event::Alt, &mut map); // Those codes actually vary between ncurses versions... - - let key_names = hashmap!{ - "DC" => Key::Del, - "DN" => Key::Down, - "END" => Key::End, - "HOM" => Key::Home, - "IC" => Key::Ins, - "LFT" => Key::Left, - "NXT" => Key::PageDown, - "PRV" => Key::PageUp, - "RIT" => Key::Right, - "UP" => Key::Up, - }; - - for code in 512..1024 { - let name = match ncurses::keyname(code) { - Some(name) => name, - None => continue, - }; - - if !name.starts_with('k') { - continue; - } - - let (key_name, modifier) = name[1..].split_at(name.len() - 2); - let key = match key_names.get(key_name) { - Some(&key) => key, - None => continue, - }; - let event = match modifier { - "3" => Event::Alt(key), - "4" => Event::AltShift(key), - "5" => Event::Ctrl(key), - "6" => Event::CtrlShift(key), - "7" => Event::CtrlAlt(key), - _ => continue, - }; - map.insert(code, event); - } + super::fill_key_codes(&mut map, ncurses::keyname); map } diff --git a/src/backend/curses/pan.rs b/src/backend/curses/pan.rs index 186cf29..91b09db 100644 --- a/src/backend/curses/pan.rs +++ b/src/backend/curses/pan.rs @@ -12,12 +12,17 @@ use utf8; use vec::Vec2; pub struct Concrete { + // Used current_style: Cell, pairs: RefCell>, - window: pancurses::Window, + + key_codes: HashMap, last_mouse_button: Option, event_queue: Vec, + + // pancurses needs a handle to the current window. + window: pancurses::Window, } impl Concrete { @@ -157,6 +162,7 @@ impl backend::Backend for Concrete { window: window, last_mouse_button: None, event_queue: Vec::new(), + key_codes: initialize_keymap(), } } @@ -241,6 +247,8 @@ impl backend::Backend for Concrete { pancurses::Input::Character(c) if 32 <= (c as u32) && (c as u32) <= 255 => { + // TODO: pancurses may start parsing the input. + // In this case, return as-is. utf8::read_char(c as u8, || { self.window.getch().and_then(|i| match i { pancurses::Input::Character(c) => { @@ -265,53 +273,14 @@ impl backend::Backend for Concrete { } // TODO: Some key combos are not recognized by pancurses, // but are sent as Unknown. We could still parse them here. - pancurses::Input::Unknown(code) => match code { - 220 => Event::Ctrl(Key::Del), - - 224 => Event::Alt(Key::Down), - 225 => Event::AltShift(Key::Down), - 226 => Event::Ctrl(Key::Down), - 227 => Event::CtrlShift(Key::Down), - - 229 => Event::Alt(Key::End), - 230 => Event::AltShift(Key::End), - 231 => Event::Ctrl(Key::End), - 232 => Event::CtrlShift(Key::End), - - 235 => Event::Alt(Key::Home), - 236 => Event::AltShift(Key::Home), - 237 => Event::Ctrl(Key::Home), - 238 => Event::CtrlShift(Key::Home), - - 246 => Event::Alt(Key::Left), - 247 => Event::AltShift(Key::Left), - 248 => Event::Ctrl(Key::Left), - 249 => Event::CtrlShift(Key::Left), - - 251 => Event::Alt(Key::PageDown), - 252 => Event::AltShift(Key::PageDown), - 253 => Event::Ctrl(Key::PageDown), - 254 => Event::CtrlShift(Key::PageDown), - - 256 => Event::Alt(Key::PageUp), - 257 => Event::AltShift(Key::PageUp), - 258 => Event::Ctrl(Key::PageUp), - 259 => Event::CtrlShift(Key::PageUp), - - 261 => Event::Alt(Key::Right), - 262 => Event::AltShift(Key::Right), - 263 => Event::Ctrl(Key::Right), - 264 => Event::CtrlShift(Key::Right), - - 267 => Event::Alt(Key::Up), - 268 => Event::AltShift(Key::Up), - 269 => Event::Ctrl(Key::Up), - 270 => Event::CtrlShift(Key::Up), - other => { - warn!("Unknown: {}", other); - Event::Unknown(split_i32(other)) - } - }, + pancurses::Input::Unknown(code) => self.key_codes + // pancurses does some weird keycode mapping + .get(&(code + 256 + 48)) + .cloned() + .unwrap_or_else(|| { + warn!("Unknown: {}", code); + Event::Unknown(split_i32(code)) + }), // TODO: I honestly have no fucking idea what KeyCodeYes is pancurses::Input::KeyCodeYes => Event::Refresh, pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak), @@ -536,3 +505,12 @@ fn get_mouse_button(bare_event: mmask_t) -> MouseButton { _ => MouseButton::Other, } } + +fn initialize_keymap() -> HashMap { + + let mut map = HashMap::new(); + + super::fill_key_codes(&mut map, pancurses::keyname); + + map +} diff --git a/src/lib.rs b/src/lib.rs index 7845465..442c2fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,7 +68,7 @@ extern crate enumset; #[macro_use] extern crate log; -#[cfg(feature = "ncurses")] +#[cfg(any(feature = "ncurses", feature = "pancurses"))] #[macro_use] extern crate maplit;