diff options
-rw-r--r-- | src/completion.rs | 2 | ||||
-rw-r--r-- | src/event_exec.rs | 73 | ||||
-rw-r--r-- | src/fileinfo.rs | 124 | ||||
-rw-r--r-- | src/indexed_vector.rs | 7 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/shortcut.rs | 23 | ||||
-rw-r--r-- | src/status.rs | 4 | ||||
-rw-r--r-- | src/tab.rs | 17 | ||||
-rw-r--r-- | src/term_manager.rs | 15 | ||||
-rw-r--r-- | src/visited.rs | 56 |
10 files changed, 178 insertions, 144 deletions
diff --git a/src/completion.rs b/src/completion.rs index 9e26e55..cd6eabc 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -192,7 +192,7 @@ impl Completion { fn search(&mut self, input_string: &str, path_content: &PathContent) -> FmResult<()> { self.update( path_content - .files + .content .iter() .filter(|f| f.filename.contains(input_string)) .map(|f| f.filename.clone()) diff --git a/src/event_exec.rs b/src/event_exec.rs index 7d5b59d..a2219f8 100644 --- a/src/event_exec.rs +++ b/src/event_exec.rs @@ -13,6 +13,7 @@ use crate::copy_move::CopyMove; use crate::fileinfo::{FileKind, PathContent}; use crate::filter::FilterKind; use crate::fm_error::{FmError, FmResult}; +use crate::indexed_vector::IndexedVector; use crate::mode::{ConfirmedAction, InputKind, MarkAction, Mode}; use crate::opener::execute_in_child; use crate::preview::Preview; @@ -59,7 +60,7 @@ impl EventExec { pub fn event_flag_all(status: &mut Status) -> FmResult<()> { status.tabs[status.index] .path_content - .files + .content .iter() .for_each(|file| { status.flagged.insert(file.path.clone()); @@ -72,7 +73,7 @@ impl EventExec { pub fn event_reverse_flags(status: &mut Status) -> FmResult<()> { status.tabs[status.index] .path_content - .files + .content .iter() .for_each(|file| { if status.flagged.contains(&file.path.clone()) { @@ -88,7 +89,7 @@ impl EventExec { pub fn event_toggle_flag(status: &mut Status) -> FmResult<()> { let file = status.tabs[status.index] .path_content - .selected_file() + .selected() .ok_or_else(|| FmError::custom("event toggle flag", "No selected file"))?; status.toggle_flag_on_path(file.path.clone()); Self::event_down_one_row(status.selected()); @@ -111,7 +112,7 @@ impl EventExec { /// Change to CHMOD mode allowing to edit permissions of a file. pub fn event_chmod(status: &mut Status) -> FmResult<()> { - if status.selected().path_content.files.is_empty() { + if status.selected().path_content.content.is_empty() { return Ok(()); } status.selected().mode = Mode::InputSimple(InputKind::Chmod); @@ -119,7 +120,7 @@ impl EventExec { status.flagged.insert( status.tabs[status.index] .path_content - .selected_file() + .selected() .unwrap() .path .clone(), @@ -297,7 +298,7 @@ impl EventExec { tab.input.reset(); tab.completion.reset(); tab.path_content.reset_files()?; - tab.window.reset(tab.path_content.files.len()); + tab.window.reset(tab.path_content.content.len()); tab.mode = Mode::Normal; tab.preview = Preview::empty(); Ok(()) @@ -307,7 +308,7 @@ impl EventExec { pub fn event_up_one_row(tab: &mut Tab) { match tab.mode { Mode::Normal => { - tab.path_content.select_prev(); + tab.path_content.prev(); tab.move_line_up(); } Mode::Preview => tab.line_index = tab.window.top, @@ -320,7 +321,7 @@ impl EventExec { pub fn event_down_one_row(tab: &mut Tab) { match tab.mode { Mode::Normal => { - tab.path_content.select_next(); + tab.path_content.next(); tab.move_line_down(); } Mode::Preview => tab.line_index = tab.window.bottom, @@ -363,7 +364,7 @@ impl EventExec { pub fn event_go_bottom(tab: &mut Tab) { let last_index: usize; if let Mode::Normal = tab.mode { - last_index = tab.path_content.files.len() - 1; + last_index = tab.path_content.content.len() - 1; tab.path_content.select_index(last_index); } else { last_index = tab.preview.len() - 1; @@ -388,7 +389,7 @@ impl EventExec { pub fn event_page_down(tab: &mut Tab) { let down_index: usize; if let Mode::Normal = tab.mode { - down_index = min(tab.path_content.files.len() - 1, tab.line_index + 10); + down_index = min(tab.path_content.content.len() - 1, tab.line_index + 10); tab.path_content.select_index(down_index); } else { down_index = min(tab.preview.len() - 1, tab.line_index + 30) @@ -513,10 +514,10 @@ impl EventExec { /// more details on previewinga file. /// Does nothing if the directory is empty. pub fn event_preview(tab: &mut Tab) -> FmResult<()> { - if tab.path_content.files.is_empty() { + if tab.path_content.content.is_empty() { return Ok(()); } - if let Some(file_info) = tab.path_content.selected_file() { + if let Some(file_info) = tab.path_content.selected() { if let FileKind::NormalFile = file_info.file_kind { tab.mode = Mode::Preview; tab.preview = Preview::new(file_info)?; @@ -588,10 +589,10 @@ impl EventExec { /// If the user types an uppercase char, the sort is reverse. pub fn event_leave_sort(tab: &mut Tab, c: char) { tab.mode = Mode::Normal; - if tab.path_content.files.is_empty() { + if tab.path_content.content.is_empty() { return; } - tab.path_content.files[tab.line_index].unselect(); + tab.path_content.content[tab.line_index].unselect(); tab.path_content.update_sort_from_char(c); tab.path_content.sort(); Self::event_go_top(tab); @@ -609,7 +610,7 @@ impl EventExec { tab.path_content.show_hidden = !tab.path_content.show_hidden; tab.path_content.reset_files()?; tab.line_index = 0; - tab.window.reset(tab.path_content.files.len()); + tab.window.reset(tab.path_content.content.len()); Ok(()) } @@ -619,7 +620,7 @@ impl EventExec { status .selected_non_mut() .path_content - .selected_file() + .selected() .ok_or_else(|| FmError::custom("event open file", "Empty directory"))? .path .clone(), @@ -627,7 +628,7 @@ impl EventExec { Ok(_) => (), Err(e) => info!( "Error opening {:?}: {:?}", - status.selected_non_mut().path_content.selected_file(), + status.selected_non_mut().path_content.selected(), e ), } @@ -683,7 +684,8 @@ impl EventExec { pub fn event_right_click(status: &mut Status, row: u16) -> FmResult<()> { if let Mode::Normal = status.selected_non_mut().mode { let tab = status.selected(); - if tab.path_content.files.is_empty() || row as usize > tab.path_content.files.len() + 1 + if tab.path_content.content.is_empty() + || row as usize > tab.path_content.content.len() + 1 { return Err(FmError::custom("event right click", "not found")); } @@ -692,7 +694,7 @@ impl EventExec { tab.window.scroll_to(tab.line_index); if let FileKind::Directory = tab .path_content - .selected_file() + .selected() .ok_or_else(|| FmError::custom("event right click", "not found"))? .file_kind { @@ -715,7 +717,7 @@ impl EventExec { /// reasons unknow to me - it does nothing. /// It requires the "nvim-send" application to be in $PATH. pub fn event_nvim_filepicker(tab: &mut Tab) -> FmResult<()> { - if tab.path_content.files.is_empty() { + if tab.path_content.content.is_empty() { info!("Called nvim filepicker in an empty directory."); return Ok(()); } @@ -740,7 +742,7 @@ impl EventExec { /// Copy the selected filename to the clipboard. Only the filename. pub fn event_filename_to_clipboard(tab: &Tab) -> FmResult<()> { - if let Some(file) = tab.path_content.selected_file() { + if let Some(file) = tab.path_content.selected() { let filename = file.filename.clone(); let mut ctx = ClipboardContext::new()?; ctx.set_contents(filename)?; @@ -770,11 +772,11 @@ impl EventExec { /// Move back in history to the last visited directory. pub fn event_back(tab: &mut Tab) -> FmResult<()> { - if tab.history.visited.len() <= 1 { + if tab.history.content.len() <= 1 { return Ok(()); } - tab.history.visited.pop(); - let last = tab.history.visited[tab.history.len() - 1].clone(); + tab.history.content.pop(); + let last = tab.history.content[tab.history.len() - 1].clone(); tab.set_pathcontent(last)?; Ok(()) @@ -803,7 +805,7 @@ impl EventExec { /// We only tries to rename in the same directory, so it shouldn't be a problem. /// Filename is sanitized before processing. pub fn exec_rename(tab: &mut Tab) -> FmResult<()> { - if tab.path_content.files.is_empty() { + if tab.path_content.content.is_empty() { return Err(FmError::custom("event rename", "Empty directory")); } fs::rename( @@ -857,7 +859,7 @@ impl EventExec { /// be found. /// Optional parameters can be passed normally. ie. `"ls -lah"` pub fn exec_exec(tab: &mut Tab) -> FmResult<()> { - if tab.path_content.files.is_empty() { + if tab.path_content.content.is_empty() { return Err(FmError::custom("exec exec", "empty directory")); } let exec_command = tab.input.string(); @@ -914,7 +916,7 @@ impl EventExec { /// We move the selection to the first matching file. fn search_from(tab: &mut Tab, searched_name: String, mut next_index: usize) { let mut found = false; - for (index, file) in tab.path_content.files.iter().enumerate().skip(next_index) { + for (index, file) in tab.path_content.content.iter().enumerate().skip(next_index) { if file.filename.contains(&searched_name) { next_index = index; found = true; @@ -926,7 +928,7 @@ impl EventExec { tab.line_index = next_index; tab.window.scroll_to(tab.line_index); } else { - for (index, file) in tab.path_content.files.iter().enumerate().take(next_index) { + for (index, file) in tab.path_content.content.iter().enumerate().take(next_index) { if file.filename.starts_with(&searched_name) { next_index = index; found = true; @@ -943,7 +945,7 @@ impl EventExec { pub fn event_search_next(tab: &mut Tab) -> FmResult<()> { if let Some(searched) = tab.searched.clone() { - let next_index = (tab.line_index + 1) % tab.path_content.files.len(); + let next_index = (tab.line_index + 1) % tab.path_content.content.len(); Self::search_from(tab, searched, next_index); } else { } @@ -963,7 +965,7 @@ impl EventExec { tab.input.reset(); tab.history.push(&path); tab.path_content = PathContent::new(path, tab.show_hidden)?; - tab.window.reset(tab.path_content.files.len()); + tab.window.reset(tab.path_content.content.len()); Ok(()) } @@ -971,7 +973,11 @@ impl EventExec { /// It may fail if the user has no permission to visit the path. pub fn exec_shortcut(tab: &mut Tab) -> FmResult<()> { tab.input.reset(); - let path = tab.shortcut.selected(); + let path = tab + .shortcut + .selected() + .ok_or_else(|| FmError::custom("exec shortcut", "empty shortcuts"))? + .to_owned(); tab.history.push(&path); tab.path_content = PathContent::new(path, tab.show_hidden)?; Self::event_normal(tab) @@ -984,7 +990,8 @@ impl EventExec { tab.path_content = PathContent::new( tab.history .selected() - .ok_or_else(|| FmError::custom("exec history", "path unreachable"))?, + .ok_or_else(|| FmError::custom("exec history", "path unreachable"))? + .to_owned(), tab.show_hidden, )?; tab.history.drop_queue(); @@ -1203,7 +1210,7 @@ impl EventExec { pub fn event_thumbnail(tab: &mut Tab) -> FmResult<()> { if let Mode::Normal = tab.mode { tab.mode = Mode::Preview; - if let Some(file_info) = tab.path_content.selected_file() { + if let Some(file_info) = tab.path_content.selected() { tab.preview = Preview::thumbnail(file_info.path.to_owned())?; tab.window.reset(tab.preview.len()); } diff --git a/src/fileinfo.rs b/src/fileinfo.rs index e92c63e..64d43c1 100644 --- a/src/fileinfo.rs +++ b/src/fileinfo.rs @@ -13,6 +13,7 @@ use crate::constant_strings_paths::PERMISSIONS_STR; use crate::filter::FilterKind; use crate::fm_error::{FmError, FmResult}; use crate::git::git; +use crate::indexed_vector::IndexedVector; use crate::sort::SortKind; use crate::status::Status; @@ -211,9 +212,9 @@ pub struct PathContent { /// The current path pub path: path::PathBuf, /// A vector of FileInfo with every file in current path - pub files: Vec<FileInfo>, + pub content: Vec<FileInfo>, /// The index of the selected file. - pub selected: usize, + pub selected_index: usize, /// Do we display the hidden files ? pub show_hidden: bool, /// The kind of sort used to display the files. @@ -232,16 +233,16 @@ impl PathContent { let mut files = Self::files(&path, show_hidden, filter.clone())?; let sort_kind = SortKind::default(); sort_kind.sort(&mut files); - let selected: usize = 0; + let selected_index: usize = 0; if !files.is_empty() { - files[selected].select(); + files[selected_index].select(); } let used_space = get_used_space(&files); Ok(Self { path, - files, - selected, + content: files, + selected_index, show_hidden, sort_kind, filter, @@ -250,13 +251,13 @@ impl PathContent { } pub fn change_directory(&mut self, path: &path::Path) -> FmResult<()> { - self.files = Self::files(path, self.show_hidden, self.filter.clone())?; - self.sort_kind.sort(&mut self.files); - self.selected = 0; - if !self.files.is_empty() { - self.files[0].select() + self.content = Self::files(path, self.show_hidden, self.filter.clone())?; + self.sort_kind.sort(&mut self.content); + self.selected_index = 0; + if !self.content.is_empty() { + self.content[0].select() } - self.used_space = get_used_space(&self.files); + self.used_space = get_used_space(&self.content); self.path = path.to_path_buf(); Ok(()) } @@ -304,20 +305,20 @@ impl PathContent { /// Sort the file with current key. pub fn sort(&mut self) { - self.sort_kind.sort(&mut self.files) + self.sort_kind.sort(&mut self.content) } /// Calculates the size of the owner column. fn owner_column_width(&self) -> usize { let owner_size_btreeset: std::collections::BTreeSet<usize> = - self.files.iter().map(|file| file.owner.len()).collect(); + self.content.iter().map(|file| file.owner.len()).collect(); *owner_size_btreeset.iter().next_back().unwrap_or(&1) } /// Calculates the size of the group column. fn group_column_width(&self) -> usize { let group_size_btreeset: std::collections::BTreeSet<usize> = - self.files.iter().map(|file| file.group.len()).collect(); + self.content.iter().map(|file| file.group.len()).collect(); *group_size_btreeset.iter().next_back().unwrap_or(&1) } @@ -326,42 +327,24 @@ impl PathContent { if display_full { let owner_size = self.owner_column_width(); let group_size = self.group_column_width(); - self.files + self.content .iter() .map(|fileinfo| fileinfo.format(owner_size, group_size).unwrap_or_default()) .collect() } else { - self.files + self.content .iter() .map(|fileinfo| fileinfo.format_simple().unwrap_or_default()) .collect() } } - /// Select the next file, if any. - pub fn select_next(&mut self) { - if !self.files.is_empty() && self.selected < self.files.len() - 1 { - self.files[self.selected].unselect(); - self.selected += 1; - self.files[self.selected].select(); - } - } - - /// Select the previous file, if any. - pub fn select_prev(&mut self) { - if self.selected > 0 { - self.files[self.selected].unselect(); - self.selected -= 1; - self.files[self.selected].select(); - } - } - /// Select the file from a given index. pub fn select_index(&mut self, index: usize) { - if index < self.files.len() { - self.files[self.selected].unselect(); - self.files[index].select(); - self.selected = index; + if index < self.content.len() { + self.content[self.selected_index].unselect(); + self.content[index].select(); + self.selected_index = index; } } @@ -369,29 +352,19 @@ impl PathContent { /// Reads and sort the content with current key. /// Select the first file if any. pub fn reset_files(&mut self) -> Result<(), FmError> { - self.files = Self::files(&self.path, self.show_hidden, self.filter.clone())?; + self.content = Self::files(&self.path, self.show_hidden, self.filter.clone())?; self.sort_kind = SortKind::default(); self.sort(); - self.selected = 0; - if !self.files.is_empty() { - self.files[self.selected].select(); + self.selected_index = 0; + if !self.content.is_empty() { + self.content[self.selected_index].select(); } Ok(()) } - /// Return the Optional FileInfo - /// Since the FileInfo is borrowed it won't be mutable. - pub fn selected_file(&self) -> Option<&FileInfo> { - if self.files.is_empty() { - None - } else { - Some(&self.files[self.selected]) - } - } - /// Path of the currently selected file. pub fn selected_path_str(&self) -> Option<String> { - Some(self.selected_file()?.path.to_str()?.to_owned()) + Some(self.selected()?.path.to_str()?.to_owned()) } /// True if the path starts with a subpath. @@ -403,14 +376,14 @@ impl PathContent { /// It may fails if the current path is empty, aka if nothing is selected. pub fn is_selected_dir(&self) -> FmResult<bool> { match self - .selected_file() + .selected() .ok_or_else(|| FmError::custom("is selected dir", "Empty directory"))? .file_kind { FileKind::Directory => Ok(true), FileKind::SymbolicLink => { let dest = self - .selected_file() + .selected() .ok_or_else(|| FmError::custom("is selected dir", "unreachable"))? .read_dest() .unwrap_or_default(); @@ -422,7 +395,7 @@ impl PathContent { /// True if the path is empty. pub fn is_empty(&self) -> bool { - self.files.is_empty() + self.content.is_empty() } /// Human readable string representation of the space used by _files_ @@ -443,6 +416,43 @@ impl PathContent { } } +impl IndexedVector<FileInfo> for PathContent { + fn is_empty(&self) -> bool { + self.content.is_empty() + } + + fn len(&self) -> usize { + self.content.len() + } + /// Select the next file, if any. + fn next(&mut self) { + if !self.content.is_empty() && self.selected_index < self.content.len() - 1 { + self.content[self.selected_index].unselect(); + self.selected_index += 1; + self.content[self.selected_index].select(); + } + } + + /// Select the previous file, if any. + fn prev(&mut self) { + if self.selected_index > 0 { + self.content[self.selected_index].unselect(); + self.selected_index -= 1; + self.content[self.selected_index].select(); + } + } + + /// Return the Optional FileInfo + /// Since the FileInfo is borrowed it won't be mutable. + fn selected(&self) -> Option<&FileInfo> { + if self.content.is_empty() { + None + } else { + Some(&self.content[self.selected_index]) + } + } +} + /// Associates a filetype to `tuikit::prelude::Attr` : fg color, bg color and /// effect. /// Selected file is reversed. diff --git a/src/indexed_vector.rs b/src/indexed_vector.rs new file mode 100644 index 0000000..07c2312 --- /dev/null +++ b/src/indexed_vector.rs @@ -0,0 +1,7 @@ +pub trait IndexedVector<T> { + fn is_empty(&self) -> bool; + fn len(&self) -> usize; + fn next(&mut self); + fn prev(&mut self); + fn selected(&self) -> Option<&T>; +} @@ -15,6 +15,7 @@ pub mod filter; pub mod fm_error; pub mod git; pub mod help; +pub mod indexed_vector; pub mod input; pub mod keybindings; pub mod log; diff --git a/src/shortcut.rs b/src/shortcut.rs index 4e84529..92826e2 100644 --- a/src/shortcut.rs +++ b/src/shortcut.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use crate::constant_strings_paths::HARDCODED_SHORTCUTS; +use crate::indexed_vector::IndexedVector; /// Holds the hardcoded and mountpoints shortcuts the user can jump to. /// Also know which shortcut is currently selected by the user. @@ -10,7 +11,7 @@ use crate::constant_strings_paths::HARDCODED_SHORTCUTS; pub struct Shortcut { /// The path to the shortcuts. It's a vector since we can't know how much /// mount points are defined. - pub shortcuts: Vec<PathBuf>, + pub content: Vec<PathBuf>, /// The currently selected shortcut pub index: usize, } @@ -27,7 +28,7 @@ impl Shortcut { let mut shortcuts = Self::hardcoded_shortcuts(); shortcuts = Self::with_home_path(shortcuts); Self { - shortcuts, + content: shortcuts, index: 0, } } @@ -49,27 +50,29 @@ impl Shortcut { /// Update the shortcuts with the mount points. pub fn extend_with_mount_points(&mut self, mount_points: &[&Path]) { - self.shortcuts + self.content .extend(mount_points.iter().map(|p| p.to_path_buf())); } /// Refresh the shortcuts. It drops non "hardcoded" shortcuts and /// extend the vector with the mount points. pub fn refresh(&mut self, mount_points: &[&Path]) { - self.shortcuts.truncate(HARDCODED_SHORTCUTS.len() + 1); + self.content.truncate(HARDCODED_SHORTCUTS.len() + 1); self.extend_with_mount_points(mount_points) } +} +impl IndexedVector<PathBuf> for Shortcut { fn is_empty(&self) -> bool { - self.shortcuts.is_empty() + self.content.is_empty() } fn len(&self) -> usize { - self.shortcuts.len() + self.content.len() } /// Select the next shortcut. - pub fn next(&mut self) { + fn next(&mut self) { if self.is_empty() { self.index = 0; } else { @@ -78,7 +81,7 @@ impl Shortcut { } /// Select the previous shortcut. - pub fn prev(&mut self) { + fn prev(&mut self) { if self.is_empty() { self.index = 0 } else if self.index > 0 { @@ -89,7 +92,7 @@ impl Shortcut { } /// Returns the pathbuf of the currently selected shortcut. - pub fn selected(&self) -> PathBuf { - self.shortcuts[self.index].clone() + fn selected(&self) -> Option<&PathBuf> { + Some(&self.content[self.index]) } } diff --git a/src/status.rs b/src/status.rs index a95d648..4f9ad35 100644 --- a/src/status.rs +++ b/src/status.rs @@ -200,7 +200,7 @@ impl Status { pub fn clear_flags_and_reset_view(&mut self) -> FmResult<()> { self.flagged.clear(); self.selected().path_content.reset_files()?; - let len = self.tabs[self.index].path_content.files.len(); + let len = self.tabs[self.index].path_content.content.len(); self.selected().window.reset(len); self.reset_tabs_view() } @@ -221,7 +221,7 @@ impl Status { } self.flagged.clear(); let re = Regex::new(&self.selected_non_mut().input.string())?; - for file in self.tabs[self.index].path_content.files.iter() { + for file in self.tabs[self.index].path_content.content.iter() { if re.is_match(&file.path.to_string_lossy()) { self.flagged.insert(file.path.clone()); } @@ -6,6 +6,7 @@ use crate::content_window::ContentWindow; use crate::fileinfo::PathContent; use crate::filter::FilterKind; use crate::fm_error::{FmError, FmResult}; +use crate::indexed_vector::IndexedVector; use crate::input::Input; use crate::mode::Mode; use crate::preview::Preview; @@ -57,7 +58,7 @@ impl Tab { let nvim_server = args.server; let mode = Mode::Normal; let line_index = 0; - let window = ContentWindow::new(path_content.files.len(), height); + let window = ContentWindow::new(path_content.content.len(), height); let input = Input::default(); let completion = Completion::default(); let must_quit = false; @@ -103,7 +104,7 @@ impl Tab { self.line_index = 0; self.input.reset(); self.path_content.reset_files()?; - self.window.reset(self.path_content.files.len()); + self.window.reset(self.path_content.content.len()); Ok(()) } @@ -113,13 +114,13 @@ impl Tab { pub fn go_to_child(&mut self) -> FmResult<()> { let childpath = self .path_content - .selected_file() + .selected() .ok_or_else(|| FmError::custom("go_to_child", "Empty directory"))? .path .clone(); self.history.push(&childpath); self.path_content = PathContent::new(childpath, self.show_hidden)?; - self.window.reset(self.path_content.files.len()); + self.window.reset(self.path_content.content.len()); self.line_index = 0; self.input.cursor_start(); Ok(()) @@ -149,14 +150,14 @@ impl Tab { pub fn set_pathcontent(&mut self, path: path::PathBuf) -> FmResult<()> { self.history.push(&path); self.path_content.change_directory(&path)?; - self.window.reset(self.path_content.files.len()); + self.window.reset(self.path_content.content.len()); self.line_index = 0; Ok(()) } /// Set the window. Doesn't require the lenght to be known. pub fn set_window(&mut self) { - let len = self.path_content.files.len(); + let len = self.path_content.content.len(); self.window.reset(len); } @@ -169,7 +170,7 @@ impl Tab { /// Returns the correct index jump target to a flagged files. pub fn find_jump_index(&self, jump_target: &path::Path) -> Option<usize> { self.path_content - .files + .content .iter() .position(|file| file.path == jump_target) } @@ -183,7 +184,7 @@ impl Tab { /// Move the index one line down pub fn move_line_down(&mut self) { - let max_line = self.path_content.files.len(); + let max_line = self.path_content.content.len(); if max_line >= ContentWindow::WINDOW_MARGIN_TOP && self.line_index < max_line - ContentWindow::WINDOW_MARGIN_TOP { diff --git a/src/term_manager.rs b/src/term_manager.rs index e86ff83..d01a190 100644 --- a/src/term_manager.rs +++ b/src/term_manager.rs @@ -15,6 +15,7 @@ use crate::constant_strings_paths::{ use crate::content_window::ContentWindow; use crate::fileinfo::fileinfo_attr; use crate::fm_error::{FmError, FmResult}; +use crate::indexed_vector::IndexedVector; use crate::mode::{ConfirmedAction, InputKind, MarkAction, Mode}; use crate::preview::{Preview, TextKind, Window}; use crate::status::Status; @@ -112,7 +113,7 @@ impl<'a> WinTab<'a> { match tab.mode { Mode::Normal => { if !status.display_full { - if let Some(file) = tab.path_content.selected_file() { + if let Some(file) = tab.path_content.selected() { let owner_size = file.owner.len(); let group_size = file.group.len(); let mut attr = fileinfo_attr(status, file, self.colors); @@ -147,7 +148,7 @@ impl<'a> WinTab<'a> { Mode::Normal => { vec![ format!("{} ", tab.path_content.path_to_str()?), - format!("{} files ", tab.path_content.files.len()), + format!("{} files ", tab.path_content.content.len()), format!("{} ", tab.path_content.used_space()), format!("Avail: {} ", disk_space), format!("{} ", &tab.path_content.git_string()?), @@ -182,7 +183,7 @@ impl<'a> WinTab<'a> { } fn default_preview_first_line(tab: &Tab) -> Vec<String> { - match tab.path_content.selected_file() { + match tab.path_content.selected() { Some(fileinfo) => { vec![ format!("{}", tab.mode.clone()), @@ -216,9 +217,9 @@ impl<'a> WinTab<'a> { /// When there's too much files, only those around the selected one are /// displayed. fn files(&self, status: &Status, tab: &Tab, canvas: &mut dyn Canvas) -> FmResult<()> { - let len = tab.path_content.files.len(); + let len = tab.path_content.content.len(); for (i, (file, string)) in std::iter::zip( - tab.path_content.files.iter(), + tab.path_content.content.iter(), tab.path_content.strings(status.display_full).iter(), ) .enumerate() @@ -283,7 +284,7 @@ impl<'a> WinTab<'a> { /// Display the history of visited directories. fn history(&self, tab: &Tab, canvas: &mut dyn Canvas) -> FmResult<()> { canvas.print(0, 0, "Go to...")?; - for (row, path) in tab.history.visited.iter().rev().enumerate() { + for (row, path) in tab.history.content.iter().rev().enumerate() { let mut attr = Attr::default(); if tab.history.len() > tab.history.index |