From 9656f16179bb873c025adac096e4e6d3e3b06e69 Mon Sep 17 00:00:00 2001 From: qkzk Date: Thu, 4 Jan 2024 22:52:57 +0100 Subject: merge flagged & fuzzy --- src/app/header_footer.rs | 20 +++---- src/app/status.rs | 60 +++++++++++---------- src/app/tab.rs | 29 +++-------- src/config/keybindings.rs | 2 +- src/event/action_map.rs | 4 +- src/event/event_exec.rs | 30 +++++------ src/io/display.rs | 37 +++++++------ src/modes/display/fuzzy.rs | 121 ------------------------------------------- src/modes/display/mod.rs | 2 - src/modes/edit/flagged.rs | 120 +++++++++++++++++++++++++++++++++++++----- src/modes/edit/leave_mode.rs | 3 +- src/modes/edit/menu.rs | 2 +- src/modes/mode.rs | 2 +- 13 files changed, 192 insertions(+), 240 deletions(-) delete mode 100644 src/modes/display/fuzzy.rs (limited to 'src') diff --git a/src/app/header_footer.rs b/src/app/header_footer.rs index 14d9214..7bfbfd7 100644 --- a/src/app/header_footer.rs +++ b/src/app/header_footer.rs @@ -299,8 +299,8 @@ mod inner { impl FuzzyHeader { const ACTIONS: [ActionMap; 2] = [ActionMap::ResetMode, ActionMap::OpenFile]; - pub fn new(status: &Status, tab: &Tab) -> Result { - let strings = Self::make_strings(tab); + pub fn new(status: &Status) -> Result { + let strings = Self::make_strings(status); let sizes = Self::make_sizes(&strings); let (width, _) = status.internal_settings.term.term_size()?; @@ -311,10 +311,12 @@ mod inner { }) } - fn make_strings(tab: &Tab) -> Vec { + fn make_strings(status: &Status) -> Vec { vec![ "Fuzzy files".to_owned(), - tab.fuzzy + status + .menu + .flagged .selected() .unwrap_or(&std::path::PathBuf::new()) .to_string_lossy() @@ -384,14 +386,14 @@ mod inner { impl FuzzyFooter { const ACTIONS: [ActionMap; 2] = [ActionMap::Nothing, ActionMap::Jump]; - pub fn new(status: &Status, tab: &Tab) -> Result { + pub fn new(status: &Status) -> Result { let (width, _) = status.internal_settings.term.term_size()?; let used_width = if status.display_settings.use_dual_tab(width) { width / 2 } else { width }; - let raw_strings = Self::make_strings(status, tab); + let raw_strings = Self::make_strings(status); let sizes = Self::make_sizes(&raw_strings); let strings = Footer::make_padded_strings(&raw_strings, used_width); @@ -402,12 +404,12 @@ mod inner { }) } - fn make_strings(status: &Status, tab: &Tab) -> Vec { + fn make_strings(status: &Status) -> Vec { vec![ format!( " {index} / {len}", - index = tab.fuzzy.index + 1, - len = tab.fuzzy.len() + index = status.menu.flagged.index + 1, + len = status.menu.flagged.len() ), format!(" {nb} flags", nb = status.menu.flagged.len()), ] diff --git a/src/app/status.rs b/src/app/status.rs index 26a4fa2..ee66284 100644 --- a/src/app/status.rs +++ b/src/app/status.rs @@ -28,7 +28,6 @@ use crate::io::{ execute_and_capture_output_without_check, execute_sudo_command_with_password, reset_sudo_faillock, }; -use crate::modes::Content; use crate::modes::Display; use crate::modes::Edit; use crate::modes::FileKind; @@ -49,6 +48,7 @@ use crate::modes::Tree; use crate::modes::Users; use crate::modes::{copy_move, regex_matcher}; use crate::modes::{BlockDeviceAction, Navigate}; +use crate::modes::{Content, FileInfo}; use crate::modes::{ContentWindow, CopyMove}; use crate::{log_info, log_line}; @@ -364,9 +364,17 @@ impl Status { self.tabs[1].set_display_mode(Display::Preview); self.set_edit_mode(1, Edit::Nothing)?; - let fileinfo = self.tabs[0] - .current_file() - .context("force preview: No file to select")?; + let fileinfo = match self.tabs[0].display_mode { + Display::Flagged => { + let Some(path) = self.menu.flagged.selected() else { + return Ok(()); + }; + FileInfo::new(path, &self.tabs[0].users)? + } + _ => self.tabs[0] + .current_file() + .context("force preview: No file to select")?, + }; let preview = match fileinfo.file_kind { FileKind::Directory => Preview::directory(&fileinfo, &self.tabs[0].users), _ => Preview::file(&fileinfo), @@ -449,6 +457,7 @@ impl Status { match self.current_tab().display_mode { Display::Preview => (), Display::Tree => (), + Display::Flagged => (), Display::Directory => { self.tabs[self.index] .directory @@ -456,11 +465,6 @@ impl Status { .iter() .for_each(|file| self.menu.flagged.toggle(&file.path)); } - Display::Fuzzy => self.tabs[self.index] - .fuzzy - .content - .iter() - .for_each(|p| self.menu.flagged.toggle(p)), } } @@ -468,7 +472,9 @@ impl Status { pub fn toggle_flag_for_selected(&mut self) { let tab = self.current_tab(); - if matches!(tab.edit_mode, Edit::Nothing) && !matches!(tab.display_mode, Display::Preview) { + if matches!(tab.edit_mode, Edit::Nothing) + && !matches!(tab.display_mode, Display::Preview | Display::Flagged) + { let Ok(file) = tab.current_file() else { return; }; @@ -511,6 +517,11 @@ impl Status { return Ok(()); }; let skim = skimer.search_filename(&self.current_tab().directory_str()); + let paths: Vec = skim + .iter() + .map(|s| std::path::PathBuf::from(s.output().to_string())) + .collect(); + self.menu.flagged.update(paths); let Some(output) = skim.first() else { return Ok(()); }; @@ -531,6 +542,11 @@ impl Status { return Ok(()); }; let skim = skimer.search_line_in_file(&self.current_tab().directory_str()); + let paths: Vec = skim + .iter() + .map(|s| std::path::PathBuf::from(s.output().to_string())) + .collect(); + self.menu.flagged.update(paths); let Some(output) = skim.first() else { return Ok(()); }; @@ -619,13 +635,7 @@ impl Status { let paths = match self.current_tab().display_mode { Display::Directory => self.tabs[self.index].directory.paths(), Display::Tree => self.tabs[self.index].tree.paths(), - Display::Preview => return Ok(()), - Display::Fuzzy => self.tabs[self.index] - .fuzzy - .content - .iter() - .map(|p| p.as_path()) - .collect(), + _ => return Ok(()), }; regex_matcher(&input, &paths, &mut self.menu.flagged)?; Ok(()) @@ -653,15 +663,6 @@ impl Status { .open_multiple(self.menu.flagged.content()) } - pub fn open_all_fuzzy(&mut self) -> Result<()> { - if !matches!(self.current_tab().display_mode, Display::Fuzzy) { - return Ok(()); - }; - self.internal_settings - .opener - .open_multiple(self.tabs[self.index].fuzzy.content()) - } - fn ensure_iso_device_is_some(&mut self) -> Result<()> { if self.menu.iso_device.is_none() { let path = path_to_string(&self.current_tab().current_file()?.path); @@ -997,7 +998,7 @@ impl Status { let is_right = self.index == 1; match self.current_tab().display_mode { Display::Preview => return Ok(()), - Display::Fuzzy => FuzzyHeader::new(self, self.current_tab())? + Display::Flagged => FuzzyHeader::new(self)? .action(col as usize, is_right) .matcher(self, binds), _ => Header::new(self, self.current_tab())? @@ -1061,10 +1062,7 @@ impl Status { } pub fn fuzzy_flags(&mut self) -> Result<()> { - self.tabs[self.index] - .fuzzy - .update(self.menu.flagged.content.clone()); - self.current_tab_mut().set_display_mode(Display::Fuzzy); + self.current_tab_mut().set_display_mode(Display::Flagged); Ok(()) } } diff --git a/src/app/tab.rs b/src/app/tab.rs index b518eb0..18309f9 100644 --- a/src/app/tab.rs +++ b/src/app/tab.rs @@ -8,6 +8,7 @@ use crate::common::{ has_last_modification_happened_less_than, path_to_string, row_to_window_index, set_clipboard, }; use crate::io::Args; +use crate::modes::Content; use crate::modes::Directory; use crate::modes::FileInfo; use crate::modes::FilterKind; @@ -16,7 +17,6 @@ use crate::modes::Preview; use crate::modes::Selectable; use crate::modes::SortKind; use crate::modes::Users; -use crate::modes::{Content, Fuzzy}; use crate::modes::{ContentWindow, FileKind}; use crate::modes::{Display, Edit}; use crate::modes::{Go, To, Tree}; @@ -70,8 +70,6 @@ pub struct Tab { /// Lines of the previewed files. /// Empty if not in preview mode. pub preview: Preview, - /// Fuzzy - pub fuzzy: Fuzzy, /// The edit mode the application is currenty in. /// Most of the time is spent in `EditMode::Nothing` @@ -130,7 +128,6 @@ impl Tab { let searched = None; let index = directory.select_file(&path); let tree = Tree::default(); - let fuzzy = Fuzzy::new(vec![], height); window.scroll_to(index); Ok(Self { @@ -145,7 +142,6 @@ impl Tab { users, tree, settings, - fuzzy, }) } @@ -172,10 +168,6 @@ impl Tab { let node = self.tree.selected_node().context("no selected node")?; node.fileinfo(&self.users) } - Display::Fuzzy => FileInfo::new( - self.fuzzy.selected().context("no selected fuzzy file")?, - &self.users, - ), _ => Ok(self .directory .selected() @@ -190,7 +182,7 @@ impl Tab { Display::Tree => self.tree.display_len(), Display::Preview => self.preview.len(), Display::Directory => self.directory.len(), - Display::Fuzzy => self.fuzzy.len(), + Display::Flagged => 0, } } @@ -217,7 +209,7 @@ impl Tab { Display::Directory => self.directory.filenames_containing(input_string), Display::Tree => self.tree.filenames_containing(input_string), Display::Preview => vec![], - Display::Fuzzy => self.fuzzy.filenames_containing(input_string), + Display::Flagged => vec![], } } @@ -272,7 +264,7 @@ impl Tab { has_last_modification_happened_less_than(&self.directory.path, 10)? } Display::Tree => self.tree.has_modified_dirs(), - Display::Fuzzy => false, // TODO! what to do ????, + Display::Flagged => false, // TODO! what to do ????, } { self.refresh_and_reselect_file() } else { @@ -370,15 +362,7 @@ impl Tab { let index = self.tree.displayable().index(); self.scroll_to(index); } - Display::Fuzzy => { - let index = self - .fuzzy - .content - .iter() - .position(|p| p == &selected_path.to_path_buf()) - .unwrap_or_default(); - self.fuzzy.select_index(index); - } + Display::Flagged => {} } Ok(()) } @@ -518,7 +502,7 @@ impl Tab { } self.tree.go(To::Path(&jump_target)) } - Display::Fuzzy => { + Display::Flagged => { self.set_display_mode(Display::Directory); self.jump(jump_target)?; } @@ -727,7 +711,6 @@ impl Tab { match self.display_mode { Display::Directory => self.normal_select_row(row), Display::Tree => self.tree_select_row(row)?, - Display::Fuzzy => self.fuzzy.select_row(row), _ => (), } Ok(()) diff --git a/src/config/keybindings.rs b/src/config/keybindings.rs index 220b8ab..6ed570d 100644 --- a/src/config/keybindings.rs +++ b/src/config/keybindings.rs @@ -60,7 +60,7 @@ impl Bindings { (Key::Char('C'), ActionMap::Compress), (Key::Char('E'), ActionMap::ToggleDisplayFull), (Key::Char('G'), ActionMap::End), - (Key::Char('F'), ActionMap::DisplayFuzzy), + (Key::Char('F'), ActionMap::DisplayFlagged), (Key::Char('H'), ActionMap::FuzzyFindHelp), (Key::Char('J'), ActionMap::PageDown), (Key::Char('K'), ActionMap::PageUp), diff --git a/src/event/action_map.rs b/src/event/action_map.rs index 5974c61..a21495a 100644 --- a/src/event/action_map.rs +++ b/src/event/action_map.rs @@ -29,7 +29,7 @@ pub enum ActionMap { CutPaste, Delete, DeleteFile, - DisplayFuzzy, + DisplayFlagged, EncryptedDrive, End, Enter, @@ -130,7 +130,7 @@ impl ActionMap { Self::CutPaste => EventAction::cut_paste(status), Self::Delete => EventAction::delete(status), Self::DeleteFile => EventAction::delete_file(status), - Self::DisplayFuzzy => EventAction::display_fuzzy(status), + Self::DisplayFlagged => EventAction::display_flagged(status), Self::EncryptedDrive => EventAction::encrypted_drive(status), Self::End => EventAction::end(status), Self::Enter => EventAction::enter(status, binds), diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index 084f767..db31265 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -70,7 +70,7 @@ impl EventAction { } } else if matches!( status.current_tab().display_mode, - Display::Preview | Display::Fuzzy + Display::Preview | Display::Flagged ) { status.tabs[status.index].set_display_mode(Display::Directory); status.tabs[status.index].refresh_view()?; @@ -138,13 +138,13 @@ impl EventAction { Ok(()) } - pub fn display_fuzzy(status: &mut Status) -> Result<()> { - if matches!(status.current_tab().display_mode, Display::Fuzzy) { + pub fn display_flagged(status: &mut Status) -> Result<()> { + if matches!(status.current_tab().display_mode, Display::Flagged) { status .current_tab_mut() .set_display_mode(Display::Directory); } else { - status.current_tab_mut().set_display_mode(Display::Fuzzy); + status.current_tab_mut().set_display_mode(Display::Flagged); } Ok(()) } @@ -225,7 +225,7 @@ impl EventAction { } fn set_copy_paste(status: &mut Status, copy_or_move: NeedConfirmation) -> Result<()> { - if matches!(status.current_tab().display_mode, Display::Fuzzy) { + if matches!(status.current_tab().display_mode, Display::Flagged) { return Ok(()); }; if status.menu.flagged.is_empty() { @@ -284,7 +284,7 @@ impl EventAction { match status.current_tab_mut().display_mode { Display::Directory => Self::normal_enter_file(status), Display::Tree => Self::tree_enter_file(status), - Display::Fuzzy => Self::jump_fuzzy(status), + Display::Flagged => Self::jump_fuzzy(status), _ => Ok(()), } } @@ -335,7 +335,7 @@ impl EventAction { } pub fn open_all(status: &mut Status) -> Result<()> { - status.open_all_fuzzy() + status.open_flagged_files() } /// Enter the execute mode. Most commands must be executed to allow for @@ -542,7 +542,7 @@ impl EventAction { } pub fn jump_fuzzy(status: &mut Status) -> Result<()> { - let Some(path) = status.current_tab().fuzzy.selected() else { + let Some(path) = status.menu.flagged.selected() else { return Ok(()); }; let path = path.to_owned(); @@ -564,7 +564,7 @@ impl EventAction { Display::Preview => { return Ok(()); } - Display::Fuzzy => todo!("search next"), + Display::Flagged => todo!("search next"), } status.refresh_status()?; status.set_second_pane_for_preview()?; @@ -605,7 +605,7 @@ impl EventAction { Display::Directory => tab.normal_up_one_row(), Display::Preview => tab.preview_page_up(), Display::Tree => tab.tree_select_prev()?, - Display::Fuzzy => tab.fuzzy.select_prev(), + Display::Flagged => status.menu.flagged.select_prev(), } Ok(()) } @@ -616,7 +616,7 @@ impl EventAction { Display::Directory => tab.normal_down_one_row(), Display::Preview => tab.preview_page_down(), Display::Tree => tab.tree_select_next()?, - Display::Fuzzy => tab.fuzzy.select_next(), + Display::Flagged => status.menu.flagged.select_next(), } Ok(()) } @@ -726,7 +726,7 @@ impl EventAction { Display::Directory => tab.normal_go_top(), Display::Preview => tab.preview_go_top(), Display::Tree => tab.tree_go_to_root()?, - Display::Fuzzy => tab.fuzzy.select_first(), + Display::Flagged => status.menu.flagged.select_first(), }; } _ => status.menu.input.cursor_start(), @@ -743,7 +743,7 @@ impl EventAction { Display::Directory => tab.normal_go_bottom(), Display::Preview => tab.preview_go_bottom(), Display::Tree => tab.tree_go_to_bottom_leaf()?, - Display::Fuzzy => tab.fuzzy.select_last(), + Display::Flagged => status.menu.flagged.select_last(), }; } _ => status.menu.input.cursor_end(), @@ -779,7 +779,7 @@ impl EventAction { tab.tree_page_up(); status.update_second_pane_for_preview()?; } - Display::Fuzzy => tab.fuzzy.page_up(), + Display::Flagged => status.menu.flagged.page_up(), }; Ok(()) } @@ -812,7 +812,7 @@ impl EventAction { tab.tree_page_down(); status.update_second_pane_for_preview()?; } - Display::Fuzzy => tab.fuzzy.page_down(), + Display::Flagged => status.menu.flagged.page_down(), }; Ok(()) } diff --git a/src/io/display.rs b/src/io/display.rs index 4211b74..92c4cd9 100644 --- a/src/io/display.rs +++ b/src/io/display.rs @@ -186,7 +186,7 @@ impl<'a> WinMain<'a> { DisplayMode::Directory => self.draw_files(canvas), DisplayMode::Tree => self.draw_tree(canvas), DisplayMode::Preview => self.draw_preview(self.tab, &self.tab.window, canvas), - DisplayMode::Fuzzy => self.draw_fuzzy(canvas), + DisplayMode::Flagged => self.draw_fagged(canvas), } } @@ -545,24 +545,27 @@ impl<'a> WinMain<'a> { Ok(()) } - fn draw_fuzzy(&self, canvas: &mut dyn Canvas) -> Result> { - let attr = Attr::default(); - let window = &self.tab.fuzzy.window; + fn draw_fagged(&self, canvas: &mut dyn Canvas) -> Result> { + let window = &self.status.menu.flagged.window; for (index, path) in self - .tab - .fuzzy + .status + .menu + .flagged .content .iter() .enumerate() .skip(window.top) .take(min(canvas.height()?, window.bottom + 1)) { - let file_info = FileInfo::new(path, &self.tab.users)?; - let mut attr = self.tab.fuzzy.attr(index, &attr); - let row = index + 2 - window.top; - self.print_as_flagged(canvas, row, path, &mut attr)?; - canvas.print_with_attr(row, 4, &file_info.path.to_string_lossy(), attr)?; + let fileinfo = FileInfo::new(path, &self.tab.users)?; + let attr = fileinfo_attr(&fileinfo); + let row = index + 3 - window.top; + canvas.print_with_attr(row, 4, &fileinfo.path.to_string_lossy(), attr)?; } + if let Some(selected) = self.status.menu.flagged.selected() { + let fileinfo = FileInfo::new(selected, &self.tab.users)?; + canvas.print_with_attr(1, 4, &fileinfo.format(6, 6)?, fileinfo_attr(&fileinfo))?; + }; Ok(None) } } @@ -597,10 +600,8 @@ impl<'a> Draw for WinMainHeader<'a> { /// The colors are reversed when the tab is selected. It gives a visual indication of where he is. fn draw(&self, canvas: &mut dyn Canvas) -> DrawResult<()> { let content = match self.tab.display_mode { - DisplayMode::Preview => PreviewHeader::make_preview(self.status, self.tab), - DisplayMode::Fuzzy => FuzzyHeader::new(self.status, self.tab)? - .strings() - .to_owned(), + DisplayMode::Preview => PreviewHeader::strings(self.status, self.tab), + DisplayMode::Flagged => FuzzyHeader::new(self.status)?.strings().to_owned(), _ => Header::new(self.status, self.tab)?.strings().to_owned(), }; draw_colored_strings(0, 0, &content, canvas, self.is_selected)?; @@ -621,7 +622,7 @@ impl<'a> WinMainHeader<'a> { struct PreviewHeader; impl PreviewHeader { - fn make_preview(status: &Status, tab: &Tab) -> Vec { + fn strings(status: &Status, tab: &Tab) -> Vec { match &tab.preview { Preview::Text(text_content) => match text_content.kind { TextKind::HELP => Self::make_help(), @@ -750,9 +751,7 @@ impl<'a> Draw for WinMainFooter<'a> { let height = canvas.height()?; let content = match self.tab.display_mode { DisplayMode::Preview => vec![], - DisplayMode::Fuzzy => FuzzyFooter::new(self.status, self.tab)? - .strings() - .to_owned(), + DisplayMode::Flagged => FuzzyFooter::new(self.status)?.strings().to_owned(), _ => Footer::new(self.status, self.tab)?.strings().to_owned(), }; let mut attr = ATTR_COB_BOLD; diff --git a/src/modes/display/fuzzy.rs b/src/modes/display/fuzzy.rs deleted file mode 100644 index d9ef239..0000000 --- a/src/modes/display/fuzzy.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::ffi::OsStr; -use std::path::PathBuf; - -use crate::impl_content; -use crate::impl_selectable; -use crate::modes::ContentWindow; - -#[derive(Debug)] -pub struct Fuzzy { - pub content: Vec, - pub index: usize, - pub window: ContentWindow, -} - -impl Fuzzy { - pub fn new(content: Vec, 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 push(&mut self, path: PathBuf) { - self.content.push(path); - self.reset_window(); - } - - pub fn reset_window(&mut self) { - self.window.reset(self.content.len()) - } - - pub fn update(&mut self, content: Vec) { - 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 { - 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() - } -} - -impl_content!(PathBuf, Fuzzy); -impl_selectable!(Fuzzy); diff --git a/src/modes/display/mod.rs b/src/modes/display/mod.rs index 05317d5..fb7d52e 100644 --- a/src/modes/display/mod.rs +++ b/src/modes/display/mod.rs @@ -1,7 +1,6 @@ mod content_window; mod directory; mod fileinfo; -mod fuzzy; mod preview; mod skim; mod tree; @@ -13,7 +12,6 @@ pub use fileinfo::{ convert_octal_mode, extract_extension, fileinfo_attr, is_not_hidden, ColorEffect, FileInfo, FileKind, }; -pub use fuzzy::Fuzzy; pub use preview::{ BinaryContent, ColoredText, ExtensionKind, HLContent, Preview, TextKind, TreePreview, Ueberzug, Window, 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, /// The index of the selected file. Used to jump. pub index: usize, + pub window: ContentWindow, } impl Flagged { + pub fn new(content: Vec, 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) { + 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 { + 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); diff --git a/src/modes/edit/leave_mode.rs b/src/modes/edit/leave_mode.rs index b452d90..041d76c 100644 --- a/src/modes/edit/leave_mode.rs +++ b/src/modes/edit/leave_mode.rs @@ -202,11 +202,10 @@ impl LeaveMode { return Err(error); } }; - if matches!(status.current_tab().display_mode, Display::Fuzzy) { + if matches!(status.current_tab().display_mode, Display::Flagged) { if status.menu.flagged.contains(&old_path) { status.menu.flagged.replace(&old_path, &new_path); } - status.current_tab_mut().fuzzy.replace_selected(new_path) } status.current_tab_mut().refresh_view() } diff --git a/src/modes/edit/menu.rs b/src/modes/edit/menu.rs index db3fea2..a2adb76 100644 --- a/src/modes/edit/menu.rs +++ b/src/modes/edit/menu.rs @@ -84,7 +84,7 @@ impl Menu { compression: Compresser::default(), context: ContextMenu::default(), encrypted_devices: CryptoDeviceOpener::default(), - flagged: Flagged::default(), + flagged: Flagged::new(vec![], 80), history: History::default(), input: Input::default(), iso_device: None, diff --git a/src/modes/mode.rs b/src/modes/mode.rs index d1daccd..caf891d 100644 --- a/src/modes/mode.rs +++ b/src/modes/mode.rs @@ -364,5 +364,5 @@ pub enum Display { /// Preview a file or directory Preview, /// Fuzzy - Fuzzy, + Flagged, } -- cgit v1.2.3