summaryrefslogtreecommitdiffstats
path: root/src/commands/key_command.rs
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2020-09-19 21:21:33 -0400
committerJiayi Zhao <jeff.no.zhao@gmail.com>2020-09-19 21:21:33 -0400
commit7b4c611ed4d804bd52aeda0a619a54bea9b1e13d (patch)
tree7ba31fff7d5de171aadfc32c67f81dd64428b3ba /src/commands/key_command.rs
parent7741d4d2c8798ad0bb609e97fb3bda86c5318a36 (diff)
Change command to use an enum instead of polymorphism
Diffstat (limited to 'src/commands/key_command.rs')
-rw-r--r--src/commands/key_command.rs347
1 files changed, 347 insertions, 0 deletions
diff --git a/src/commands/key_command.rs b/src/commands/key_command.rs
new file mode 100644
index 0000000..c493069
--- /dev/null
+++ b/src/commands/key_command.rs
@@ -0,0 +1,347 @@
+use std::path;
+
+use crate::context::JoshutoContext;
+use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult};
+use crate::io::IOWorkerOptions;
+use crate::ui::TuiBackend;
+use crate::util::load_child::LoadChild;
+use crate::util::sort::SortType;
+
+use crate::HOME_DIR;
+
+use super::*;
+
+#[derive(Clone, Debug)]
+pub enum KeyCommand {
+ BulkRename,
+ ChangeDirectory(path::PathBuf),
+ CommandLine(String, String),
+
+ CutFiles,
+ CopyFiles,
+ PasteFiles(IOWorkerOptions),
+
+ CursorMoveUp(usize),
+ CursorMoveDown(usize),
+ CursorMoveHome,
+ CursorMoveEnd,
+ CursorMovePageUp,
+ CursorMovePageDown,
+
+ DeleteFiles,
+ NewDirectory(path::PathBuf),
+ OpenFile,
+ OpenFileWith,
+ ParentDirectory,
+
+ Quit,
+ ForceQuit,
+ ReloadDirList,
+ RenameFile(path::PathBuf),
+ RenameFileAppend,
+ RenameFilePrepend,
+
+ Search(String),
+ SearchNext,
+ SearchPrev,
+
+ SelectFiles { toggle: bool, all: bool },
+ SetMode,
+ ShellCommand(Vec<String>),
+
+ ToggleHiddenFiles,
+
+ Sort(SortType),
+ SortReverse,
+
+ NewTab,
+ CloseTab,
+ TabSwitch(i32),
+}
+
+impl KeyCommand {
+ pub fn command(&self) -> &'static str {
+ match self {
+ Self::BulkRename => "bulk_rename",
+ Self::ChangeDirectory(_) => "change_directory",
+ Self::NewTab => "new_tab",
+ Self::CloseTab => "close_tab",
+ Self::CommandLine(_, _) => "console",
+
+ Self::CutFiles => "cut_files",
+ Self::CopyFiles => "copy_files",
+ Self::PasteFiles(_) => "paste_files",
+
+ Self::CursorMoveUp(_) => "cursor_move_up",
+ Self::CursorMoveDown(_) => "cursor_move_down",
+ Self::CursorMoveHome => "cursor_move_home",
+ Self::CursorMoveEnd => "cursor_move_end",
+ Self::CursorMovePageUp => "cursor_move_page_up",
+ Self::CursorMovePageDown => "cursor_move_page_down",
+
+ Self::DeleteFiles => "cursor_move_delete",
+ Self::NewDirectory(_) => "new_directory",
+ Self::OpenFile => "open",
+ Self::OpenFileWith => "open_with",
+ Self::ParentDirectory => "cd ..",
+
+ Self::Quit => "quit",
+ Self::ForceQuit => "force_quit",
+ Self::ReloadDirList => "reload_dirlist",
+ Self::RenameFile(_) => "rename_file",
+ Self::RenameFileAppend => "rename_append",
+ Self::RenameFilePrepend => "rename_prepend",
+
+ Self::Search(_) => "search",
+ Self::SearchNext => "search_next",
+ Self::SearchPrev => "search_prev",
+
+ Self::SelectFiles { toggle: _, all: _ } => "select",
+ Self::SetMode => "set_mode",
+ Self::ShellCommand(_) => "shell",
+
+ Self::ToggleHiddenFiles => "toggle_hidden",
+
+ Self::Sort(_) => "sort",
+ Self::SortReverse => "sort_reverse",
+
+ Self::TabSwitch(_) => "tab_switch",
+ }
+ }
+
+ pub fn parse_command(s: &str) -> JoshutoResult<Self> {
+ let (command, arg) = match s.find(' ') {
+ Some(i) => (&s[..i], s[i + 1..].trim_start()),
+ None => (s, ""),
+ };
+
+ match command {
+ "bulk_rename" => Ok(Self::BulkRename),
+ "cd" => match arg {
+ "" => match HOME_DIR.as_ref() {
+ Some(s) => Ok(Self::ChangeDirectory(s.clone())),
+ None => Err(JoshutoError::new(
+ JoshutoErrorKind::EnvVarNotPresent,
+ format!("{}: Cannot find home directory", command),
+ )),
+ },
+ ".." => Ok(Self::ParentDirectory),
+ arg => Ok(Self::ChangeDirectory(path::PathBuf::from(arg))),
+ },
+ "close_tab" => Ok(Self::CloseTab),
+ "copy_files" => Ok(Self::CopyFiles),
+ "console" => Ok(Self::CommandLine(arg.to_owned(), "".to_owned())),
+ "cursor_move_home" => Ok(Self::CursorMoveHome),
+ "cursor_move_end" => Ok(Self::CursorMoveEnd),
+ "cursor_move_page_up" => Ok(Self::CursorMovePageUp),
+ "cursor_move_page_down" => Ok(Self::CursorMovePageDown),
+ "cursor_move_down" => match arg {
+ "" => Ok(Self::CursorMoveDown(1)),
+ arg => match arg.parse::<usize>() {
+ Ok(s) => Ok(Self::CursorMoveDown(s)),
+ Err(e) => Err(JoshutoError::new(
+ JoshutoErrorKind::ParseError,
+ e.to_string(),
+ )),
+ },
+ },
+ "cursor_move_up" => match arg {
+ "" => Ok(Self::CursorMoveUp(1)),
+ arg => match arg.parse::<usize>() {
+ Ok(s) => Ok(Self::CursorMoveUp(s)),
+ Err(e) => Err(JoshutoError::new(
+ JoshutoErrorKind::ParseError,
+ e.to_string(),
+ )),
+ },
+ },
+ "cut_files" => Ok(Self::CutFiles),
+ "delete_files" => Ok(Self::DeleteFiles),
+ "force_quit" => Ok(Self::ForceQuit),
+ "mkdir" => match arg {
+ "" => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: missing additional parameter", command),
+ )),
+ arg => Ok(Self::NewDirectory(path::PathBuf::from(arg))),
+ },
+ "new_tab" => Ok(Self::NewTab),
+
+ "open_file" => Ok(Self::OpenFile),
+ "open_file_with" => Ok(Self::OpenFileWith),
+ "paste_files" => {
+ let mut options = IOWorkerOptions::default();
+ for arg in arg.split_whitespace() {
+ match arg {
+ "--overwrite" => options.overwrite = true,
+ "--skip_exist" => options.skip_exist = true,
+ _ => {
+ return Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: unknown option {}", command, arg),
+ ));
+ }
+ }
+ }
+ Ok(Self::PasteFiles(options))
+ }
+ "quit" => Ok(Self::Quit),
+ "reload_dir_list" => Ok(Self::ReloadDirList),
+ "rename" => match arg {
+ "" => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: Expected 1, got 0", command),
+ )),
+ arg => {
+ let path: path::PathBuf = path::PathBuf::from(arg);
+ Ok(Self::RenameFile(path))
+ }
+ },
+ "rename_append" => Ok(Self::RenameFileAppend),
+ "rename_prepend" => Ok(Self::RenameFilePrepend),
+ "search" => match arg {
+ "" => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: Expected 1, got 0", command),
+ )),
+ arg => Ok(Self::Search(arg.to_string())),
+ },
+ "search_next" => Ok(Self::SearchNext),
+ "search_prev" => Ok(Self::SearchPrev),
+ "select_files" => {
+ let mut toggle = false;
+ let mut all = false;
+ for arg in arg.split_whitespace() {
+ match arg {
+ "--toggle" => toggle = true,
+ "--all" => all = true,
+ _ => {
+ return Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: unknown option {}", command, arg),
+ ));
+ }
+ }
+ }
+ Ok(Self::SelectFiles { toggle, all })
+ }
+ "set_mode" => Ok(Self::SetMode),
+ "shell" => match shell_words::split(arg) {
+ Ok(s) if !s.is_empty() => Ok(Self::ShellCommand(s)),
+ Ok(_) => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("sort: args {}", arg),
+ )),
+ Err(e) => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: {}", arg, e),
+ )),
+ },
+ "sort" => match arg {
+ "reverse" => Ok(Self::SortReverse),
+ arg => match SortType::parse(arg) {
+ Some(s) => Ok(Self::Sort(s)),
+ None => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("sort: Unknown option {}", arg),
+ )),
+ },
+ },
+ "tab_switch" => match arg {
+ "" => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: {}", command, "No option provided"),
+ )),
+ arg => match arg.parse::<i32>() {
+ Ok(s) => Ok(Self::TabSwitch(s)),
+ Err(e) => Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ format!("{}: {}", command, e.to_string()),
+ )),
+ },
+ },
+ "toggle_hidden" => Ok(Self::ToggleHiddenFiles),
+ inp => Err(JoshutoError::new(
+ JoshutoErrorKind::UnknownCommand,
+ format!("Unknown command: {}", inp),
+ )),
+ }
+ }
+}
+
+impl JoshutoRunnable for KeyCommand {
+ fn execute(&self, context: &mut JoshutoContext, backend: &mut TuiBackend) -> JoshutoResult<()> {
+ match &*self {
+ Self::BulkRename => bulk_rename::bulk_rename(context, backend),
+ Self::ChangeDirectory(p) => {
+ change_directory::change_directory(context, p.as_path())?;
+ LoadChild::load_child(context)?;
+ Ok(())
+ }
+ Self::NewTab => tab_ops::new_tab(context),
+ Self::CloseTab => tab_ops::close_tab(context),
+ Self::CommandLine(p, s) => {
+ command_line::readline(context, backend, p.as_str(), s.as_str())
+ }
+ Self::CutFiles => file_ops::cut(context),
+ Self::CopyFiles => file_ops::copy(context),
+ Self::PasteFiles(options) => file_ops::paste(context, options.clone()),
+
+ Self::CursorMoveUp(u) => cursor_move::up(context, *u),
+ Self::CursorMoveDown(u) => cursor_move::down(context, *u),
+ Self::CursorMoveHome => cursor_move::home(context),
+ Self::CursorMoveEnd => cursor_move::end(context),
+ Self::CursorMovePageUp => cursor_move::page_up(context, backend),
+ Self::CursorMovePageDown => cursor_move::page_down(context, backend),
+
+ Self::DeleteFiles => {
+ delete_files::delete_selected_files(context, backend)?;
+ Ok(())
+ }
+ Self::NewDirectory(p) => new_directory::new_directory(context, p.as_path()),
+ Self::OpenFile => open_file::open(context, backend),
+ Self::OpenFileWith => open_file::open_with(context, backend),
+ Self::ParentDirectory => parent_directory::parent_directory(context),
+
+ Self::Quit => quit::quit(context),
+ Self::ForceQuit => quit::force_quit(context),
+ Self::ReloadDirList => reload::reload_dirlist(context),
+ Self::RenameFile(p) => rename_file::rename_file(context, p.as_path()),
+ Self::RenameFileAppend => rename_file::rename_file_append(context, backend),
+ Self::RenameFilePrepend => rename_file::rename_file_prepend(context, backend),
+ Self::Search(pattern) => search::search(context, pattern.as_str()),
+ Self::SearchNext => search::search_next(context),
+ Self::SearchPrev => search::search_prev(context),
+
+ Self::SelectFiles { toggle, all } => {
+ selection::select_files(context, *toggle, *all)
+ }
+ Self::SetMode => set_mode::set_mode(context, backend),
+ Self::ShellCommand(v) => shell::shell(context, backend, v.as_slice()),
+
+ Self::ToggleHiddenFiles => show_hidden::toggle_hidden(context),
+
+ Self::Sort(t) => sort::set_sort(context, t.clone()),
+ Self::SortReverse => sort::toggle_reverse(context),
+
+ Self::TabSwitch(i) => {
+ let new_index = (context.tab_context_ref().get_index() as i32 + i)
+ % context.tab_context_ref().len() as i32;
+ let new_index = new_index as usize;
+ tab_ops::tab_switch(new_index, context)?;
+ Ok(())
+ }
+ }
+ }
+}
+
+impl std::fmt::Display for KeyCommand {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ match &*self {
+ Self::ChangeDirectory(p) => write!(f, "{} {}", self.command(), p.to_str().unwrap()),
+ _ => write!(f, "{}", self.command()),
+ }
+ }
+}
+
+impl JoshutoCommand for KeyCommand {}