[options] custom keymap: support binding keys

This commit is contained in:
zhang_ji 2016-06-30 12:24:21 +08:00
parent e8c7366811
commit eae4dd6e2e
4 changed files with 198 additions and 53 deletions

View file

@ -6,3 +6,4 @@ authors = ["Mark Wallace <lotabout@gmail.com>"]
[dependencies]
libc = "*"
ncurses = "*"
getopts = "0.2"

View file

@ -54,3 +54,44 @@ pub enum Event {
EvActUp,
EvActYank,
}
pub fn parse_action(action: &str) -> Option<Event> {
match action {
"abort" => Some(Event::EvActAbort),
"accept" => Some(Event::EvActAccept),
"backward-char" => Some(Event::EvActBackwardChar),
"backward-delete-char" => Some(Event::EvActBackwardDeleteChar),
"backward-kill-word" => Some(Event::EvActBackwardKillWord),
"backward-word" => Some(Event::EvActBackwardWord),
"beginning-of-line" => Some(Event::EvActBeginningOfLine),
"cancel" => Some(Event::EvActCancel),
"clear-screen" => Some(Event::EvActClearScreen),
"delete-char" => Some(Event::EvActDeleteChar),
"delete-charEOF" => Some(Event::EvActDeleteCharEOF),
"deselect-all" => Some(Event::EvActDeselectAll),
"down" => Some(Event::EvActDown),
"end-of-line" => Some(Event::EvActEndOfLine),
"forward-char" => Some(Event::EvActForwardChar),
"forward-word" => Some(Event::EvActForwardWord),
"ignore" => Some(Event::EvActIgnore),
"kill-line" => Some(Event::EvActKillLine),
"kill-word" => Some(Event::EvActKillWord),
"next-history" => Some(Event::EvActNextHistory),
"page-down" => Some(Event::EvActPageDown),
"page-up" => Some(Event::EvActPageUp),
"previous-history" => Some(Event::EvActPreviousHistory),
"select-all" => Some(Event::EvActSelectAll),
"toggle" => Some(Event::EvActToggle),
"toggle-all" => Some(Event::EvActToggleAll),
"toggle-down" => Some(Event::EvActToggleDown),
"toggle-in" => Some(Event::EvActToggleIn),
"toggle-out" => Some(Event::EvActToggleOut),
"toggle-sort" => Some(Event::EvActToggleSort),
"toggle-up" => Some(Event::EvActToggleUp),
"unix-line-discard" => Some(Event::EvActUnixLineDiscard),
"unix-word-rubout" => Some(Event::EvActUnixWordRubout),
"up" => Some(Event::EvActUp),
"yank" => Some(Event::EvActYank),
_ => None
}
}

View file

@ -11,7 +11,7 @@ use std::collections::VecDeque;
use std::time::Duration;
use util::eventbox::EventBox;
use event::Event;
use event::{Event, parse_action};
use ncurses::*;
@ -52,6 +52,33 @@ impl Input {
}
}
}
pub fn bind(&mut self, key: &str, action: &str) {
let key = parse_key(key);
let action = parse_action(action);
if key == None || action == None {return;}
let key = key.unwrap();
let act = action.unwrap();
// remove the key for existing keymap;
let _ = self.keymap.remove(&key);
self.keymap.entry(key).or_insert(act);
}
// keymap is comma separated: 'ctrl-j:accept,ctrl-k:kill-line'
pub fn parse_keymap(&mut self, keymap: Option<String>) {
if let Some(key_action) = keymap {
for pair in key_action.split(',') {
let vec: Vec<&str> = pair.split(':').collect();
if vec.len() != 2 {
continue;
} else {
self.bind(vec[0], vec[1]);
}
}
}
}
}
struct KeyBoard {
@ -268,32 +295,8 @@ impl KeyBoard {
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Key {
CtrlA,
CtrlB,
CtrlC,
CtrlD,
CtrlE,
CtrlF,
CtrlG,
CtrlH,
Tab,
CtrlJ,
CtrlK,
CtrlL,
Enter,
CtrlN,
CtrlO,
CtrlP,
CtrlQ,
CtrlR,
CtrlS,
CtrlT,
CtrlU,
CtrlV,
CtrlW,
CtrlX,
CtrlY,
CtrlZ,
CtrlA, CtrlB, CtrlC, CtrlD, CtrlE, CtrlF, CtrlG, CtrlH, Tab, CtrlJ, CtrlK, CtrlL, Enter,
CtrlN, CtrlO, CtrlP, CtrlQ, CtrlR, CtrlS, CtrlT, CtrlU, CtrlV, CtrlW, CtrlX, CtrlY, CtrlZ,
ESC,
Mouse,
@ -314,35 +317,106 @@ pub enum Key {
AltSpace,
AltSlash,
AltBS,
AltA,
AltB,
AltC,
AltD,
AltE,
AltF,
AltG,
AltH,
AltI,
AltJ,
AltK,
AltL,
AltM,
AltN,
AltO,
AltP,
AltQ,
AltR,
AltS,
AltT,
AltU,
AltV,
AltW,
AltX,
AltY,
AltZ,
AltA, AltB, AltC, AltD, AltE, AltF, AltG, AltH, AltI, AltJ, AltK, AltL, AltM,
AltN, AltO, AltP, AltQ, AltR, AltS, AltT, AltU, AltV, AltW, AltX, AltY, AltZ,
Char(char),
}
pub fn parse_key(key: &str) -> Option<Key> {
match key {
"ctrl-a" => Some(Key::CtrlA),
"ctrl-b" => Some(Key::CtrlB),
"ctrl-c" => Some(Key::CtrlC),
"ctrl-d" => Some(Key::CtrlD),
"ctrl-e" => Some(Key::CtrlE),
"ctrl-f" => Some(Key::CtrlF),
"ctrl-g" => Some(Key::CtrlG),
"ctrl-h" => Some(Key::CtrlH),
"tab" | "ctrl-i" => Some(Key::Tab),
"ctrl-j" => Some(Key::CtrlJ),
"ctrl-k" => Some(Key::CtrlK),
"ctrl-l" => Some(Key::CtrlL),
"enter" | "return" | "ctrl-m" => Some(Key::Enter),
"ctrl-n" => Some(Key::CtrlN),
"ctrl-o" => Some(Key::CtrlO),
"ctrl-p" => Some(Key::CtrlP),
"ctrl-q" => Some(Key::CtrlQ),
"ctrl-r" => Some(Key::CtrlR),
"ctrl-s" => Some(Key::CtrlS),
"ctrl-t" => Some(Key::CtrlT),
"ctrl-u" => Some(Key::CtrlU),
"ctrl-v" => Some(Key::CtrlV),
"ctrl-w" => Some(Key::CtrlW),
"ctrl-x" => Some(Key::CtrlX),
"ctrl-y" => Some(Key::CtrlY),
"ctrl-z" => Some(Key::CtrlZ),
"esc" => Some(Key::ESC),
"mouse" => Some(Key::Mouse),
"doubleclick" => Some(Key::DoubleClick),
"btab" | "shift-tab" => Some(Key::BTab),
"bspace" | "bs" => Some(Key::BSpace),
"del" => Some(Key::Del),
"pgup" | "page-up" => Some(Key::PgUp),
"pgdn" | "page-down" => Some(Key::PgDn),
"up" => Some(Key::Up),
"down" => Some(Key::Down),
"left" => Some(Key::Left),
"right" => Some(Key::Right),
"home" => Some(Key::Home),
"end" => Some(Key::End),
"shift-left" => Some(Key::SLeft),
"shift-right" => Some(Key::SRight),
"f1" => Some(Key::F1),
"f2" => Some(Key::F2),
"f3" => Some(Key::F3),
"f4" => Some(Key::F4),
"f5" => Some(Key::F5),
"f6" => Some(Key::F6),
"f7" => Some(Key::F7),
"f8" => Some(Key::F8),
"f9" => Some(Key::F9),
"f10" => Some(Key::F10),
"f11" => Some(Key::F11),
"f12" => Some(Key::F12),
"altenter" => Some(Key::AltEnter),
"altspace" => Some(Key::AltSpace),
"altslash" => Some(Key::AltSlash),
"alt-bs" | "alt-bspace" => Some(Key::AltBS),
"alt-a" => Some(Key::AltA),
"alt-b" => Some(Key::AltB),
"alt-c" => Some(Key::AltC),
"alt-d" => Some(Key::AltD),
"alt-e" => Some(Key::AltE),
"alt-f" => Some(Key::AltF),
"alt-g" => Some(Key::AltG),
"alt-h" => Some(Key::AltH),
"alt-i" => Some(Key::AltI),
"alt-j" => Some(Key::AltJ),
"alt-k" => Some(Key::AltK),
"alt-l" => Some(Key::AltL),
"alt-m" => Some(Key::AltM),
"alt-n" => Some(Key::AltN),
"alt-o" => Some(Key::AltO),
"alt-p" => Some(Key::AltP),
"alt-q" => Some(Key::AltQ),
"alt-r" => Some(Key::AltR),
"alt-s" => Some(Key::AltS),
"alt-t" => Some(Key::AltT),
"alt-u" => Some(Key::AltU),
"alt-v" => Some(Key::AltV),
"alt-w" => Some(Key::AltW),
"alt-x" => Some(Key::AltX),
"alt-y" => Some(Key::AltY),
"alt-z" => Some(Key::AltZ),
_ => None,
}
}
fn get_default_key_map() -> HashMap<Key, Event> {
let mut ret = HashMap::new();
ret.insert(Key::ESC, Event::EvActAbort);
@ -407,3 +481,4 @@ fn get_default_key_map() -> HashMap<Key, Event> {
ret.insert(Key::CtrlY, Event::EvActYank);
ret
}

View file

@ -1,6 +1,7 @@
#![feature(io)]
extern crate libc;
extern crate ncurses;
extern crate getopts;
mod util;
mod item;
mod reader;
@ -29,9 +30,30 @@ use matcher::Matcher;
use model::Model;
use libc::{sigemptyset, sigaddset, sigwait, pthread_sigmask};
use curses::{ColorTheme, Curses};
use getopts::Options;
use std::env;
fn main() {
// option parsing
let args: Vec<String> = env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.optopt("b", "bind", "comma seperated keybindings", "ctrl-j:accept,ctrl-k:kill-line");
opts.optflag("h", "help", "print this help menu");
let options = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => { panic!(f.to_string()) }
};
// print help message
if options.opt_present("h") {
print_usage(&program, opts);
return
}
let theme = curses::ColorTheme::new();
let mut curse = Curses::new();
curse.init(Some(&theme), false, false);
@ -54,6 +76,7 @@ fn main() {
let eb_clone_input = eb.clone();
let mut input = Input::new(eb_clone_input);
input.parse_keymap(options.opt_str("b"));
// register terminal resize event, `pthread_sigmask` should be run before any thread.
let mut sigset = unsafe {mem::uninitialized()};
@ -192,3 +215,8 @@ fn main() {
endwin();
model.output();
}
fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} [options]", program);
print!("{}", opts.usage(&brief));
}