diff options
Diffstat (limited to 'src/modes/edit/flagged.rs')
-rw-r--r-- | src/modes/edit/flagged.rs | 120 |
1 files changed, 107 insertions, 13 deletions
diff --git a/src/modes/edit/flagged.rs b/src/modes/edit/flagged.rs index 41a5a8a..76be3a7 100644 --- a/src/modes/edit/flagged.rs +++ b/src/modes/edit/flagged.rs @@ -1,9 +1,11 @@ +use std::ffi::OsStr; use std::path::{Path, PathBuf}; use crate::impl_content; use crate::impl_selectable; +use crate::modes::ContentWindow; -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct Flagged { /// Contains the different flagged files. /// It's basically a `Set` (of whatever kind) and insertion would be faster @@ -14,15 +16,117 @@ pub struct Flagged { pub content: Vec<PathBuf>, /// The index of the selected file. Used to jump. pub index: usize, + pub window: ContentWindow, } impl Flagged { + pub fn new(content: Vec<PathBuf>, terminal_height: usize) -> Self { + Self { + window: ContentWindow::new(content.len(), terminal_height), + content, + index: 0, + } + } + + pub fn select_next(&mut self) { + self.next(); + self.window.scroll_down_one(self.index); + } + + pub fn select_prev(&mut self) { + self.prev(); + self.window.scroll_up_one(self.index); + } + + pub fn select_first(&mut self) { + self.index = 0; + self.window.scroll_to(0); + } + + pub fn select_last(&mut self) { + self.index = self.content.len().checked_sub(1).unwrap_or_default(); + self.window.scroll_to(self.index); + } + + /// Set the index to the minimum of given index and the maximum possible index (len - 1) + pub fn select_index(&mut self, index: usize) { + self.index = index.min(self.content.len().checked_sub(1).unwrap_or_default()); + self.window.scroll_to(self.index); + } + + pub fn select_row(&mut self, row: u16) { + let index = row.checked_sub(3).unwrap_or_default() as usize + self.window.top; + self.select_index(index); + } + + pub fn page_down(&mut self) { + for _ in 0..10 { + if self.index + 1 == self.content.len() { + break; + } + self.select_next(); + } + } + + pub fn page_up(&mut self) { + for _ in 0..10 { + if self.index == 0 { + break; + } + self.select_prev(); + } + } + + pub fn reset_window(&mut self) { + self.window.reset(self.content.len()) + } + + pub fn update(&mut self, content: Vec<PathBuf>) { + self.content = content; + self.reset_window(); + self.index = 0; + } + + pub fn clear(&mut self) { + self.content = vec![]; + self.reset_window(); + self.index = 0; + } + + pub fn remove_selected(&mut self) { + self.content.remove(self.index); + self.index.checked_sub(0).unwrap_or_default(); + self.reset_window(); + } + + pub fn replace_selected(&mut self, new_path: PathBuf) { + if self.content.is_empty() { + return; + } + self.content[self.index] = new_path; + } + + pub fn filenames_containing(&self, input_string: &str) -> Vec<String> { + let to_filename: fn(&PathBuf) -> Option<&OsStr> = |path| path.file_name(); + let to_str: fn(&OsStr) -> Option<&str> = |filename| filename.to_str(); + self.content + .iter() + .filter_map(to_filename) + .filter_map(to_str) + .filter(|&p| p.contains(input_string)) + .map(|p| p.to_owned()) + .collect() + } + /// Push a new path into the content. /// We maintain the content sorted and it's used to make `contains` faster. pub fn push(&mut self, path: PathBuf) { match self.content.binary_search(&path) { Ok(_) => (), - Err(pos) => self.content.insert(pos, path), + Err(pos) => { + self.content.insert(pos, path); + self.reset_window() + } } } @@ -39,11 +143,7 @@ impl Flagged { self.content.insert(pos, path_buf); } } - } - - /// Empty the flagged files. - pub fn clear(&mut self) { - self.content.clear(); + self.reset_window(); } /// True if the `path` is flagged. @@ -72,12 +172,6 @@ impl Flagged { .map(|p| p.to_owned()) .collect() } - - /// Remove the selected file from the flagged files. - pub fn remove_selected(&mut self) { - self.content.remove(self.index); - self.index = 0; - } } // impl_selectable_content!(PathBuf, Flagged); |