summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/completion.rs12
-rw-r--r--src/event_exec.rs59
-rw-r--r--src/preview.rs195
-rw-r--r--src/status.rs38
-rw-r--r--src/tab.rs111
-rw-r--r--src/term_manager.rs42
-rw-r--r--src/trees.rs66
7 files changed, 176 insertions, 347 deletions
diff --git a/src/completion.rs b/src/completion.rs
index fca4559..38ed615 100644
--- a/src/completion.rs
+++ b/src/completion.rs
@@ -4,7 +4,6 @@ use anyhow::Result;
use strum::IntoEnumIterator;
use crate::fileinfo::PathContent;
-use crate::preview::ColoredTriplet;
/// Different kind of completions
#[derive(Clone, Default, Copy)]
@@ -216,13 +215,18 @@ impl Completion {
pub fn search_from_tree(
&mut self,
input_string: &str,
- content: &[ColoredTriplet],
+ content: &[&std::ffi::OsStr],
) -> Result<()> {
self.update(
content
.iter()
- .filter(|(_, _, s)| s.text.contains(input_string))
- .map(|(_, _, s)| s.text.replace("▸ ", "").replace("▾ ", ""))
+ .filter(|&p| p.to_string_lossy().contains(input_string))
+ .map(|p| {
+ p.to_string_lossy()
+ .into_owned()
+ .replace("▸ ", "")
+ .replace("▾ ", "")
+ })
.collect(),
);
diff --git a/src/event_exec.rs b/src/event_exec.rs
index 6117a63..611f896 100644
--- a/src/event_exec.rs
+++ b/src/event_exec.rs
@@ -73,18 +73,14 @@ impl EventAction {
let tab = status.selected_non_mut();
match tab.mode {
- Mode::Normal => {
- let Some(file) = tab.path_content.selected() else {
+ Mode::Normal | Mode::Tree => {
+ let Ok(file) = tab.selected() else {
return Ok(());
};
let path = file.path.clone();
status.toggle_flag_on_path(&path);
status.selected().down_one_row();
}
- Mode::Tree => {
- let path = tab.directory.tree.current_node.filepath();
- status.toggle_flag_on_path(&path);
- }
_ => (),
}
Ok(())
@@ -378,7 +374,7 @@ impl EventAction {
/// Basic folders (/, /dev... $HOME) and mount points (even impossible to
/// visit ones) are proposed.
pub fn shortcut(tab: &mut Tab) -> Result<()> {
- std::env::set_current_dir(tab.current_directory_path())?;
+ std::env::set_current_dir(tab.current_directory_path().context("no parent")?)?;
tab.shortcut.update_git_root();
tab.set_mode(Mode::Navigate(Navigate::Shortcut));
Ok(())
@@ -396,7 +392,7 @@ impl EventAction {
};
let nvim_server = status.nvim_server.clone();
if status.flagged.is_empty() {
- let Some(fileinfo) = status.selected_non_mut().selected() else {
+ let Ok(fileinfo) = status.selected_non_mut().selected() else {
return Ok(());
};
let Some(path_str) = fileinfo.path.to_str() else {
@@ -460,7 +456,7 @@ impl EventAction {
log_line!("{DEFAULT_DRAGNDROP} must be installed.");
return Ok(());
}
- let Some(file) = status.selected_non_mut().selected() else {
+ let Ok(file) = status.selected_non_mut().selected() else {
return Ok(());
};
let path_str = file
@@ -539,7 +535,7 @@ impl EventAction {
let tab = status.selected();
match tab.mode {
Mode::Normal => tab.move_to_parent()?,
- Mode::Tree => tab.tree_select_parent()?,
+ Mode::Tree => tab.tree_select_parent(),
Mode::InputSimple(_) | Mode::InputCompleted(_) => {
tab.input.cursor_left();
}
@@ -556,7 +552,11 @@ impl EventAction {
match tab.mode {
Mode::Normal => LeaveMode::open_file(status),
Mode::Tree => {
- tab.select_first_child()?;
+ if tab.tree.selected_path().is_file() {
+ tab.tree_select_next()?;
+ } else {
+ LeaveMode::open_file(status)?;
+ };
status.update_second_pane_for_preview()
}
Mode::InputSimple(_) | Mode::InputCompleted(_) => {
@@ -799,7 +799,7 @@ impl EventAction {
return Ok(());
}
if let Mode::Normal | Mode::Tree = tab.mode {
- let Some(file_info) = tab.selected() else {
+ let Ok(file_info) = tab.selected() else {
return Ok(());
};
info!("selected {:?}", file_info);
@@ -1099,7 +1099,11 @@ impl Display for NodeCreation {
impl NodeCreation {
fn create(&self, tab: &mut Tab) -> Result<()> {
let root_path = match tab.previous_mode {
- Mode::Tree => tab.directory.tree.directory_of_selected()?.to_owned(),
+ Mode::Tree => tab
+ .tree
+ .directory_of_selected()
+ .context("no parent")?
+ .to_owned(),
_ => tab.path_content.path.clone(),
};
log::info!("root_path: {root_path:?}");
@@ -1137,6 +1141,9 @@ impl LeaveMode {
/// Open the file with configured opener or enter the directory.
pub fn open_file(status: &mut Status) -> Result<()> {
let tab = status.selected();
+ if matches!(tab.mode, Mode::Tree) {
+ return EventAction::open_file(status);
+ };
if tab.path_content.is_empty() {
return Ok(());
}
@@ -1292,15 +1299,15 @@ impl LeaveMode {
/// We only try to rename in the same directory, so it shouldn't be a problem.
/// Filename is sanitized before processing.
pub fn rename(tab: &mut Tab) -> Result<()> {
- let fileinfo = match tab.previous_mode {
- Mode::Tree => &tab.directory.tree.current_node.fileinfo,
- _ => tab
- .path_content
+ let original_path = if let Mode::Tree = tab.mode {
+ tab.tree.selected_path()
+ } else {
+ tab.path_content
.selected()
- .context("rename: couldnt parse selected")?,
+ .context("rename: couldn't parse selected file")?
+ .path
+ .as_path()
};
-
- let original_path = &fileinfo.path;
if let Some(parent) = original_path.parent() {
let new_path = parent.join(sanitize_filename::sanitize(tab.input.string()));
info!(
@@ -1438,17 +1445,10 @@ impl LeaveMode {
status.update_second_pane_for_preview()
}
+ // TODO! enter the tree if it's a directory
/// Execute the selected node if it's a file else enter the directory.
pub fn tree(status: &mut Status) -> Result<()> {
- let tab = status.selected();
- let node = tab.directory.tree.current_node.clone();
- if !node.is_dir {
- EventAction::open_file(status)
- } else {
- tab.set_pathcontent(&node.filepath())?;
- tab.make_tree(None)?;
- Ok(())
- }
+ EventAction::open_file(status)
}
/// Store a password of some kind (sudo or device passphrase).
@@ -1548,6 +1548,7 @@ impl LeaveMode {
let (username, hostname, remote_path) = (strings[0], strings[1], strings[2]);
let current_path: &str = tab
.current_directory_path()
+ .context("no parent")?
.to_str()
.context("couldn't parse the path")?;
let first_arg = &format!("{username}@{hostname}:{remote_path}");
diff --git a/src/preview.rs b/src/preview.rs
index 89d656d..221bf2c 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -24,7 +24,9 @@ use crate::decompress::{list_files_tar, list_files_zip};
use crate::fileinfo::{FileInfo, FileKind};
use crate::filter::FilterKind;
use crate::opener::execute_and_capture_output_without_check;
-use crate::tree::{ColoredString, Tree};
+use crate::sort::SortKind;
+use crate::tree::ColoredString;
+use crate::trees::FileSystem;
use crate::users::Users;
use crate::utils::{clear_tmp_file, filename_from_path, is_program_in_path};
@@ -114,19 +116,11 @@ impl Preview {
/// Creates a new `Directory` from the file_info
/// It explores recursivelly the directory and creates a tree.
/// The recursive exploration is limited to depth 2.
- pub fn directory(
- file_info: &FileInfo,
- users: &Users,
- filter: &FilterKind,
- show_hidden: bool,
- ) -> Result<Self> {
+ pub fn directory(file_info: &FileInfo, users: &Users) -> Result<Self> {
Ok(Self::Directory(Directory::new(
- &file_info.path,
+ file_info.path.to_owned(),
users,
- filter,
- show_hidden,
- Some(2),
- )?))
+ )))
}
/// Creates a new preview instance based on the filekind and the extension of
@@ -1049,181 +1043,34 @@ impl ColoredText {
#[derive(Clone, Debug)]
pub struct Directory {
pub content: Vec<ColoredTriplet>,
- pub tree: Tree,
- len: usize,
- pub selected_index: usize,
}
impl Directory {
- /// Creates a new tree view of the directory.
- /// We only hold the result here, since the tree itself has now usage atm.
- pub fn new(
- path: &Path,
- users: &Users,
- filter_kind: &FilterKind,
- show_hidden: bool,
- max_depth: Option<usize>,
- ) -> Result<Self> {
- let max_depth = match max_depth {
- Some(max_depth) => max_depth,
- None => Tree::MAX_DEPTH,
- };
+ pub fn new(path: PathBuf, users: &Users) -> Self {
+ let tree = FileSystem::new(
+ path,
+ 4,
+ SortKind::tree_default(),
+ users,
+ false,
+ &FilterKind::All,
+ );
- let mut tree = Tree::from_path(path, max_depth, users, filter_kind, show_hidden, vec![0])?;
- tree.select_root();
- let (selected_index, content) = tree.into_navigable_content();
- Ok(Self {
- tree,
- len: content.len(),
- content,
- selected_index,
- })
- }
+ let (_selected_index, content) = tree.into_navigable_content(users);
- /// Creates an empty directory preview.
- pub fn empty(path: &Path, users: &Users) -> Result<Self> {
- Ok(Self {
- tree: Tree::empty(path, users)?,
- len: 0,
- content: vec![],
- selected_index: 0,
- })
+ Self { content }
}
- /// Reset the attributes to default one and free some unused memory.
- pub fn clear(&mut self) {
- self.len = 0;
- self.content = vec![];
- self.selected_index = 0;
- self.tree.clear();
+ pub fn empty() -> Self {
+ Self { content: vec![] }
}
- /// Number of displayed lines.
pub fn len(&self) -> usize {
- self.len
+ self.content.len()
}
- /// True if there's no lines in preview.
pub fn is_empty(&self) -> bool {
- self.len == 0
- }
-
- /// Select the root node and reset the view.
- pub fn select_root(&mut self) -> Result<()> {
- self.tree.select_root();
- (self.selected_index, self.content) = self.tree.into_navigable_content();
- self.update_tree_position_from_index()?;
- Ok(())
- }
-
- /// Unselect every child node.
- pub fn unselect_children(&mut self) {
- self.tree.unselect_children()
- }
-
- /// Select the "next" element of the tree if any.
- /// This is the element immediatly below the current one.
- pub fn select_next(&mut self) -> Result<()> {
- if self.selected_index < self.content.len() {
- self.tree.increase_required_height();
- self.unselect_children();
- self.selected_index += 1;
- self.update_tree_position_from_index()?;
- }
- Ok(())
- }
-
- /// Select the previous sibling if any.
- /// This is the element immediatly below the current one.
- pub fn select_prev(&mut self) -> Result<()> {
- if self.selected_index > 0 {
- self.tree.decrease_required_height();
- self.unselect_children();
- self.selected_index -= 1;
- self.update_tree_position_from_index()?;
- }
- Ok(())
- }
-
- /// Move up 10 times.
- pub fn page_up(&mut self) -> Result<()> {
- if self.selected_index > 10 {
- self.selected_index -= 10;
- } else {
- self.selected_index = 1;
- }
- self.update_tree_position_from_index()
- }
-
- /// Move down 10 times
- pub fn page_down(&mut self) -> Result<()> {
- self.selected_index += 10;
- if self.selected_index > self.content.len() {
- if !self.content.is_empty() {
- self.selected_index = self.content.len();
- } else {
- self.selected_index = 1;
- }
- }
- self.update_tree_position_from_index()
- }
-
- /// Update the position of the selected element from its index.
- pub fn update_tree_position_from_index(&mut self) -> Result<()> {
- self.tree.position = self.tree.position_from_index(self.selected_index);
- let (_, _, node) = self.tree.select_from_position()?;
- self.tree.current_node = node;
- (_, self.content) = self.tree.into_navigable_content();
- Ok(())
- }
-
- /// Select the first child, if any.
- pub fn select_first_child(&mut self) -> Result<()> {
- self.tree.select_first_child()?;
- (self.selected_index, self.content) = self.tree.into_navigable_content();
- self.update_tree_position_from_index()?;
- Ok(())
- }
-
- /// Select the parent of current node.
- pub fn select_parent(&mut self) -> Result<()> {
- self.tree.select_parent()?;
- (self.selected_index, self.content) = self.tree.into_navigable_content();
- self.update_tree_position_from_index()?;
- Ok(())
- }
-
- /// Select the last leaf of the tree (ie the last line.)
- pub fn go_to_bottom_leaf(&mut self) -> Result<()> {
- self.tree.go_to_bottom_leaf()?;
- (self.selected_index, self.content) = self.tree.into_navigable_content();
- self.update_tree_position_from_index()?;
- Ok(())
- }
-
- /// Make a preview of the tree.
- pub fn make_preview(&mut self) {
- (self.selected_index, self.content) = self.tree.into_navigable_content();
- }
-
- /// Calculates the top, bottom and lenght of the view, depending on which element
- /// is selected and the size of the window used to display.
- pub fn calculate_tree_window(&self, terminal_height: usize) -> (usize, usize, usize) {
- let length = self.content.len();
-
- let top: usize;
- let bottom: usize;
- let window_height = terminal_height - ContentWindow::WINDOW_MARGIN_TOP;
- if self.selected_index < terminal_height - 1 {
- top = 0;
- bottom = window_height;
- } else {
- let padding = std::cmp::max(10, terminal_height / 2);
- top = self.selected_index - padding;
- bottom = top + window_height;
- }
-
- (top, bottom, length)
+ self.content.is_empty()
}
}
diff --git a/src/status.rs b/src/status.rs
index 9fe1871..341585c 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -32,7 +32,7 @@ use crate::password::{
drop_sudo_privileges, execute_sudo_command_with_password, reset_sudo_faillock, PasswordHolder,
PasswordKind, PasswordUsage,
};
-use crate::preview::{Directory, Preview};
+use crate::preview::Preview;
use crate::removable_devices::RemovableDevices;
use crate::selectable_content::SelectableContent;
use crate::shell_menu::ShellMenu;
@@ -408,9 +408,9 @@ impl Status {
let dest = match self.selected_non_mut().previous_mode {
Mode::Tree => self
.selected_non_mut()
- .directory
.tree
- .directory_of_selected()?
+ .directory_of_selected()
+ .context("no parent")?
.display()
.to_string(),
_ => self
@@ -582,9 +582,7 @@ impl Status {
/// Drop the current tree, replace it with an empty one.
pub fn remove_tree(&mut self) -> Result<()> {
- let path = self.selected_non_mut().path_content.path.clone();
- let users = &self.selected_non_mut().users;
- self.selected().directory = Directory::empty(&path, users)?;
+ self.selected().tree = FileSystem::empty();
Ok(())
}
@@ -598,12 +596,12 @@ impl Status {
if self.selected_non_mut().path_content.is_empty() {
return Ok(());
}
- let Some(file_info) = self.selected_non_mut().selected() else {
+ let Ok(file_info) = self.selected_non_mut().selected() else {
return Ok(());
};
match file_info.file_kind {
FileKind::NormalFile => {
- let preview = Preview::file(file_info).unwrap_or_default();
+ let preview = Preview::file(&file_info).unwrap_or_default();
self.selected().set_mode(Mode::Preview);
self.selected().window.reset(preview.len());
self.selected().preview = preview;
@@ -652,13 +650,8 @@ impl Status {
.selected()
.context("force preview: No file to select")?;
let preview = match fileinfo.file_kind {
- FileKind::Directory => Preview::directory(
- fileinfo,
- &self.tabs[0].users,
- &self.tabs[0].filter,
- self.tabs[0].show_hidden,
- ),
- _ => Preview::file(fileinfo),
+ FileKind::Directory => Preview::directory(&fileinfo, &self.tabs[0].users),
+ _ => Preview::file(&fileinfo),
};
self.tabs[1].preview = preview.unwrap_or_default();
@@ -691,17 +684,16 @@ impl Status {
/// Open a the selected file with its opener
pub fn open_selected_file(&mut self) -> Result<()> {
- let filepath = &self
- .selected_non_mut()
- .selected()
- .context("Empty directory")?
- .path
- .clone();
- let opener = self.opener.open_info(filepath);
+ let filepath = if matches!(self.selected_non_mut().mode, Mode::Tree) {
+ self.selected_non_mut().tree.selected_path().to_owned()
+ } else {
+ self.selected_non_mut().selected()?.path.to_owned()
+ };
+ let opener = self.opener.open_info(&filepath);
if let Some(InternalVariant::NotSupported) = opener.internal_variant.as_ref() {
self.mount_iso_drive()?;
} else {
- match self.opener.open(filepath) {
+ match self.opener.open(&filepath) {
Ok(_) => (),
Err(e) => info!(
"Error opening {:?}: {:?}",
diff --git a/src/tab.rs b/src/tab.rs
index 2abae8f..ddf6f68 100644
--- a/src/tab.rs
+++ b/src/tab.rs
@@ -13,13 +13,13 @@ use crate::history::History;
use crate::input::Input;
use crate::mode::{InputSimple, Mode};
use crate::opener::execute_in_child;
-use crate::preview::{Directory, Preview};
+use crate::preview::Preview;
use crate::selectable_content::SelectableContent;
use crate::shortcut::Shortcut;
use crate::sort::SortKind;
-use crate::trees::FileSystem;
+use crate::trees::{calculate_tree_window, FileSystem};
use crate::users::Users;
-use crate::utils::{filename_from_path, row_to_window_index, set_clipboard};
+use crate::utils::{row_to_window_index, set_clipboard};
/// Holds every thing about the current tab of the application.
/// Most of the mutation is done externally.
@@ -50,8 +50,6 @@ pub struct Tab {
pub shortcut: Shortcut,
/// Last searched string
pub searched: Option<String>,
- /// Optional tree view
- pub directory: Directory,
/// The filter use before displaying files
pub filter: FilterKind,
/// Visited directories
@@ -76,7 +74,6 @@ impl Tab {
} else {
path.parent().context("")?
};
- let directory = Directory::empty(start_dir, &users)?;
let filter = FilterKind::All;
let show_hidden = args.all || settings.all;
let mut path_content = PathContent::new(start_dir, &users, &filter, show_hidden)?;
@@ -106,7 +103,6 @@ impl Tab {
preview,
shortcut,
searched,
- directory,
filter,
show_hidden,
history,
@@ -135,7 +131,7 @@ impl Tab {
if matches!(self.previous_mode, Mode::Tree) =>
{
self.completion
- .search_from_tree(&self.input.string(), &self.directory.content)
+ .search_from_tree(&self.input.string(), &self.tree.paths())
}
Mode::InputCompleted(InputCompleted::Command) => {
self.completion.command(&self.input.string())
@@ -150,7 +146,7 @@ impl Tab {
self.input.reset();
self.preview = Preview::empty();
self.completion.reset();
- self.directory.clear();
+ self.tree = FileSystem::empty();
Ok(())
}
@@ -303,12 +299,6 @@ impl Tab {
}
}
- /// Select the root node of the tree.
- pub fn tree_select_root(&mut self) -> Result<()> {
- self.directory.unselect_children();
- self.directory.select_root()
- }
-
/// Move to the parent of current path
pub fn move_to_parent(&mut self) -> Result<()> {
let path = self.path_content.path.clone();
@@ -342,13 +332,8 @@ impl Tab {
/// Select the parent of current node.
/// If we were at the root node, move to the parent and make a new tree.
- pub fn tree_select_parent(&mut self) -> Result<()> {
- self.directory.unselect_children();
- if self.directory.tree.position.len() <= 1 {
- self.move_to_parent()?;
- self.make_tree(None)?
- }
- self.directory.select_parent()
+ pub fn tree_select_parent(&mut self) {
+ self.tree.select_parent()
}
/// Move down 10 times in the tree
@@ -378,12 +363,6 @@ impl Tab {
Ok(())
}
- /// Select the first child if any.
- pub fn tree_select_first_child(&mut self) -> Result<()> {
- self.directory.unselect_children();
- self.directory.select_first_child()
- }
-
/// Go to the last leaf.
pub fn tree_go_to_bottom_leaf(&mut self) -> Result<()> {
self.tree.select_last();
@@ -395,19 +374,10 @@ impl Tab {
/// 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 {
+ pub fn current_directory_path(&mut self) -> Option<&path::Path> {
match self.mode {
- 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,
+ Mode::Tree => return self.tree.directory_of_selected(),
+ _ => Some(&self.path_content.path),
}
}
@@ -417,16 +387,23 @@ impl Tab {
/// In normal mode it's the current working directory.
pub fn directory_of_selected(&self) -> Result<&path::Path> {
match self.mode {
- Mode::Tree => self.directory.tree.directory_of_selected(),
+ Mode::Tree => self.tree.directory_of_selected().context("No parent"),
_ => Ok(&self.path_content.path),
}
}
/// Optional Fileinfo of the selected element.
- pub fn selected(&self) -> Option<&FileInfo> {
+ pub fn selected(&self) -> Result<FileInfo> {
match self.mode {
- Mode::Tree => Some(&self.directory.tree.current_node.fileinfo),
- _ => self.path_content.selected(),
+ Mode::Tree => {
+ let node = self.tree.selected_node().context("no selected node")?;
+ node.fileinfo(&self.users)
+ }
+ _ => Ok(self
+ .path_content
+ .selected()
+ .context("no selected file")?
+ .to_owned()),
}
}
@@ -536,11 +513,6 @@ impl Tab {
Ok(())
}
- /// Select the first child of the current node and reset the display.
- pub fn select_first_child(&mut self) -> Result<()> {
- self.tree_select_first_child()
- }
-
/// Copy the selected filename to the clipboard. Only the filename.
pub fn filename_to_clipboard(&self) -> Result<()> {
set_clipboard(
@@ -659,15 +631,12 @@ impl Tab {
}
fn tree_select_row(&mut self, row: u16, 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 screen_index = row_to_window_index(row);
+ let (selected_index, content) = self.tree.into_navigable_content(&self.users);
+ let (top, _, _) = calculate_tree_window(selected_index, term_height, term_height);
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();
- self.directory.tree.current_node = node;
+ let (_, _, colored_path) = content.get(index).context("no selected file")?;
+ self.tree.select_from_path(&colored_path.path);
Ok(())
}
@@ -723,21 +692,21 @@ impl Tab {
}
pub fn rename(&mut self) -> Result<()> {
- if self.selected().is_some() {
- let old_name = match self.mode {
- Mode::Tree => self.directory.tree.current_node.filename(),
- _ => filename_from_path(
- &self
- .path_content
- .selected()
- .context("Event rename: no file in current directory")?
- .path,
- )?
- .to_owned(),
+ let old_name: String = if matches!(self.mode, Mode::Tree) {
+ self.tree
+ .selected_path()
+ .file_name()
+ .context("no filename")?
+ .to_string_lossy()
+ .into()
+ } else {
+ let Ok(fileinfo) = self.selected() else {
+ return Ok(());
};
- self.input.replace(&old_name);
- self.set_mode(Mode::InputSimple(InputSimple::Rename));
- }
+ fileinfo.filename.to_owned()
+ };
+ self.input.replace(&old_name);
+ self.set_mode(Mode::InputSimple(InputSimple::Rename));
Ok(())
}
}
diff --git a/src/term_manager.rs b/src/term_manager.rs
index e7b5749..15bbf61 100644
--- a/src/term_manager.rs
+++ b/src/term_manager.rs
@@ -198,10 +198,10 @@ impl<'a> WinMain<'a> {
match tab.mode {
Mode::Normal | Mode::Tree => {
if !status.display_full {
- let Some(file) = tab.selected() else {
+ let Ok(file) = tab.selected() else {
return Ok(0);
};
- self.second_line_detailed(file, status, canvas)
+ self.second_line_detailed(&file, status, canvas)
} else {
self.second_line_simple(status, canvas)
}
@@ -296,7 +296,7 @@ impl<'a> WinMain<'a> {
]
}
- fn pick_previewed_fileinfo(&self) -> Option<&FileInfo> {
+ fn pick_previewed_fileinfo(&self) -> Result<FileInfo> {
if self.status.dual_pane && self.status.preview_second {
self.status.tabs[0].selected()
} else {
@@ -305,7 +305,7 @@ impl<'a> WinMain<'a> {
}
fn default_preview_first_line(&self, tab: &Tab) -> Vec<String> {
- if let Some(fileinfo) = self.pick_previewed_fileinfo() {
+ if let Ok(fileinfo) = self.pick_previewed_fileinfo() {
let mut strings = vec![" Preview ".to_owned()];
if !tab.preview.is_empty() {
let index = match &tab.preview {
@@ -394,36 +394,6 @@ impl<'a> WinMain<'a> {
Ok(())
}
- fn _tree(&self, status: &Status, tab: &Tab, canvas: &mut dyn Canvas) -> Result<()> {
- let left_margin = if status.display_full { 1 } else { 3 };
- let (_, height) = canvas.size()?;
- let (top, bottom, len) = tab.directory.calculate_tree_window(height);
-
- for (i, (metadata, prefix, colored_string)) in tab.directory.window(top, bottom, len) {
- let row = i + ContentWindow::WINDOW_MARGIN_TOP - top;
- let mut attr = colored_string.color_effect.attr();
- if status.flagged.contains(&colored_string.path) {
- attr.effect |= Effect::BOLD;
- canvas.print_with_attr(row, 0, "█", ATTR_YELLOW_BOLD)?;
- }
-
- let col_metadata = if status.display_full {
- canvas.print_with_attr(row, left_margin, metadata, attr)?
- } else {
- 0
- };
- let col_tree_prefix = canvas.print(row, left_margin + col_metadata, prefix)?;
- canvas.print_with_attr(
- row,
- left_margin + col_metadata + col_tree_prefix,
- &colored_string.text,
- attr,
- )?;
- }
- self.second_line(status, tab, canvas)?;
- Ok(())
- }
-
fn trees(&self, status: &Status, tab: &Tab, canvas: &mut dyn Canvas) -> Result<()> {
let left_margin = if status.display_full { 1 } else { 3 };
let (_, height) = canvas.size()?;
@@ -975,9 +945,9 @@ impl<'a> WinSecondary<'a> {
}
let dest = match tab.previous_mode {
Mode::Tree => tab
- .directory
.tree
- .directory_of_selected()?
+ .directory_of_selected()
+ .context("No directory_of_selected")?
.display()
.to_string(),
_ => tab.path_content.path_to_str(),
diff --git a/src/trees.rs b/src/trees.rs
index 0b77f62..a016ca7 100644
--- a/src/trees.rs
+++ b/src/trees.rs
@@ -143,8 +143,12 @@ impl FileSystem {
}
}
- pub fn sort(&mut self, _sort_kind: SortKind) -> Result<()> {
- todo!()
+ pub fn selected_path(&self) -> &Path {
+ self.selected.as_path()
+ }
+
+ pub fn selected_node(&self) -> Option<&Node> {
+ self.nodes.get(&self.selected)
}
/// Select next sibling or the next sibling of the parent
@@ -215,7 +219,6 @@ impl FileSystem {
}
None
}
-
// TODO! find the bottom child of parent instead of jumping back 1 level
/// Select previous sibling or the parent
pub fn select_prev(&mut self) {
@@ -283,6 +286,32 @@ impl FileSystem {
self.selected = self.last_path.to_owned();
}
+ pub fn select_parent(&mut self) {
+ if let Some(parent_path) = self.selected.parent() {
+ let Some(parent_node) = self.nodes.get_mut(parent_path) else {
+ return;
+ };
+ parent_node.select();
+ let Some(selected_node) = self.nodes.get_mut(&self.selected) else {
+ un