summaryrefslogtreecommitdiffstats
path: root/src/tab.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tab.rs')
-rw-r--r--src/tab.rs151
1 files changed, 92 insertions, 59 deletions
diff --git a/src/tab.rs b/src/tab.rs
index 1af24bf..fe3c8a6 100644
--- a/src/tab.rs
+++ b/src/tab.rs
@@ -16,7 +16,7 @@ use crate::opener::execute_in_child;
use crate::preview::{Directory, Preview};
use crate::selectable_content::SelectableContent;
use crate::shortcut::Shortcut;
-use crate::utils::{row_to_index, set_clipboard};
+use crate::utils::{row_to_window_index, set_clipboard};
use crate::visited::History;
/// Holds every thing about the current tab of the application.
@@ -97,7 +97,6 @@ impl Tab {
/// Fill the input string with the currently selected completion.
pub fn fill_completion(&mut self) -> Result<()> {
- // self.completion.set_kind(&self.mode);
match self.mode {
Mode::InputCompleted(InputCompleted::Goto) => {
let current_path = self.path_content_str().unwrap_or_default().to_owned();
@@ -125,19 +124,25 @@ impl Tab {
}
}
+ /// Refresh everything but the view
+ pub fn refresh_params(&mut self) -> Result<()> {
+ self.filter = FilterKind::All;
+ self.input.reset();
+ self.preview = Preview::new_empty();
+ self.completion.reset();
+ self.directory.clear();
+ Ok(())
+ }
+
/// Refresh the current view.
/// Input string is emptied, the files are read again, the window of
/// displayed files is reset.
/// The first file is selected.
pub fn refresh_view(&mut self) -> Result<()> {
- self.filter = FilterKind::All;
- self.input.reset();
+ self.refresh_params()?;
self.path_content
.reset_files(&self.filter, self.show_hidden)?;
self.window.reset(self.path_content.content.len());
- self.preview = Preview::new_empty();
- self.completion.reset();
- self.directory.clear();
Ok(())
}
@@ -217,8 +222,11 @@ impl Tab {
/// Refresh the existing users.
pub fn refresh_users(&mut self, users_cache: UsersCache) -> Result<()> {
+ let last_pathcontent_index = self.path_content.index;
self.path_content
- .refresh_users(users_cache, &self.filter, self.show_hidden)
+ .refresh_users(users_cache, &self.filter, self.show_hidden)?;
+ self.path_content.select_index(last_pathcontent_index);
+ Ok(())
}
/// Search in current directory for an file whose name contains `searched_name`,
@@ -263,7 +271,9 @@ impl Tab {
/// Move to the parent of current path
pub fn move_to_parent(&mut self) -> Result<()> {
let path = self.path_content.path.clone();
- let Some(parent) = path.parent() else { return Ok(()) };
+ let Some(parent) = path.parent() else {
+ return Ok(());
+ };
self.set_pathcontent(parent)
}
@@ -294,14 +304,11 @@ impl Tab {
/// Select the next sibling.
pub fn tree_select_next(&mut self, colors: &Colors) -> Result<()> {
- self.directory.tree.increase_required_height();
- self.directory.unselect_children();
self.directory.select_next(colors)
}
/// Select the previous siblging
pub fn tree_select_prev(&mut self, colors: &Colors) -> Result<()> {
- self.directory.unselect_children();
self.directory.select_prev(colors)
}
@@ -313,17 +320,28 @@ impl Tab {
/// Go to the last leaf.
pub fn tree_go_to_bottom_leaf(&mut self, colors: &Colors) -> Result<()> {
- self.directory.tree.set_required_height(usize::MAX);
+ self.directory.tree.set_required_height_to_max();
self.directory.unselect_children();
self.directory.go_to_bottom_leaf(colors)
}
/// Returns the current path.
- /// It Tree mode, it's the path of the selected node.
- /// Else, it's the current path of pathcontent.
- pub fn current_path(&mut self) -> &path::Path {
+ /// In tree mode :
+ /// if the selected node is a directory, that's it.
+ /// else, it is the parent of the selected node.
+ /// In other modes, it's the current path of pathcontent.
+ pub fn current_directory_path(&mut self) -> &path::Path {
match self.mode {
- Mode::Tree => &self.directory.tree.current_node.fileinfo.path,
+ Mode::Tree => {
+ let path = &self.directory.tree.current_node.fileinfo.path;
+ if path.is_dir() {
+ return path;
+ }
+ let Some(parent) = path.parent() else {
+ return path::Path::new("/");
+ };
+ parent
+ }
_ => &self.path_content.path,
}
}
@@ -380,9 +398,12 @@ impl Tab {
/// Reset the last mode.
/// The last mode is set to normal again.
- pub fn reset_mode(&mut self) {
+ /// Returns True if the last mode requires a refresh afterwards.
+ pub fn reset_mode(&mut self) -> bool {
+ let must_refresh = self.mode.refresh_required();
self.mode = self.previous_mode;
self.previous_mode = Mode::Normal;
+ must_refresh
}
/// Returns true if the current mode requires 2 windows.
@@ -400,7 +421,7 @@ impl Tab {
self.path_content.select_current();
self.window.scroll_down_one(self.path_content.index)
}
- Mode::Preview => self.window.scroll_down_one(self.window.bottom),
+ Mode::Preview => self.preview_page_down(),
_ => (),
}
}
@@ -414,7 +435,7 @@ impl Tab {
self.path_content.select_current();
self.window.scroll_up_one(self.path_content.index)
}
- Mode::Preview => self.window.scroll_up_one(self.window.top),
+ Mode::Preview => self.preview_page_up(),
_ => (),
}
}
@@ -446,19 +467,16 @@ impl Tab {
/// Select the first child of the current node and reset the display.
pub fn select_first_child(&mut self, colors: &Colors) -> Result<()> {
- self.directory.tree.increase_required_height();
self.tree_select_first_child(colors)
}
/// Select the next sibling of the current node.
pub fn select_next(&mut self, colors: &Colors) -> Result<()> {
- self.directory.tree.increase_required_height();
self.tree_select_next(colors)
}
/// Select the previous sibling of the current node.
pub fn select_prev(&mut self, colors: &Colors) -> Result<()> {
- self.directory.tree.decrease_required_height();
self.tree_select_prev(colors)
}
@@ -511,62 +529,77 @@ impl Tab {
self.path_content.select_index(up_index);
self.window.scroll_to(up_index)
}
- Mode::Preview => {
- if self.window.top > 0 {
- let skip = min(self.window.top, 30);
- self.window.bottom -= skip;
- self.window.top -= skip;
- }
- }
+ Mode::Preview => self.preview_page_up(),
_ => (),
}
}
+ fn preview_page_up(&mut self) {
+ if self.window.top > 0 {
+ let skip = min(self.window.top, 30);
+ self.window.bottom -= skip;
+ self.window.top -= skip;
+ }
+ }
+
/// Move down 10 rows in normal mode.
/// In other modes where vertical scrolling is possible (atm Preview),
/// if moves down one page.
pub fn page_down(&mut self) {
match self.mode {
- Mode::Normal => {
- let down_index = min(
- self.path_content.content.len() - 1,
- self.path_content.index + 10,
- );
- self.path_content.select_index(down_index);
- self.window.scroll_to(down_index);
- }
- Mode::Preview => {
- if self.window.bottom < self.preview.len() {
- let skip = min(self.preview.len() - self.window.bottom, 30);
- self.window.bottom += skip;
- self.window.top += skip;
- }
- }
+ Mode::Normal => self.normal_page_down(),
+ Mode::Preview => self.preview_page_down(),
_ => (),
}
}
+ fn normal_page_down(&mut self) {
+ let down_index = min(
+ self.path_content.content.len() - 1,
+ self.path_content.index + 10,
+ );
+ self.path_content.select_index(down_index);
+ self.window.scroll_to(down_index);
+ }
+
+ fn preview_page_down(&mut self) {
+ if self.window.bottom < self.preview.len() {
+ let skip = min(self.preview.len() - self.window.bottom, 30);
+ self.window.bottom += skip;
+ self.window.top += skip;
+ }
+ }
+
/// Select a given row, if there's something in it.
- pub fn select_row(&mut self, row: u16, colors: &Colors) -> Result<()> {
+ pub fn select_row(&mut self, row: u16, colors: &Colors, term_height: usize) -> Result<()> {
match self.mode {
- Mode::Normal => {
- let index = row_to_index(row);
- self.path_content.select_index(index);
- self.window.scroll_to(index);
- }
- Mode::Tree => {
- let index = row_to_index(row) + 1;
- self.directory.tree.unselect_children();
- self.directory.tree.position = self.directory.tree.position_from_index(index);
- let (_, _, node) = self.directory.tree.select_from_position()?;
- self.directory.make_preview(colors);
- self.directory.tree.current_node = node;
- }
+ Mode::Normal => self.normal_select_row(row),
+ Mode::Tree => self.tree_select_row(row, colors, term_height)?,
_ => (),
}
Ok(())
}
+ fn normal_select_row(&mut self, row: u16) {
+ let screen_index = row_to_window_index(row);
+ let index = screen_index + self.window.top;
+ self.path_content.select_index(index);
+ self.window.scroll_to(index);
+ }
+
+ fn tree_select_row(&mut self, row: u16, colors: &Colors, term_height: usize) -> Result<()> {
+ let screen_index = row_to_window_index(row) + 1;
+ // term.height = canvas.height + 2 rows for the canvas border
+ let (top, _, _) = self.directory.calculate_tree_window(term_height - 2);
+ let index = screen_index + top;
+ self.directory.tree.unselect_children();
+ self.directory.tree.position = self.directory.tree.position_from_index(index);
+ let (_, _, node) = self.directory.tree.select_from_position()?;
+ self.directory.make_preview(colors);
+ self.directory.tree.current_node = node;
+ Ok(())
+ }
+
/// Sort the file with given criteria
/// Valid kind of sorts are :
/// by kind : directory first, files next, in alphanumeric order