Use special key detection for pancurses

Shared with the ncurses backend code
This commit is contained in:
Alexandre Bury 2018-02-20 15:44:07 -08:00
parent 767e225db0
commit 99046d10c3
5 changed files with 77 additions and 91 deletions

View File

@ -48,7 +48,7 @@ version = "5.91.0"
[dependencies.pancurses] [dependencies.pancurses]
features = ["wide"] features = ["wide"]
optional = true optional = true
version = "0.13" version = "0.14"
[dependencies.pulldown-cmark] [dependencies.pulldown-cmark]
default-features = false default-features = false
@ -67,7 +67,7 @@ blt-backend = ["bear-lib-terminal"]
default = ["ncurses-backend"] default = ["ncurses-backend"]
markdown = ["pulldown-cmark"] markdown = ["pulldown-cmark"]
ncurses-backend = ["ncurses", "maplit"] ncurses-backend = ["ncurses", "maplit"]
pancurses-backend = ["pancurses"] pancurses-backend = ["pancurses", "maplit"]
termion-backend = ["termion", "chan", "chan-signal"] termion-backend = ["termion", "chan", "chan-signal"]
[lib] [lib]

View File

@ -1,4 +1,6 @@
use theme::{BaseColor, Color}; use theme::{BaseColor, Color};
use event::{Event, Key};
use std::collections::HashMap;
#[cfg(feature = "ncurses")] #[cfg(feature = "ncurses")]
mod n; mod n;
@ -14,6 +16,51 @@ fn split_i32(code: i32) -> Vec<u8> {
(0..4).map(|i| ((code >> (8 * i)) & 0xFF) as u8).collect() (0..4).map(|i| ((code >> (8 * i)) & 0xFF) as u8).collect()
} }
fn fill_key_codes<F>(target: &mut HashMap<i32, Event>, f: F)
where
F: Fn(i32) -> Option<String>,
{
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 { fn find_closest(color: &Color) -> i16 {
match *color { match *color {
Color::TerminalDefault => -1, Color::TerminalDefault => -1,

View File

@ -13,7 +13,6 @@ use vec::Vec2;
pub struct Concrete { pub struct Concrete {
current_style: Cell<ColorPair>, current_style: Cell<ColorPair>,
pairs: RefCell<HashMap<ColorPair, i16>>, pairs: RefCell<HashMap<ColorPair, i16>>,
key_codes: HashMap<i32, Event>, key_codes: HashMap<i32, Event>,
@ -446,45 +445,7 @@ fn initialize_keymap() -> HashMap<i32, Event> {
add_fn(313, Event::Alt, &mut map); add_fn(313, Event::Alt, &mut map);
// Those codes actually vary between ncurses versions... // Those codes actually vary between ncurses versions...
super::fill_key_codes(&mut map, ncurses::keyname);
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);
}
map map
} }

View File

@ -12,12 +12,17 @@ use utf8;
use vec::Vec2; use vec::Vec2;
pub struct Concrete { pub struct Concrete {
// Used
current_style: Cell<ColorPair>, current_style: Cell<ColorPair>,
pairs: RefCell<HashMap<ColorPair, i32>>, pairs: RefCell<HashMap<ColorPair, i32>>,
window: pancurses::Window,
key_codes: HashMap<i32, Event>,
last_mouse_button: Option<MouseButton>, last_mouse_button: Option<MouseButton>,
event_queue: Vec<Event>, event_queue: Vec<Event>,
// pancurses needs a handle to the current window.
window: pancurses::Window,
} }
impl Concrete { impl Concrete {
@ -157,6 +162,7 @@ impl backend::Backend for Concrete {
window: window, window: window,
last_mouse_button: None, last_mouse_button: None,
event_queue: Vec::new(), event_queue: Vec::new(),
key_codes: initialize_keymap(),
} }
} }
@ -241,6 +247,8 @@ impl backend::Backend for Concrete {
pancurses::Input::Character(c) pancurses::Input::Character(c)
if 32 <= (c as u32) && (c as u32) <= 255 => 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, || { 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) => { pancurses::Input::Character(c) => {
@ -265,53 +273,14 @@ impl backend::Backend for Concrete {
} }
// TODO: Some key combos are not recognized by pancurses, // TODO: Some key combos are not recognized by pancurses,
// but are sent as Unknown. We could still parse them here. // but are sent as Unknown. We could still parse them here.
pancurses::Input::Unknown(code) => match code { pancurses::Input::Unknown(code) => self.key_codes
220 => Event::Ctrl(Key::Del), // pancurses does some weird keycode mapping
.get(&(code + 256 + 48))
224 => Event::Alt(Key::Down), .cloned()
225 => Event::AltShift(Key::Down), .unwrap_or_else(|| {
226 => Event::Ctrl(Key::Down), warn!("Unknown: {}", code);
227 => Event::CtrlShift(Key::Down), Event::Unknown(split_i32(code))
}),
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))
}
},
// TODO: I honestly have no fucking idea what KeyCodeYes is // TODO: I honestly have no fucking idea what KeyCodeYes is
pancurses::Input::KeyCodeYes => Event::Refresh, pancurses::Input::KeyCodeYes => Event::Refresh,
pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak), pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
@ -536,3 +505,12 @@ fn get_mouse_button(bare_event: mmask_t) -> MouseButton {
_ => MouseButton::Other, _ => MouseButton::Other,
} }
} }
fn initialize_keymap() -> HashMap<i32, Event> {
let mut map = HashMap::new();
super::fill_key_codes(&mut map, pancurses::keyname);
map
}

View File

@ -68,7 +68,7 @@ extern crate enumset;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[cfg(feature = "ncurses")] #[cfg(any(feature = "ncurses", feature = "pancurses"))]
#[macro_use] #[macro_use]
extern crate maplit; extern crate maplit;