summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2019-01-05 22:54:32 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2019-01-05 22:54:32 -0500
commit9bababf24d2dad7a8d5478cda8f181864d0c3f30 (patch)
tree139f68f2bbaa9ae4d546d33cf55d85b3a53b48d7
parent9216b5fe47e2dddc679c8c8845c4eee874634da4 (diff)
revert back to using keymap.toml
- figured out a way to make things work
-rw-r--r--src/joshuto.rs4
-rw-r--r--src/joshuto/command.rs224
-rw-r--r--src/joshuto/config.rs2
-rw-r--r--src/joshuto/input.rs142
-rw-r--r--src/joshuto/keymap.rs411
-rw-r--r--src/joshuto/mimetype.rs4
-rw-r--r--src/joshuto/theme.rs183
-rw-r--r--src/joshuto/ui.rs12
-rw-r--r--src/joshuto/window.rs9
-rw-r--r--src/main.rs6
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(