diff options
-rw-r--r-- | config/keymap.toml | 24 | ||||
-rw-r--r-- | src/joshuto.rs | 113 | ||||
-rw-r--r-- | src/joshuto/command.rs | 29 | ||||
-rw-r--r-- | src/joshuto/command/change_directory.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/cursor_move.rs | 10 | ||||
-rw-r--r-- | src/joshuto/command/file_operation.rs | 12 | ||||
-rw-r--r-- | src/joshuto/command/new_directory.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/open_file.rs | 4 | ||||
-rw-r--r-- | src/joshuto/command/parent_directory.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/quit.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/reload_dir.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/search.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/selection.rs | 5 | ||||
-rw-r--r-- | src/joshuto/command/show_hidden.rs | 2 | ||||
-rw-r--r-- | src/joshuto/command/tab_operation.rs | 86 | ||||
-rw-r--r-- | src/joshuto/command/tab_switch.rs | 60 | ||||
-rw-r--r-- | src/joshuto/ui.rs | 17 | ||||
-rw-r--r-- | src/joshuto/window.rs | 19 |
18 files changed, 286 insertions, 107 deletions
diff --git a/config/keymap.toml b/config/keymap.toml index 6a0050e..de5dccd 100644 --- a/config/keymap.toml +++ b/config/keymap.toml @@ -3,6 +3,11 @@ keys = [ "q" ] command = "quit" [[mapcommand]] +keys = [ "R" ] +command = "reload_dir_list" + + +[[mapcommand]] keys = [ "Up" ] command = "cursor_move" args = [ "-1" ] @@ -130,16 +135,25 @@ keys = [ "/" ] command = "search" +[[mapcommand]] +keys = [ "t", "t" ] +command = "new_tab" -## Features not yet implemented +[[mapcommand]] +keys = [ "w", "w" ] +command = "close_tab" [[mapcommand]] -keys = [ "R" ] -command = "reload_dir_list" +keys = [ "[" ] +command = "tab_switch" +args = [ "-1" ] [[mapcommand]] -keys = [ "Ctrl", "t" ] -command = "new_tab" +keys = [ "]" ] +command = "tab_switch" +args = [ "1" ] + +## Features not yet implemented [[mapcommand]] keys = [ "b", "b" ] diff --git a/src/joshuto.rs b/src/joshuto.rs index c9c954c..737bbc6 100644 --- a/src/joshuto.rs +++ b/src/joshuto.rs @@ -1,9 +1,7 @@ -#[allow(dead_code)] extern crate ncurses; use std; use std::collections::HashMap; -use std::env; use std::path; use std::process; use std::sync; @@ -32,60 +30,16 @@ pub struct JoshutoTab { pub preview_list: Option<structs::JoshutoDirList>, } -pub struct JoshutoContext<'a> { - pub username: String, - pub hostname: String, - pub threads: Vec<(sync::mpsc::Receiver<command::ProgressInfo>, thread::JoinHandle<i32>)>, - pub views: window::JoshutoView, - pub tab_index: usize, - pub tabs: Vec<JoshutoTab>, - - pub config_t: &'a mut config::JoshutoConfig, - pub mimetype_t: &'a config::JoshutoMimetype, - pub theme_t: &'a config::JoshutoTheme, -} - -impl<'a> JoshutoContext<'a> { - pub fn new(config_t: &'a mut config::JoshutoConfig, - mimetype_t: &'a config::JoshutoMimetype, - theme_t: &'a config::JoshutoTheme) -> Self +impl JoshutoTab { + pub fn new(curr_path: path::PathBuf, sort_type: &sort::SortType) -> Self { - let username: String = whoami::username(); - let hostname: String = whoami::hostname(); - - let views: window::JoshutoView = - window::JoshutoView::new(config_t.column_ratio); - - JoshutoContext { - username, - hostname, - threads: Vec::new(), - views, - tab_index: 0, - tabs: Vec::new(), - config_t, - mimetype_t, - theme_t - } - } - - pub fn new_tab(&mut self) - { - let curr_path: path::PathBuf = match env::current_dir() { - Ok(path) => { path }, - Err(e) => { - eprintln!("{}", e); - process::exit(1); - }, - }; - /* keep track of where we are in directories */ let mut history = history::DirHistory::new(); - history.populate_to_root(&curr_path, &self.config_t.sort_type); + history.populate_to_root(&curr_path, sort_type); /* load up directories */ let curr_view: Option<structs::JoshutoDirList> = - match history.pop_or_create(&curr_path, &self.config_t.sort_type) { + match history.pop_or_create(&curr_path, sort_type) { Ok(s) => { Some(s) }, Err(e) => { eprintln!("{}", e); @@ -96,7 +50,7 @@ impl<'a> JoshutoContext<'a> { let parent_view: Option<structs::JoshutoDirList> = match curr_path.parent() { Some(parent) => { - match history.pop_or_create(&parent, &self.config_t.sort_type) { + match history.pop_or_create(&parent, sort_type) { Ok(s) => { Some(s) }, Err(e) => { eprintln!("{}", e); @@ -112,10 +66,9 @@ impl<'a> JoshutoContext<'a> { match s.get_curr_entry() { Some(dirent) => { if dirent.path.is_dir() { - preview_view = match history.pop_or_create(&dirent.path, &self.config_t.sort_type) { + preview_view = match history.pop_or_create(&dirent.path, sort_type) { Ok(s) => { Some(s) }, Err(e) => { - eprintln!("{}", e); None }, }; @@ -131,25 +84,51 @@ impl<'a> JoshutoContext<'a> { preview_view = None } - ui::redraw_status(&self.views, curr_view.as_ref(), &curr_path, - &self.username, &self.hostname); - - ui::redraw_view(&self.views.left_win, parent_view.as_ref()); - ui::redraw_view(&self.views.mid_win, curr_view.as_ref()); - ui::redraw_view(&self.views.right_win, preview_view.as_ref()); - - ncurses::doupdate(); - - let tab = JoshutoTab { + JoshutoTab { curr_path, history, curr_list: curr_view, parent_list: parent_view, preview_list: preview_view, - }; + } + } +} + +pub struct JoshutoContext<'a> { + pub username: String, + pub hostname: String, + pub threads: Vec<(sync::mpsc::Receiver<command::ProgressInfo>, thread::JoinHandle<i32>)>, + pub views: window::JoshutoView, + pub tab_index: usize, + pub tabs: Vec<JoshutoTab>, + + pub config_t: &'a mut config::JoshutoConfig, + pub mimetype_t: &'a config::JoshutoMimetype, + pub theme_t: &'a config::JoshutoTheme, +} + +impl<'a> JoshutoContext<'a> { + pub fn new(config_t: &'a mut config::JoshutoConfig, + mimetype_t: &'a config::JoshutoMimetype, + theme_t: &'a config::JoshutoTheme) -> Self + { + let username: String = whoami::username(); + let hostname: String = whoami::hostname(); - self.tabs.push(tab); - self.tab_index = self.tabs.len() - 1; + let views: window::JoshutoView = + window::JoshutoView::new(config_t.column_ratio); + + JoshutoContext { + username, + hostname, + threads: Vec::new(), + views, + tab_index: 0, + tabs: Vec::new(), + config_t, + mimetype_t, + theme_t + } } pub fn reload_dirlists(&mut self) @@ -273,7 +252,7 @@ pub fn run(mut config_t: config::JoshutoConfig, let mut context = JoshutoContext::new(&mut config_t, &mimetype_t, &theme_t); - context.new_tab(); + command::NewTab::new_tab(&mut context); let wait_duration: time::Duration = time::Duration::from_millis(100); diff --git a/src/joshuto/command.rs b/src/joshuto/command.rs index 9c6f7da..3973ba1 100644 --- a/src/joshuto/command.rs +++ b/src/joshuto/command.rs @@ -52,6 +52,14 @@ pub use self::show_hidden::ToggleHiddenFiles; mod selection; pub use self::selection::SelectFiles; +mod tab_operation; +pub use self::tab_operation::NewTab; +pub use self::tab_operation::CloseTab; + +mod tab_switch; +pub use self::tab_switch::TabSwitch; + + #[derive(Debug)] pub enum CommandKeybind { SimpleKeybind(Box<dyn JoshutoCommand>), @@ -126,6 +134,7 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<dyn Jo None } }, + "close_tab" => Some(Box::new(self::CloseTab::new())), "copy_files" => Some(Box::new(self::CopyFiles::new())), "cursor_move" => { if let Some(args) = args { @@ -153,6 +162,7 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<dyn Jo "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())), @@ -235,6 +245,25 @@ pub fn from_args(command: &str, args: Option<&Vec<String>>) -> Option<Box<dyn Jo } Some(Box::new(self::SelectFiles::new(toggle, all))) }, + "tab_switch" => { + if let Some(args) = args { + if args.len() > 0 { + match args[0].parse::<i32>() { + Ok(s) => { + Some(Box::new(self::TabSwitch::new(s))) + }, + Err(e) => { + eprintln!("{}", e); + None + }, + } + } else { + None + } + } else { + None + } + } "toggle_hidden" => Some(Box::new(self::ToggleHiddenFiles::new())), _ => None, } diff --git a/src/joshuto/command/change_directory.rs b/src/joshuto/command/change_directory.rs index 7db7da1..30e6938 100644 --- a/src/joshuto/command/change_directory.rs +++ b/src/joshuto/command/change_directory.rs @@ -10,7 +10,7 @@ use joshuto; use joshuto::command; use joshuto::ui; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct ChangeDirectory { path: path::PathBuf, } diff --git a/src/joshuto/command/cursor_move.rs b/src/joshuto/command/cursor_move.rs index 0779c94..27fd6e4 100644 --- a/src/joshuto/command/cursor_move.rs +++ b/src/joshuto/command/cursor_move.rs @@ -9,7 +9,7 @@ use joshuto::ui; use joshuto::command; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CursorMove { movement: i32, } @@ -108,7 +108,7 @@ impl command::Runnable for CursorMove { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CursorMovePageUp; impl CursorMovePageUp { @@ -148,7 +148,7 @@ impl command::Runnable for CursorMovePageUp { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CursorMovePageDown; impl CursorMovePageDown { @@ -189,7 +189,7 @@ impl command::Runnable for CursorMovePageDown { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CursorMoveHome; impl CursorMoveHome { @@ -227,7 +227,7 @@ impl command::Runnable for CursorMoveHome { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CursorMoveEnd; impl CursorMoveEnd { diff --git a/src/joshuto/command/file_operation.rs b/src/joshuto/command/file_operation.rs index f7cd12f..99c91c1 100644 --- a/src/joshuto/command/file_operation.rs +++ b/src/joshuto/command/file_operation.rs @@ -58,7 +58,7 @@ enum FileOp { Copy, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CutFiles; impl CutFiles { @@ -87,7 +87,7 @@ impl command::Runnable for CutFiles { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CopyFiles; impl CopyFiles { @@ -116,7 +116,7 @@ impl command::Runnable for CopyFiles { } } -#[derive(Debug,Clone)] +#[derive(Clone, Debug)] pub struct ProgressInfo { pub bytes_finished: u64, pub total_bytes: u64, @@ -273,7 +273,7 @@ impl command::Runnable for PasteFiles { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct DeleteFiles; impl DeleteFiles { @@ -357,14 +357,14 @@ impl command::Runnable for DeleteFiles { } -#[derive(Debug)] +#[derive(Clone, Debug, Display)] pub enum RenameFileMethod { Append, Prepend, Overwrite } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct RenameFile { method: RenameFileMethod, } diff --git a/src/joshuto/command/new_directory.rs b/src/joshuto/command/new_directory.rs index 14578c2..94ce880 100644 --- a/src/joshuto/command/new_directory.rs +++ b/src/joshuto/command/new_directory.rs @@ -11,7 +11,7 @@ use joshuto::window; use joshuto::command; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct NewDirectory; impl NewDirectory { diff --git a/src/joshuto/command/open_file.rs b/src/joshuto/command/open_file.rs index c9ba9c8..5d60ce3 100644 --- a/src/joshuto/command/open_file.rs +++ b/src/joshuto/command/open_file.rs @@ -16,7 +16,7 @@ use joshuto::ui; use joshuto::unix; use joshuto::window; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct OpenFile; impl OpenFile { @@ -144,7 +144,7 @@ impl command::Runnable for OpenFile { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct OpenFileWith; impl OpenFileWith { diff --git a/src/joshuto/command/parent_directory.rs b/src/joshuto/command/parent_directory.rs index 60e370f..c854910 100644 --- a/src/joshuto/command/parent_directory.rs +++ b/src/joshuto/command/parent_directory.rs @@ -9,7 +9,7 @@ use joshuto; use joshuto::ui; use joshuto::command; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct ParentDirectory; impl ParentDirectory { diff --git a/src/joshuto/command/quit.rs b/src/joshuto/command/quit.rs index 06d81b3..1f81c14 100644 --- a/src/joshuto/command/quit.rs +++ b/src/joshuto/command/quit.rs @@ -6,7 +6,7 @@ use joshuto; use joshuto::command; use joshuto::ui; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Quit; impl Quit { diff --git a/src/joshuto/command/reload_dir.rs b/src/joshuto/command/reload_dir.rs index 6be9bbf..834667e 100644 --- a/src/joshuto/command/reload_dir.rs +++ b/src/joshuto/command/reload_dir.rs @@ -9,7 +9,7 @@ use joshuto; use joshuto::ui; use joshuto::command; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct ReloadDirList; impl ReloadDirList { diff --git a/src/joshuto/command/search.rs b/src/joshuto/command/search.rs index 072522e..1262854 100644 --- a/src/joshuto/command/search.rs +++ b/src/joshuto/command/search.rs @@ -9,7 +9,7 @@ use joshuto::window; use joshuto::command; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Search; impl Search { diff --git a/src/joshuto/command/selection.rs b/src/joshuto/command/selection.rs index 74ccc6e..babd33c 100644 --- a/src/joshuto/command/selection.rs +++ b/src/joshuto/command/selection.rs @@ -1,13 +1,10 @@ -extern crate fs_extra; -extern crate ncurses; - use std; use std::fmt; use joshuto; use joshuto::command; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SelectFiles { toggle: bool, all: bool, diff --git a/src/joshuto/command/show_hidden.rs b/src/joshuto/command/show_hidden.rs index 5abd51c..e0a2e15 100644 --- a/src/joshuto/command/show_hidden.rs +++ b/src/joshuto/command/show_hidden.rs @@ -8,7 +8,7 @@ use joshuto; use joshuto::command; use joshuto::ui; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct ToggleHiddenFiles; impl ToggleHiddenFiles { diff --git a/src/joshuto/command/tab_operation.rs b/src/joshuto/command/tab_operation.rs new file mode 100644 index 0000000..43855b7 --- /dev/null +++ b/src/joshuto/command/tab_operation.rs @@ -0,0 +1,86 @@ +use std; +use std::fmt; +use std::path; +use std::env; + +use joshuto; +use joshuto::command; + +#[derive(Clone, Debug)] +pub struct NewTab; + +impl NewTab { + pub fn new() -> Self { NewTab } + pub const fn command() -> &'static str { "new_tab" } + + pub fn new_tab(context: &mut joshuto::JoshutoContext) + { + let curr_path: path::PathBuf = match env::current_dir() { + Ok(path) => { path }, + Err(e) => { + eprintln!("{}", e); + return; + }, + }; + + let tab = joshuto::JoshutoTab::new(curr_path, &context.config_t.sort_type); + + context.tabs.push(tab); + context.tab_index = context.tabs.len() - 1; + + command::TabSwitch::tab_switch(context.tabs.len() as i32 - 1, context); + } +} + +impl command::JoshutoCommand for NewTab {} + +impl std::fmt::Display for NewTab { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + f.write_str(Self::command()) + } +} + +impl command::Runnable for NewTab { + fn execute(&self, context: &mut joshuto::JoshutoContext) + { + Self::new_tab(context); + } +} + +#[derive(Clone, Debug)] +pub struct CloseTab; + +impl CloseTab { + pub fn new() -> Self { CloseTab } + pub const fn command() -> &'static str { "close_tab" } + + pub fn close_tab(context: &mut joshuto::JoshutoContext) + { + if context.tabs.len() <= 1 { + return; + } + + context.tabs.remove(context.tab_index); + if context.tab_index > 0 { + context.tab_index = context.tab_index - 1; + } + command::TabSwitch::tab_switch(context.tab_index as i32, context); + } +} + +impl command::JoshutoCommand for CloseTab {} + +impl std::fmt::Display for CloseTab { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + f.write_str(Self::command()) + } +} + +impl command::Runnable for CloseTab { + fn execute(&self, context: &mut joshuto::JoshutoContext) + { + Self::close_tab(context); + } +} diff --git a/src/joshuto/command/tab_switch.rs b/src/joshuto/command/tab_switch.rs new file mode 100644 index 0000000..f44fa4b --- /dev/null +++ b/src/joshuto/command/tab_switch.rs @@ -0,0 +1,60 @@ +use std; +use std::fmt; + +use joshuto; +use joshuto::command; +use joshuto::ui; + +#[derive(Clone, Debug)] +pub struct TabSwitch { + movement: i32, +} + +impl TabSwitch { + pub fn new(movement: i32) -> Self { + TabSwitch { + movement, + } + } + pub const fn command() -> &'static str { "tab_switch" } + + pub fn tab_switch(new_index: i32, context: &mut joshuto::JoshutoContext) + { + context.tab_index = new_index as usize; + + let curr_tab = &context.tabs[context.tab_index]; + + ui::redraw_view(&context.views.left_win, curr_tab.parent_list.as_ref()); + ui::redraw_view(&context.views.mid_win, curr_tab.curr_list.as_ref()); + ui::redraw_view(&context.views.right_win, curr_tab.preview_list.as_ref()); + + ui::redraw_status(&context.views, curr_tab.curr_list.as_ref(), &curr_tab.curr_path, + &context.username, &context.hostname); + + ui::redraw_tab_view(&context.views.tab_win, &context); + + ncurses::doupdate(); + } +} + +impl command::JoshutoCommand for TabSwitch {} + +impl std::fmt::Display for TabSwitch { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!(f, "{} {}", Self::command(), self.movement) + } +} + +impl command::Runnable for TabSwitch { + fn execute(&self, context: &mut joshuto::JoshutoContext) + { + let mut new_index = context.tab_index as i32 + self.movement; + if new_index < 0 { + new_index = 0; + } else if new_index >= context.tabs.len() as i32 { + new_index = context.tabs.len() as i32 - 1; + } + Self::tab_switch(new_index, context); + } +} diff --git a/src/joshuto/ui.rs b/src/joshuto/ui.rs index 6111a7c..e07ed54 100644 --- a/src/joshuto/ui.rs +++ b/src/joshuto/ui.rs @@ -6,6 +6,7 @@ use std::fs; use std::path; use std::time; +use joshuto; use joshuto::structs; use joshuto::unix; use joshuto::window; @@ -255,7 +256,7 @@ pub fn redraw_view(win: &window::JoshutoPanel, ncurses::wnoutrefresh(win.win); } -pub fn redraw_status(joshuto_view : &window::JoshutoView, +pub fn redraw_status(joshuto_view: &window::JoshutoView, curr_view: Option<&structs::JoshutoDirList>, curr_path: &path::PathBuf, username: &str, hostname: &str) { @@ -269,6 +270,20 @@ pub fn redraw_status(joshuto_view : &window::JoshutoView, } } +pub fn redraw_tab_view(win: &window::JoshutoPanel, context: &joshuto::JoshutoContext) +{ + let tab_len = context.tabs.len(); + if tab_len == 1 { + ncurses::werase(win.win); + } else { + ncurses::wmove(win.win, 0, 0); + ncurses::wattron(win.win, ncurses::A_BOLD()); + ncurses::waddstr(win.win, format!("{} {}", context.tab_index + 1, tab_len).as_str()); + ncurses::wattroff(win.win, ncurses::A_BOLD()); + } + ncurses::wnoutrefresh(win.win); +} + pub fn draw_loading_bar(win: &window::JoshutoPanel, percentage: f32) { let cols: i32 = (win.cols as f32 * percentage) as i32; diff --git a/src/joshuto/window.rs b/src/joshuto/window.rs index fed3a4d..ccf6f63 100644 --- a/src/joshuto/window.rs +++ b/src/joshuto/window.rs @@ -27,16 +27,9 @@ impl JoshutoPanel { } } - pub fn move_to_top(&self) - { - ncurses::top_panel(self.panel); - } - + pub fn move_to_top(&self) { ncurses::top_panel(self.panel); } #[allow(dead_code)] - pub fn move_to_bottom(&self) - { - ncurses::bottom_panel(self.panel); - } + pub fn move_to_bottom(&self) { ncurses::bottom_panel(self.panel); } pub fn redraw(&mut self, rows: i32, cols: i32, coords: (usize, usize)) { @@ -75,6 +68,7 @@ impl std::ops::Drop for Joshuto { #[derive(Debug)] pub struct JoshutoView { pub top_win: JoshutoPanel, + pub tab_win: JoshutoPanel, pub left_win: JoshutoPanel, pub mid_win: JoshutoPanel, pub right_win: JoshutoPanel, @@ -92,10 +86,14 @@ impl JoshutoView { ncurses::getmaxyx(ncurses::stdscr(), &mut term_rows, &mut term_cols); let term_divide: i32 = term_cols / sum_ratio as i32; - let win_xy: (i32, i32) = (1, term_cols); + let win_xy: (i32, i32) = (1, term_cols - 5); let win_coord: (usize, usize) = (0, 0); let top_win = JoshutoPanel::new(win_xy.0, win_xy.1, win_coord); + let win_xy: (i32, i32) = (1, 5); + let win_coord: (usize, usize) = (0, term_cols as usize - 5); + let tab_win = JoshutoPanel::new(win_xy.0, win_xy.1, win_coord); + let win_xy: (i32, i32) = (term_rows - 2, (term_divide * win_ratio.0 as i32) - 2); let win_coord: (usize, usize) = (1, 0); let left_win = JoshutoPanel::new(win_xy.0, win_xy.1, win_coord); @@ -121,6 +119,7 @@ impl JoshutoView { JoshutoView { top_win, + tab_win, left_win, mid_win, right_win, |