diff options
author | Caleb Bassi <calebjbassi@gmail.com> | 2019-02-15 04:43:09 -0800 |
---|---|---|
committer | Caleb Bassi <calebjbassi@gmail.com> | 2019-02-15 05:56:09 -0800 |
commit | 29b3922f9efb9f277641a63f8f1719a15cbb8d16 (patch) | |
tree | d919ba11fa5c754565c64c43cb1614f7ae4d2546 /src/commands/mod.rs | |
parent | 3853eef2d052460982903038daac7abd2b71d12e (diff) |
refactor: project layout
Diffstat (limited to 'src/commands/mod.rs')
-rw-r--r-- | src/commands/mod.rs | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..954dbdc --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,270 @@ +extern crate wordexp; + +mod change_directory; +mod cursor_move; +mod delete_files; +mod file_operations; +mod new_directory; +mod open_file; +mod parent_directory; +mod quit; +mod reload_dir; +mod rename_file; +mod search; +mod selection; +mod set_mode; +mod show_hidden; +mod tab_operations; +mod tab_switch; + +pub use self::change_directory::ChangeDirectory; +pub use self::cursor_move::{ + CursorMove, CursorMoveEnd, CursorMoveHome, CursorMovePageDown, CursorMovePageUp, +}; +pub use self::delete_files::DeleteFiles; +pub use self::file_operations::{CopyFiles, CutFiles, FileOperationThread, PasteFiles}; +pub use self::new_directory::NewDirectory; +pub use self::open_file::{OpenFile, OpenFileWith}; +pub use self::parent_directory::ParentDirectory; +pub use self::quit::Quit; +pub use self::reload_dir::ReloadDirList; +pub use self::rename_file::{RenameFile, RenameFileMethod}; +pub use self::search::Search; +pub use self::selection::SelectFiles; +pub use self::set_mode::SetMode; +pub use self::show_hidden::ToggleHiddenFiles; +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 context::JoshutoContext; +use structs; + +#[derive(Debug)] +pub enum CommandKeybind { + SimpleKeybind(Box<dyn JoshutoCommand>), + CompositeKeybind(HashMap<i32, CommandKeybind>), +} + +pub trait JoshutoRunnable { + fn execute(&self, context: &mut JoshutoContext); +} + +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 { + match self { + CommandKeybind::SimpleKeybind(s) => write!(f, "{}", s), + CommandKeybind::CompositeKeybind(_) => write!(f, "..."), + } + } +} + +#[derive(Clone, Debug)] +pub struct ProgressInfo { + pub bytes_finished: u64, + pub total_bytes: u64, +} + +pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<dyn JoshutoCommand>> { + match command { + "cd" => { + if let Some(args) = args { + match wordexp::wordexp(args[0].as_str(), 0) { + Ok(exp_strs) => { + for exp_str in exp_strs { + let path = PathBuf::from(exp_str); + return Some(Box::new(self::ChangeDirectory::new(path))); + } + } + Err(_) => { + eprintln!("Failed to parse: {:?}", args[0]); + } + } + } + return None; + } + "close_tab" => Some(Box::new(self::CloseTab::new())), + "copy_files" => Some(Box::new(self::CopyFiles::new())), + "cursor_move" => { + if let Some(args) = args { + if args.len() > 0 { + match args[0].parse::<i32>() { + Ok(s) => { + return Some(Box::new(self::CursorMove::new(s))); + } + Err(e) => { + eprintln!("{}", e); + } + } + } + } + return 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())), + "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())), + "paste_files" => { + let mut options = fs_extra::dir::CopyOptions::new(); + if let Some(args) = args { + 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)) + } + "quit" => Some(Box::new(self::Quit::new())), + "reload_dir_list" => Some(Box::new(self::ReloadDirList::new())), + "rename_file" => { + let method: RenameFileMethod; + if let Some(args) = args { + 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, + }; + } else { + method = self::RenameFileMethod::Append; + } + } else { + method = self::RenameFileMethod::Append; + } + Some(Box::new(self::RenameFile::new(method))) + } + "search" => Some(Box::new(self::Search::new())), + "select_files" => { + let mut toggle = false; + let mut all = false; + if let Some(args) = args { + 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); + } + } + _ => {} + } + } + } + } + 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.len() > 0 { + match args[0].parse::<i32>() { + Ok(s) => { + return Some(Box::new(self::TabSwitch::new(s))); + } + Err(e) => { + eprintln!("{}", e); + } + } + } + } + return None; + } + "toggle_hidden" => Some(Box::new(self::ToggleHiddenFiles::new())), + _ => None, + } +} + +pub fn collect_selected_paths(dirlist: &structs::JoshutoDirList) -> Option<Vec<PathBuf>> { + if dirlist.index < 0 { + return None; + } + + let selected: Vec<PathBuf> = dirlist + .contents + .iter() + .filter(|entry| entry.selected) + .map(|entry| entry.path.clone()) + .collect(); + if selected.len() > 0 { + Some(selected) + } else { + Some(vec![dirlist.contents[dirlist.index as usize].path.clone()]) + } +} + +#[allow(dead_code)] +pub fn split_shell_style(line: &String) -> Vec<&str> { + let mut args: Vec<&str> = Vec::new(); + let mut char_ind = line.char_indices(); + + while let Some((i, ch)) = char_ind.next() { + if ch.is_whitespace() { + continue; + } + if ch == '\'' { + while let Some((j, ch)) = char_ind.next() { + if ch == '\'' { + args.push(&line[i + 1..j]); + break; + } + } + } else if ch == '"' { + while let Some((j, ch)) = char_ind.next() { + if ch == '"' { + args.push(&line[i + 1..j]); + break; + } + } + } else { + while let Some((j, ch)) = char_ind.next() { + if ch.is_whitespace() { + args.push(&line[i..j]); + break; + } + } + } + } + args +} |