diff options
-rw-r--r-- | src/commands/cursor_move.rs | 1 | ||||
-rw-r--r-- | src/commands/file_operations.rs | 15 | ||||
-rw-r--r-- | src/commands/mod.rs | 253 | ||||
-rw-r--r-- | src/config/keymap.rs | 4 | ||||
-rw-r--r-- | src/error.rs | 28 | ||||
-rw-r--r-- | src/run.rs | 4 |
6 files changed, 161 insertions, 144 deletions
diff --git a/src/commands/cursor_move.rs b/src/commands/cursor_move.rs index 049657a..dbea053 100644 --- a/src/commands/cursor_move.rs +++ b/src/commands/cursor_move.rs @@ -3,7 +3,6 @@ use crate::context::JoshutoContext; use crate::error::JoshutoError; use crate::window::JoshutoView; - pub fn cursor_move(mut new_index: usize, context: &mut JoshutoContext, view: &JoshutoView) { let curr_tab = &mut context.tabs[context.curr_tab_index]; diff --git a/src/commands/file_operations.rs b/src/commands/file_operations.rs index bb6df9f..ca0836d 100644 --- a/src/commands/file_operations.rs +++ b/src/commands/file_operations.rs @@ -301,14 +301,15 @@ fn fs_cut_thread( let handle = |process_info: fs_extra::TransitProcess| { let progress_info = ProgressInfo { - bytes_finished: process_info.copied_bytes, - total_bytes: process_info.total_bytes, - }; + bytes_finished: process_info.copied_bytes, + total_bytes: process_info.total_bytes, + }; tx.send(progress_info.clone()).unwrap(); fs_extra::dir::TransitProcessResult::ContinueOrAbort }; - match fs_extra::move_items_with_progress(&cpath, &destination, &options, handle) { + match fs_extra::move_items_with_progress(&cpath, &destination, &options, handle) + { Err(e) => { let err = std::io::Error::new(std::io::ErrorKind::Other, format!("{}", e)); @@ -370,9 +371,9 @@ fn fs_copy_thread( let handle = |process_info: fs_extra::TransitProcess| { let progress_info = ProgressInfo { - bytes_finished: process_info.copied_bytes, - total_bytes: process_info.total_bytes, - }; + bytes_finished: process_info.copied_bytes, + total_bytes: process_info.total_bytes, + }; tx.send(progress_info.clone()).unwrap(); fs_extra::dir::TransitProcessResult::ContinueOrAbort }; diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 2f72640..7108b9f 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -18,7 +18,7 @@ mod tab_switch; pub use self::change_directory::ChangeDirectory; pub use self::cursor_move::{ CursorMoveDown, CursorMoveEnd, CursorMoveHome, CursorMovePageDown, CursorMovePageUp, - CursorMoveUp + CursorMoveUp, }; pub use self::delete_files::DeleteFiles; pub use self::file_operations::{CopyFiles, CutFiles, FileOperationThread, PasteFiles}; @@ -37,11 +37,10 @@ pub use self::tab_operations::{CloseTab, NewTab}; pub use self::tab_switch::TabSwitch; use std::collections::HashMap; -use std::fmt; use std::path::PathBuf; use crate::context::JoshutoContext; -use crate::error::JoshutoError; +use crate::error::{JoshutoError, KeymapError}; use crate::window::JoshutoView; #[derive(Debug)] @@ -58,7 +57,7 @@ pub trait JoshutoRunnable { pub trait JoshutoCommand: JoshutoRunnable + std::fmt::Display + std::fmt::Debug {} impl std::fmt::Display for CommandKeybind { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { CommandKeybind::SimpleKeybind(s) => write!(f, "{}", s), CommandKeybind::CompositeKeybind(_) => write!(f, "..."), @@ -72,68 +71,63 @@ pub struct ProgressInfo { pub total_bytes: u64, } -pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<JoshutoCommand>> { +pub fn from_args( + command: &str, + args: Option<&Vec<String>>, +) -> Result<Box<JoshutoCommand>, KeymapError> { match command { - "cd" => { - if let Some(args) = args { - match wordexp::wordexp(args[0].as_str(), 0) { - Ok(mut exp_strs) => { - if let Some(exp_str) = exp_strs.next() { - let path = PathBuf::from(exp_str); - return Some(Box::new(self::ChangeDirectory::new(path))); - } - } - Err(_) => { - eprintln!("Failed to parse: {:?}", args[0]); - } - } - } - None - } - "close_tab" => Some(Box::new(self::CloseTab::new())), - "copy_files" => Some(Box::new(self::CopyFiles::new())), - "cursor_move_down" => { - if let Some(args) = args { - if !args.is_empty() { - match args[0].parse::<usize>() { - Ok(s) => { - return Some(Box::new(self::CursorMoveUp::new(s))); - } - Err(e) => { - eprintln!("{}", e); - } - } - } - } - None - } - "cursor_move_up" => { - if let Some(args) = args { - if !args.is_empty() { - match args[0].parse::<usize>() { - Ok(s) => { - return Some(Box::new(self::CursorMoveDown::new(s))); - } - Err(e) => { - eprintln!("{}", e); - } + "cd" => match args { + Some(args) if !args.is_empty() => match wordexp::wordexp(args[0].as_str(), 0) { + Ok(mut exp_strs) => match exp_strs.next() { + Some(exp_str) => { + Ok(Box::new(self::ChangeDirectory::new(PathBuf::from(exp_str)))) } - } - } - 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())), - "cut_files" => Some(Box::new(self::CutFiles::new())), - "delete_files" => Some(Box::new(self::DeleteFiles::new())), - "force_quit" => Some(Box::new(self::ForceQuit::new())), - "mkdir" => Some(Box::new(self::NewDirectory::new())), - "new_tab" => Some(Box::new(self::NewTab::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())), + None => Err(KeymapError::new( + Some("cd"), + format!("Failed to parse: {}", args[0]), + )), + }, + Err(_) => Err(KeymapError::new( + Some("cd"), + format!("Failed to parse: {}", args[0]), + )), + }, + _ => match dirs::home_dir() { + Some(s) => Ok(Box::new(self::ChangeDirectory::new(s))), + None => Err(KeymapError::new( + Some("cd"), + String::from("Cannot find home directory"), + )), + }, + }, + "close_tab" => Ok(Box::new(self::CloseTab::new())), + "copy_files" => Ok(Box::new(self::CopyFiles::new())), + "cursor_move_down" => match args { + Some(args) if !args.is_empty() => match args[0].parse::<usize>() { + Ok(s) => Ok(Box::new(self::CursorMoveDown::new(s))), + Err(e) => Err(KeymapError::new(Some("cursor_move_down"), e.to_string())), + }, + _ => Ok(Box::new(self::CursorMoveDown::new(1))), + }, + "cursor_move_up" => match args { + Some(args) if !args.is_empty() => match args[0].parse::<usize>() { + Ok(s) => Ok(Box::new(self::CursorMoveUp::new(s))), + Err(e) => Err(KeymapError::new(Some("cursor_move_up"), e.to_string())), + }, + _ => Ok(Box::new(self::CursorMoveUp::new(1))), + }, + "cursor_move_home" => Ok(Box::new(self::CursorMoveHome::new())), + "cursor_move_end" => Ok(Box::new(self::CursorMoveEnd::new())), + "cursor_move_page_up" => Ok(Box::new(self::CursorMovePageUp::new())), + "cursor_move_page_down" => Ok(Box::new(self::CursorMovePageDown::new())), + "cut_files" => Ok(Box::new(self::CutFiles::new())), + "delete_files" => Ok(Box::new(self::DeleteFiles::new())), + "force_quit" => Ok(Box::new(self::ForceQuit::new())), + "mkdir" => Ok(Box::new(self::NewDirectory::new())), + "new_tab" => Ok(Box::new(self::NewTab::new())), + "open_file" => Ok(Box::new(self::OpenFile::new())), + "open_file_with" => Ok(Box::new(self::OpenFileWith::new())), + "parent_directory" => Ok(Box::new(self::ParentDirectory::new())), "paste_files" => { let mut options = fs_extra::dir::CopyOptions::new(); if let Some(args) = args { @@ -141,50 +135,43 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<Joshut 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); - } + "overwrite" => match splitarg[1].parse::<bool>() { + Ok(s) => options.overwrite = s, + _ => eprintln!("Failed to parse: {}", arg), + }, + "skip_exist" => match splitarg[1].parse::<bool>() { + Ok(s) => options.skip_exist = s, + _ => eprintln!("Failed to parse: {}", arg), + }, + _ => { + return Err(KeymapError::new( + Some("paste_files"), + format!("unknown option {}", arg), + )); } - "skip_exist" => { - if let Ok(s) = splitarg[1].parse::<bool>() { - options.skip_exist = s; - } else { - eprintln!("Failed to parse: {}", arg); - } - } - _ => {} } } } } - Some(Box::new(self::PasteFiles::new(options))) + Ok(Box::new(self::PasteFiles::new(options))) } - "quit" => Some(Box::new(self::Quit::new())), - "reload_dir_list" => Some(Box::new(self::ReloadDirList::new())), + "quit" => Ok(Box::new(self::Quit::new())), + "reload_dir_list" => Ok(Box::new(self::ReloadDirList::new())), "rename_file" => { - let method: RenameFileMethod; - if let Some(args) = args { - if !args.is_empty() { - method = match args[0].as_str() { - "prepend" => self::RenameFileMethod::Prepend, - "overwrite" => self::RenameFileMethod::Overwrite, - "append" => self::RenameFileMethod::Append, - _ => self::RenameFileMethod::Append, - }; - } else { - method = self::RenameFileMethod::Append; - } - } else { - method = self::RenameFileMethod::Append; - } - Some(Box::new(self::RenameFile::new(method))) + let method: RenameFileMethod = match args { + Some(args) if !args.is_empty() => match args[0].as_str() { + "prepend" => self::RenameFileMethod::Prepend, + "overwrite" => self::RenameFileMethod::Overwrite, + "append" => self::RenameFileMethod::Append, + _ => self::RenameFileMethod::Append, + }, + _ => self::RenameFileMethod::Append, + }; + Ok(Box::new(self::RenameFile::new(method))) } - "search" => Some(Box::new(self::Search::new())), - "search_next" => Some(Box::new(self::SearchNext::new())), - "search_prev" => Some(Box::new(self::SearchPrev::new())), + "search" => Ok(Box::new(self::Search::new())), + "search_next" => Ok(Box::new(self::SearchNext::new())), + "search_prev" => Ok(Box::new(self::SearchPrev::new())), "select_files" => { let mut toggle = false; let mut all = false; @@ -193,45 +180,49 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<Joshut 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); + "toggle" => match splitarg[1].parse::<bool>() { + Ok(s) => toggle = s, + _ => { + return Err(KeymapError::new( + Some("select_files"), + format!("unknown option {}", arg), + )); } - } - "all" => { - if let Ok(s) = splitarg[1].parse::<bool>() { - all = s; - } else { - eprintln!("Failed to parse: {}", arg); + }, + "all" => match splitarg[1].parse::<bool>() { + Ok(s) => all = s, + _ => { + return Err(KeymapError::new( + Some("select_files"), + format!("unknown option {}", arg), + )); } + }, + _ => { + return Err(KeymapError::new( + Some("select_files"), + format!("unknown option {}", arg), + )); } - _ => {} - } - } - } - } - Some(Box::new(self::SelectFiles::new(toggle, all))) - } - "set_mode" => Some(Box::new(self::SetMode::new())), - "tab_switch" => { - if let Some(args) = args { - if !args.is_empty() { - match args[0].parse::<i32>() { - Ok(s) => { - return Some(Box::new(self::TabSwitch::new(s))); - } - Err(e) => { - eprintln!("{}", e); } } } } - None + Ok(Box::new(self::SelectFiles::new(toggle, all))) } - "toggle_hidden" => Some(Box::new(self::ToggleHiddenFiles::new())), - _ => None, + "set_mode" => Ok(Box::new(self::SetMode::new())), + "tab_switch" => match args { + Some(args) if !args.is_empty() => match args[0].parse::<i32>() { + Ok(s) => Ok(Box::new(self::TabSwitch::new(s))), + Err(e) => Err(KeymapError::new(Some("tab_switch"), e.to_string())), + }, + _ => Err(KeymapError::new( + Some("tab_switch"), + String::from("No option provided"), + )), + }, + "toggle_hidden" => Ok(Box::new(self::ToggleHiddenFiles::new())), + inp @ _ => Err(KeymapError::new(None, format!("Unknown command: {}", inp))), } } diff --git a/src/config/keymap.rs b/src/config/keymap.rs index 9fb2e7d..4b4e64d 100644 --- a/src/config/keymap.rs +++ b/src/config/keymap.rs @@ -32,8 +32,8 @@ impl Flattenable<JoshutoKeymap> for JoshutoRawKeymap { if let Some(maps) = self.mapcommand { for mapcommand in maps { match commands::from_args(mapcommand.command.as_str(), mapcommand.args.as_ref()) { - Some(command) => insert_keycommand(&mut keymaps, command, &mapcommand.keys[..]), - None => eprintln!("Unknown command: {}", mapcommand.command), + Ok(command) => insert_keycommand(&mut keymaps, command, &mapcommand.keys[..]), + Err(e) => eprintln!("{}", e), } } } diff --git a/src/error.rs b/src/error.rs index a964132..bae1e0c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,31 @@ pub enum JoshutoError { IO(std::io::Error), } + +/* +pub enum KeymapErrorKind { + Parse, + UnknownArgument, + UnknownCommand, +} +*/ + +pub struct KeymapError { + pub command: Option<&'static str>, + pub error: String, +} + +impl KeymapError { + pub fn new(command: Option<&'static str>, error: String) -> Self { + KeymapError { command, error } + } +} + +impl std::fmt::Display for KeymapError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self.command { + Some(s) => write!(f, "{}: {}", s, self.error), + None => write!(f, "{}", self.error), + } + } +} @@ -193,9 +193,7 @@ pub fn run(config_t: config::JoshutoConfig, keymap_t: config::JoshutoKeymap) { match keymap_t.keymaps.get(&ch) { Some(CommandKeybind::CompositeKeybind(m)) => match recurse_get_keycommand(&m) { - Some(s) => { - keycommand = s; - } + Some(s) => keycommand = s, None => continue, }, Some(CommandKeybind::SimpleKeybind(s)) => { |