diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-01-05 22:54:32 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2019-01-05 22:54:32 -0500 |
commit | 9bababf24d2dad7a8d5478cda8f181864d0c3f30 (patch) | |
tree | 139f68f2bbaa9ae4d546d33cf55d85b3a53b48d7 | |
parent | 9216b5fe47e2dddc679c8c8845c4eee874634da4 (diff) |
revert back to using keymap.toml
- figured out a way to make things work
-rw-r--r-- | src/joshuto.rs | 4 | ||||
-rw-r--r-- | src/joshuto/command.rs | 224 | ||||
-rw-r--r-- | src/joshuto/config.rs | 2 | ||||
-rw-r--r-- | src/joshuto/input.rs | 142 | ||||
-rw-r--r-- | src/joshuto/keymap.rs | 411 | ||||
-rw-r--r-- | src/joshuto/mimetype.rs | 4 | ||||
-rw-r--r-- | src/joshuto/theme.rs | 183 | ||||
-rw-r--r-- | src/joshuto/ui.rs | 12 | ||||
-rw-r--r-- | src/joshuto/window.rs | 9 | ||||
-rw-r--r-- | src/main.rs | 6 |
10 files changed, 523 insertions, 474 deletions
diff --git a/src/joshuto.rs b/src/joshuto.rs index d33dbf4..3d99184 100644 --- a/src/joshuto.rs +++ b/src/joshuto.rs @@ -12,6 +12,7 @@ use std::thread; pub mod config; pub mod keymap; pub mod mimetype; +pub mod theme; mod command; mod history; mod input; @@ -253,7 +254,7 @@ pub fn run(config_t: config::JoshutoConfig, } if tabs[index].threads.len() > 0 { - ncurses::timeout(0); + ncurses::timeout(2); } else { ncurses::timeout(-1); } @@ -325,4 +326,5 @@ pub fn run(config_t: config::JoshutoConfig, } keycommand.execute(&mut tabs[index]); } + ncurses::endwin(); } diff --git a/src/joshuto/command.rs b/src/joshuto/command.rs index 0c44556..65b0695 100644 --- a/src/joshuto/command.rs +++ b/src/joshuto/command.rs @@ -106,125 +106,129 @@ pub fn split_shell_style(line: &String) -> Vec<&str> } -pub fn from_args(args: &[&str]) -> Option<Box<dyn JoshutoCommand>> +pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<dyn JoshutoCommand>> { - let args_len = args.len(); - - if args_len == 0 { - return None; - } - - match args[0] { - "quit" => Some(Box::new(self::Quit::new())), - "parent_directory" => Some(Box::new(self::ParentDirectory::new())), - - "open_file" => Some(Box::new(self::OpenFile::new())), - "open_file_with" => Some(Box::new(self::OpenFileWith::new())), - "cd" => { - if args_len > 1 { - let path = path::PathBuf::from(args[1]); - Some(Box::new(self::ChangeDirectory::new(path))) - } else { - None + match args { + None => { + match command { + "quit" => Some(Box::new(self::Quit::new())), + "open_file" => Some(Box::new(self::OpenFile::new())), + "open_file_with" => Some(Box::new(self::OpenFileWith::new())), + "parent_directory" => Some(Box::new(self::ParentDirectory::new())), + "cursor_move_home" => Some(Box::new(self::CursorMoveHome::new())), + "cursor_move_end" => Some(Box::new(self::CursorMoveEnd::new())), + "cursor_move_page_up" => Some(Box::new(self::CursorMovePageUp::new())), + "cursor_move_page_down" => Some(Box::new(self::CursorMovePageDown::new())), + + "toggle_hidden" => Some(Box::new(self::ToggleHiddenFiles::new())), + + "cut_files" => Some(Box::new(self::CutFiles::new())), + "copy_files" => Some(Box::new(self::CopyFiles::new())), + "delete_files" => Some(Box::new(self::DeleteFiles::new())), + "rename_file" => Some(Box::new(self::RenameFile::new(self::RenameFileMethod::Append))), + + "mkdir" => Some(Box::new(self::NewDirectory::new())), + "search" => Some(Box::new(self::Search::new())), + _ => None, } }, - - "cursor_move" => { - if args_len > 1 { - match args[1].parse::<i32>() { - Ok(s) => { - Some(Box::new(self::CursorMove::new(s))) - }, - Err(e) => { - eprintln!("{}", e); + Some(args) => { + let args_len = args.len(); + + match command { + "cd" => { + if args_len > 0 { + let path = path::PathBuf::from(args[0].as_str()); + Some(Box::new(self::ChangeDirectory::new(path))) + } else { None - }, - } - } else { - None - } - }, - "cursor_move_home" => Some(Box::new(self::CursorMoveHome::new())), - "cursor_move_end" => Some(Box::new(self::CursorMoveEnd::new())), - "cursor_move_page_up" => Some(Box::new(self::CursorMovePageUp::new())), - "cursor_move_page_down" => Some(Box::new(self::CursorMovePageDown::new())), - - "toggle_hidden" => Some(Box::new(self::ToggleHiddenFiles::new())), - - "cut_files" => Some(Box::new(self::CutFiles::new())), - "copy_files" => Some(Box::new(self::CopyFiles::new())), - "paste_files" => { - let mut options = fs_extra::dir::CopyOptions::new(); - for arg in &args[1..] { - let splitarg: Vec<&str> = arg.split('=').collect(); - if splitarg.len() == 2 { - match splitarg[0] { - "overwrite" => { - if let Ok(s) = splitarg[1].parse::<bool>() { - options.overwrite = s; - } else { - eprintln!("Failed to parse: {}", arg); - } - }, - "skip_exist" => { - if let Ok(s) = splitarg[1].parse::<bool>() { - options.skip_exist = s; - } else { - eprintln!("Failed to parse: {}", arg); + } + }, + "cursor_move" => { + if args_len > 0 { + match args[0].parse::<i32>() { + Ok(s) => { + Some(Box::new(self::CursorMove::new(s))) + }, + Err(e) => { + eprintln!("{}", e); + None + }, + } + } else { + None + } + }, + "paste_files" => { + let mut options = fs_extra::dir::CopyOptions::new(); + for arg in args { + let splitarg: Vec<&str> = arg.split('=').collect(); + if splitarg.len() == 2 { + match splitarg[0] { + "overwrite" => { + if let Ok(s) = splitarg[1].parse::<bool>() { + options.overwrite = s; + } else { + eprintln!("Failed to parse: {}", arg); + } + }, + "skip_exist" => { + if let Ok(s) = splitarg[1].parse::<bool>() { + options.skip_exist = s; + } else { + eprintln!("Failed to parse: {}", arg); + } + }, + _ => {}, } - }, - _ => {}, + } + } + let paste = self::PasteFiles::new(options); + Some(Box::new(paste)) + }, + "rename_file" => { + let method: self::file_operation::RenameFileMethod; + if args_len > 0 { + method = match args[0].as_str() { + "prepend" => self::RenameFileMethod::Prepend, + "overwrite" => self::RenameFileMethod::Overwrite, + "append" => self::RenameFileMethod::Append, + _ => self::RenameFileMethod::Append, + }; + Some(Box::new(self::RenameFile::new(method))) + } else { + None } } - } - let paste = self::PasteFiles::new(options); - Some(Box::new(paste)) - } - "delete_files" => Some(Box::new(self::DeleteFiles::new())), - "rename_file" => { - let method: self::file_operation::RenameFileMethod; - if args_len == 1 { - method = self::RenameFileMethod::Append; - } else { - method = match args[1] { - "prepend" => self::RenameFileMethod::Prepend, - "overwrite" => self::RenameFileMethod::Overwrite, - "append" => self::RenameFileMethod::Append, - _ => self::RenameFileMethod::Append, - } - } - Some(Box::new(self::RenameFile::new(method))) - } - "mkdir" => Some(Box::new(self::NewDirectory::new())), - "search" => Some(Box::new(self::Search::new())), - "select_files" => { - let mut toggle = false; - let mut all = false; - for arg in &args[1..] { - let splitarg: Vec<&str> = arg.split('=').collect(); - if splitarg.len() == 2 { - match splitarg[0] { - "toggle" => { - if let Ok(s) = splitarg[1].parse::<bool>() { - toggle = s; - } else { - eprintln!("Failed to parse: {}", arg); + "select_files" => { + let mut toggle = false; + let mut all = false; + for arg in args { + let splitarg: Vec<&str> = arg.split('=').collect(); + if splitarg.len() == 2 { + match splitarg[0] { + "toggle" => { + if let Ok(s) = splitarg[1].parse::<bool>() { + toggle = s; + } else { + eprintln!("Failed to parse: {}", arg); + } + }, + "all" => { + if let Ok(s) = splitarg[1].parse::<bool>() { + all = s; + } else { + eprintln!("Failed to parse: {}", arg); + } + }, + _ => {}, } - }, - "all" => { - if let Ok(s) = splitarg[1].parse::<bool>() { - all = s; - } else { - eprintln!("Failed to parse: {}", arg); - } - }, - _ => {}, + } } - } + Some(Box::new(self::SelectFiles::new(toggle, all))) + }, + _ => None, } - Some(Box::new(self::SelectFiles::new(toggle, all))) - } - - _ => None, + }, } } diff --git a/src/joshuto/config.rs b/src/joshuto/config.rs index 9c17c59..5545013 100644 --- a/src/joshuto/config.rs +++ b/src/joshuto/config.rs @@ -144,7 +144,7 @@ impl JoshutoConfig { pub fn get_config() -> Self { - match JoshutoConfig::read_config() { + match Self::read_config() { Some(config) => { config.flatten() } diff --git a/src/joshuto/input.rs b/src/joshuto/input.rs index 4694af7..4c35261 100644 --- a/src/joshuto/input.rs +++ b/src/joshuto/input.rs @@ -1,8 +1,12 @@ extern crate ncurses; extern crate wcwidth; +use std::collections::HashMap; + +use joshuto::command; use joshuto::keymap; use joshuto::window; +use joshuto::keymap::*; pub fn get_str(win: &window::JoshutoPanel, coord: (i32, i32)) -> Option<String> @@ -135,5 +139,143 @@ pub fn get_str_prefill(win: &window::JoshutoPanel, let user_str: String = user_input.iter().map(|(_, ch)| ch).collect(); return Some(user_str); +} + + +pub fn initialize_default_keymap() -> HashMap<i32, command::CommandKeybind> +{ + let mut keymaps: HashMap<i32, command::CommandKeybind> = HashMap::new(); + + // quit + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::Quit::new())); + keymaps.insert('q' as i32, command); + + // up + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMove::new(-1))); + keymaps.insert(ncurses::KEY_UP, command); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMove::new(-1))); + keymaps.insert('k' as i32, command); + + // down + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMove::new(1))); + keymaps.insert(ncurses::KEY_DOWN, command); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMove::new(1))); + keymaps.insert('j' as i32, command); + + // left + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::ParentDirectory::new())); + keymaps.insert(ncurses::KEY_LEFT, command); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::ParentDirectory::new())); + keymaps.insert('h' as i32, command); + + // right + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::OpenFile::new())); + keymaps.insert(ncurses::KEY_RIGHT, command); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::OpenFile::new())); + keymaps.insert('l' as i32, command); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::OpenFile::new())); + keymaps.insert(ENTER, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::OpenFileWith::new())); + keymaps.insert('r' as i32, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMovePageUp::new())); + keymaps.insert(ncurses::KEY_PPAGE, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMovePageDown::new())); + keymaps.insert(ncurses::KEY_NPAGE, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMoveHome::new())); + keymaps.insert(ncurses::KEY_HOME, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CursorMoveEnd::new())); + keymaps.insert(ncurses::KEY_END, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::DeleteFiles::new())); + keymaps.insert(ncurses::KEY_DC, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::RenameFile::new(command::RenameFileMethod::Append))); + keymaps.insert('a' as i32, command); + + { + let mut subkeymap: HashMap<i32, command::CommandKeybind> = HashMap::new(); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::ToggleHiddenFiles::new())); + subkeymap.insert('h' as i32, command); + + let command = command::CommandKeybind::CompositeKeybind(subkeymap); + keymaps.insert('z' as i32, command); + } + + { + let mut subkeymap: HashMap<i32, command::CommandKeybind> = HashMap::new(); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CutFiles::new())); + subkeymap.insert('d' as i32, command); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::DeleteFiles::new())); + subkeymap.insert('D' as i32, command); + + let command = command::CommandKeybind::CompositeKeybind(subkeymap); + keymaps.insert('d' as i32, command); + } + + { + let mut subkeymap: HashMap<i32, command::CommandKeybind> = HashMap::new(); + + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::CopyFiles::new())); + subkeymap.insert('y' as i32, command); + + let command = command::CommandKeybind::CompositeKeybind(subkeymap); + keymaps.insert('y' as i32, command); + } + + { + let mut subkeymap: HashMap<i32, command::CommandKeybind> = HashMap::new(); + + let options = fs_extra::dir::CopyOptions::new(); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::PasteFiles::new(options))); + subkeymap.insert('p' as i32, command); + + let mut options = fs_extra::dir::CopyOptions::new(); + options.overwrite = true; + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::PasteFiles::new(options))); + subkeymap.insert('o' as i32, command); + + let command = command::CommandKeybind::CompositeKeybind(subkeymap); + keymaps.insert('p' as i32, command); + } + + { + let mut subkeymap: HashMap<i32, command::CommandKeybind> = HashMap::new(); + let command = command::CommandKeybind::SimpleKeybind( + Box::new(command::NewDirectory::new())); + subkeymap.insert('k' as i32, command); + + let command = command::CommandKeybind::CompositeKeybind(subkeymap); + keymaps.insert('m' as i32, command); + } + keymaps } diff --git a/src/joshuto/keymap.rs b/src/joshuto/keymap.rs index 8623624..dec5ab5 100644 --- a/src/joshuto/keymap.rs +++ b/src/joshuto/keymap.rs @@ -1,4 +1,5 @@ extern crate fs_extra; +extern crate toml; extern crate xdg; use std::collections::HashMap; @@ -8,13 +9,7 @@ use std::io::BufRead; use std::process; use joshuto::command; -use joshuto::command::*; - -const MAP_COMMAND: &str = "map"; -// const ALIAS_COMMAND: &str = "alias"; -// const NEWTAB_COMMAND: &str = "newtab"; - -const COMMENT_DELIMITER: char = '#'; +use joshuto::input; pub const BACKSPACE: i32 = 0x7F; pub const TAB: i32 = 0x9; @@ -23,292 +18,72 @@ pub const ESCAPE: i32 = 0x1B; /* #define KEY_ALT(x) KEY_F(60) + (x - 'A') */ -#[derive(Debug)] -pub struct JoshutoKeymap { - pub keymaps: HashMap<i32, CommandKeybind>, +#[derive(Debug, Deserialize)] +struct JoshutoMapCommand { + pub keys: Vec<String>, + pub command: String, + pub args: Option<Vec<String>>, } -impl JoshutoKeymap { - pub fn new() -> Self - { - let mut keymaps: HashMap<i32, CommandKeybind> = HashMap::new(); - - // quit - let command = CommandKeybind::SimpleKeybind( - Box::new(command::Quit::new())); - keymaps.insert('q' as i32, command); - - // up - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMove::new(-1))); - keymaps.insert(ncurses::KEY_UP, command); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMove::new(-1))); - keymaps.insert('k' as i32, command); - - // down - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMove::new(1))); - keymaps.insert(ncurses::KEY_DOWN, command); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMove::new(1))); - keymaps.insert('j' as i32, command); - - // left - let command = CommandKeybind::SimpleKeybind( - Box::new(command::ParentDirectory::new())); - keymaps.insert(ncurses::KEY_LEFT, command); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::ParentDirectory::new())); - keymaps.insert('h' as i32, command); - - // right - let command = CommandKeybind::SimpleKeybind( - Box::new(command::OpenFile::new())); - keymaps.insert(ncurses::KEY_RIGHT, command); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::OpenFile::new())); - keymaps.insert('l' as i32, command); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::OpenFile::new())); - keymaps.insert(ENTER, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::OpenFileWith::new())); - keymaps.insert('r' as i32, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMovePageUp::new())); - keymaps.insert(ncurses::KEY_PPAGE, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMovePageDown::new())); - keymaps.insert(ncurses::KEY_NPAGE, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMoveHome::new())); - keymaps.insert(ncurses::KEY_HOME, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CursorMoveEnd::new())); - keymaps.insert(ncurses::KEY_END, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::DeleteFiles::new())); - keymaps.insert(ncurses::KEY_DC, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::RenameFile::new(command::RenameFileMethod::Append))); - keymaps.insert('a' as i32, command); - - { - let mut subkeymap: HashMap<i32, CommandKeybind> = HashMap::new(); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::ToggleHiddenFiles::new())); - subkeymap.insert('h' as i32, command); - - let command = CommandKeybind::CompositeKeybind(subkeymap); - keymaps.insert('z' as i32, command); - } - - { - let mut subkeymap: HashMap<i32, CommandKeybind> = HashMap::new(); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CutFiles::new())); - subkeymap.insert('d' as i32, command); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::DeleteFiles::new())); - subkeymap.insert('D' as i32, command); - - let command = CommandKeybind::CompositeKeybind(subkeymap); - keymaps.insert('d' as i32, command); - } - - { - let mut subkeymap: HashMap<i32, CommandKeybind> = HashMap::new(); - - let command = CommandKeybind::SimpleKeybind( - Box::new(command::CopyFiles::new())); - subkeymap.insert('y' as i32, command); - - let command = CommandKeybind::CompositeKeybind(subkeymap); - keymaps.insert('y' as i32, command); - } - - { - let mut subkeymap: HashMap<i32, CommandKeybind> = HashMap::new(); - - let options = fs_extra::dir::CopyOptions::new(); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::PasteFiles::new(options))); - subkeymap.insert('p' as i32, command); - - let mut options = fs_extra::dir::CopyOptions::new(); - options.overwrite = true; - let command = CommandKeybind::SimpleKeybind( - Box::new(command::PasteFiles::new(options))); - subkeymap.insert('o' as i32, command); - let command = CommandKeybind::CompositeKeybind(subkeymap); - keymaps.insert('p' as i32, command); - } - - { - let mut subkeymap: HashMap<i32, CommandKeybind> = HashMap::new(); - let command = CommandKeybind::SimpleKeybind( - Box::new(command::NewDirectory::new())); - subkeymap.insert('k' as i32, command); - - let command = CommandKeybind::CompositeKeybind(subkeymap); - keymaps.insert('m' as i32, command); - } +#[derive(Debug, Deserialize)] +struct JoshutoRawKeymap { + mapcommand: Option<Vec<JoshutoMapCommand>>, +} - JoshutoKeymap { - keymaps, - } - } +impl JoshutoRawKeymap { - pub fn from_str(keycode: &str) -> Option<i32> + pub fn flatten(self) -> JoshutoKeymap { - if keycode.len() == 1 { - for ch in keycode.chars() { - if ch.is_ascii() { - return Some(ch as i32); + let mut keymaps: HashMap<i32, command::CommandKeybind> = HashMap::new(); + if let Some(maps) = self.mapcommand { + for mapcommand in maps { + match command::from_args(mapcommand.command.as_str(), mapcommand.args.as_ref()) { + Some(command) => { + insert_keycommand(&mut keymaps, command, &mapcommand.keys[..]); + }, + None => { + println!("Unknown command: {}", mapcommand.command); + } } } - return None; - } else { - match keycode { - "Comma" => Some(',' as i32), - "Tab" => Some(TAB), - "Space" => Some(' ' as i32), - "Backspace" => Some(BACKSPACE), - "Delete" => Some(ncurses::KEY_DC), - "Enter" => Some(ENTER), - "Escape" => Some(ESCAPE), - - - "F0" => Some(ncurses::KEY_F0), - "F1" => Some(ncurses::KEY_F1), - "F2" => Some(ncurses::KEY_F2), - "F3" => Some(ncurses::KEY_F3), - "F4" => Some(ncurses::KEY_F4), - "F5" => Some(ncurses::KEY_F5), - "F6" => Some(ncurses::KEY_F6), - "F7" => Some(ncurses::KEY_F7), - "F8" => Some(ncurses::KEY_F8), - "F9" => Some(ncurses::KEY_F9), - "F10" => Some(ncurses::KEY_F10), - "F11" => Some(ncurses::KEY_F11), - "F12" => Some(ncurses::KEY_F12), - "F13" => Some(ncurses::KEY_F13), - "F14" => Some(ncurses::KEY_F14), - "F15" => Some(ncurses::KEY_F15), - - "Insert" => Some(ncurses::KEY_IC), /* insert-character key */ - "PageUp" => Some(ncurses::KEY_PPAGE), /* next-page key */ - "PageDown" => Some(ncurses::KEY_NPAGE), /* previous-page key */ - "PrintScreen" => Some(ncurses::KEY_PRINT), /* print key */ - - "Up" => Some(ncurses::KEY_UP), - "Down" => Some(ncurses::KEY_DOWN), - "Left" => Some(ncurses::KEY_LEFT), - "Right" => Some(ncurses::KEY_RIGHT), - "Home" => Some(ncurses::KEY_HOME), - "End" => Some(ncurses::KEY_END), - _ => None, - } } - } - - fn insert_keycommand(map: &mut HashMap<i32, CommandKeybind>, - keycommand: Box<dyn JoshutoCommand>, keys: &[&str]) - { - if keys.len() == 1 { - match Self::from_str(keys[0]) { - Some(s) => { - map.insert(s, CommandKeybind::SimpleKeybind(keycommand)); - }, - None => {} - } - } else { - match Self::from_str(keys[0]) { - Some(s) => { - let mut new_map: HashMap<i32, CommandKeybind>; - match map.remove(&s) { - Some(CommandKeybind::CompositeKeybind(mut m)) => { - new_map = m; - }, - Some(_) => { - eprintln!("Error: Keybindings ambiguous"); - process::exit(1); - }, - None => { - new_map = HashMap::new(); - } - } - JoshutoKeymap::insert_keycommand(&mut new_map, keycommand, &keys[1..]); - let composite_command = CommandKeybind::CompositeKeybind(new_map); - map.insert(s as i32, composite_command); - }, - None => {} - } + JoshutoKeymap { + keymaps, } } +} - fn parse_line(map: &mut HashMap<i32, CommandKeybind>, line: String) - { - let mut line = line; - { - if let Some(trunc_index) = line.find(COMMENT_DELIMITER) { - line.truncate(trunc_index as usize); - } - } - if line.len() == 0 { - return; - } - line.push('\n'); - - let args: Vec<&str> = command::split_shell_style(&line); - - if args.len() == 0 { - return; - } +#[derive(Debug)] +pub struct JoshutoKeymap { + pub keymaps: HashMap<i32, command::CommandKeybind>, +} - match args[0] { - MAP_COMMAND => { - let keys_vec: Vec<&str> = args[1].split(',').collect(); - match command::from_args(&args[2..]) { - Some(command) => { - JoshutoKeymap::insert_keycommand(map, command, &keys_vec[..]); - }, - None => { - println!("Unknown command: {}", args[2]); - }, - } - }, - _ => eprintln!("Error: Unknown command: {}", args[0]), +impl JoshutoKeymap { + pub fn new() -> Self + { + let keymaps = input::initialize_default_keymap(); + JoshutoKeymap { + keymaps, } } - fn read_config() -> Option<JoshutoKeymap> + fn read_config() -> Option<JoshutoRawKeymap> { match xdg::BaseDirectories::with_profile(::PROGRAM_NAME, "") { Ok(dirs) => { let config_path = dirs.find_config_file(::KEYMAP_FILE)?; - match fs::File::open(config_path) { - Ok(f) => { - let mut keymaps: HashMap<i32, CommandKeybind> = HashMap::new(); - let mut reader = io::BufReader::new(f); - for line in reader.lines() { - if let Ok(mut line) = line { - JoshutoKeymap::parse_line(&mut keymaps, line); - } + match fs::read_to_string(&config_path) { + Ok(config_contents) => { + match toml::from_str(&config_contents) { + Ok(config) => { + Some(config) + }, + Err(e) => { + eprintln!("{}", e); + process::exit(1); + }, } - Some(JoshutoKeymap { - keymaps, - }) }, Err(e) => { eprintln!("{}", e); @@ -327,7 +102,7 @@ impl JoshutoKeymap { { match JoshutoKeymap::read_config() { Some(config) => { - config + config.flatten() } None => { JoshutoKeymap::new() @@ -335,3 +110,93 @@ impl JoshutoKeymap { } } } + + +fn insert_keycommand(map: &mut HashMap<i32, command::CommandKeybind>, + keycommand: Box<dyn command::JoshutoCommand>, keys: &[String]) +{ + if keys.len() == 1 { + match key_to_i32(&keys[0]) { + Some(s) => { + map.insert(s, command::CommandKeybind::SimpleKeybind(keycommand)); + }, + None => {} + } + } else { + match key_to_i32(&keys[0]) { + Some(s) => { + let mut new_map: HashMap<i32, command::CommandKeybind>; + match map.remove(&s) { + Some(command::CommandKeybind::CompositeKeybind(mut m)) => { + new_map = m; + }, + Some(_) => { + eprintln!("Error: Keybindings ambiguous"); + process::exit(1); + }, + None => { + new_map = HashMap::new(); + } + } + insert_keycommand(&mut new_map, keycommand, &keys[1..]); + let composite_command = command::CommandKeybind::CompositeKeybind(new_map); + map.insert(s as i32, composite_command); + }, + None => {} + } + } +} + + +pub fn key_to_i32(keycode: &str) -> Option<i32> +{ + if keycode.len() == 1 { + for ch in keycode.chars() { + if ch.is_ascii() { + return Some(ch as i32); + } + } + return None; + } else { + match keycode { + "Comma" => Some(',' as i32), + "Tab" => Some(TAB), + "Space" => Some(' ' as i32), + "Backspace" => Some(BACKSPACE), + "Delete" => Some(ncurses::KEY_DC), + "Enter" => Some(ENTER), + "Escape" => Some(ESCAPE), + + + "F0" => Some(ncurses::KEY_F0), + "F1" => Some(ncurses::KEY_F1), + "F2" => Some(ncurses::KEY_F2), + "F3" => Some(ncurses::KEY_F3), + "F4" => Some(ncurses::KEY_F4), + "F5" => Some(ncurses::KEY_F5), + "F6" => Some(ncurses::KEY_F6), + "F7" => Some(ncurses::KEY_F7), + "F8" => Some(ncurses::KEY_F8), + "F9" => Some(ncurses::KEY_F9), + "F10" => Some(ncurses::KEY_F10), + "F11" => Some(ncurses::KEY_F11), + "F12" => Some(ncurses::KEY_F12), + "F13" => Some(ncurses::KEY_F13), + "F14" => Some( |