From 8fc070b71b0347faa514f3e82f80b009c77201d1 Mon Sep 17 00:00:00 2001 From: rabite Date: Thu, 23 Jan 2020 20:44:10 +0100 Subject: speedup: make hunter handle directories with 1M files --- src/file_browser.rs | 38 ++++++++++++++++++------------ src/files.rs | 14 ++++++++++-- src/foldview.rs | 1 + src/fscache.rs | 17 +++++++++++++- src/listview.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++-------- src/proclist.rs | 1 + src/tabview.rs | 5 ++-- 7 files changed, 114 insertions(+), 28 deletions(-) diff --git a/src/file_browser.rs b/src/file_browser.rs index c0b0a0f..f6755a6 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -87,9 +87,12 @@ pub struct FileBrowser { } impl Tabbable for TabView { + type Tab = FileBrowser; + fn new_tab(&mut self) -> HResult<()> { - let cur_tab = self.active_tab_(); + self.active_tab_mut().save_tab_settings().log(); + let cur_tab = self.active_tab(); let settings = cur_tab.fs_cache.tab_settings.read()?.clone(); let cache = cur_tab.fs_cache.new_client(settings).ok(); @@ -136,11 +139,11 @@ impl Tabbable for TabView { }).collect() } - fn active_tab(& self) -> & dyn Widget { + fn active_tab(& self) -> &Self::Tab { self.active_tab_() } - fn active_tab_mut(&mut self) -> &mut dyn Widget { + fn active_tab_mut(&mut self) -> &mut Self::Tab { self.active_tab_mut_() } @@ -274,6 +277,7 @@ impl FileBrowser { let mut list = ListView::new(&core_m.clone(), files); + selected_file.map(|f| list.select_file(&f)); @@ -342,8 +346,7 @@ impl FileBrowser { bookmarks: Arc::new(Mutex::new(bookmarks)), log_view: Arc::new(Mutex::new(log_view)), fs_cache: fs_cache, - fs_stat: Arc::new(RwLock::new(fs_stat)) - }) + fs_stat: Arc::new(RwLock::new(fs_stat)) }) } pub fn enter_dir(&mut self) -> HResult<()> { @@ -486,8 +489,6 @@ impl FileBrowser { } pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> { - self.save_tab_settings().log(); - let dir = dir.clone(); let cache = self.fs_cache.clone(); @@ -730,6 +731,12 @@ impl FileBrowser { Ok(&self.left_widget()?.content) } + pub fn save_selected_file(&self) -> HResult<()> { + self.selected_file() + .map(|f| self.fs_cache.set_selection(self.cwd.clone(), + f))? + } + pub fn save_tab_settings(&mut self) -> HResult<()> { if !self.main_async_widget_mut()?.ready() { return Ok(()) } @@ -1144,11 +1151,8 @@ impl FileBrowser { pub fn get_footer(&self) -> HResult { let xsize = self.get_coordinates()?.xsize(); let ypos = self.get_coordinates()?.position().y(); - let pos = self.main_widget()?.get_selection(); - let file = self.main_widget()? - .content - .iter_files() - .nth(pos)?; + let file = self.selected_file()?; + let permissions = file.pretty_print_permissions().unwrap_or("NOPERMS".into()); let user = file.pretty_user().unwrap_or("NOUSER".into()); @@ -1262,7 +1266,6 @@ impl Widget for FileBrowser { self.set_cwd().log(); if !self.columns.zoom_active { self.update_preview().log(); } self.columns.refresh().log(); - self.save_tab_settings().log(); Ok(()) } @@ -1274,6 +1277,9 @@ impl Widget for FileBrowser { match self.do_key(key) { Err(HError::WidgetUndefinedKeyError{..}) => { match self.main_widget_mut()?.on_key(key) { + Ok(_) => { + self.save_tab_settings()?; + } Err(HError::WidgetUndefinedKeyError{..}) => { self.preview_widget_mut()?.on_key(key)? } @@ -1303,7 +1309,11 @@ impl Acting for FileBrowser { match movement { Left => self.go_back(), Right => self.enter_dir(), - _ => self.main_widget_mut()?.movement(movement) + _ => { + self.main_widget_mut()?.movement(movement)?; + self.save_selected_file()?; + Ok(()) + } } } diff --git a/src/files.rs b/src/files.rs index 7720aa7..fe346f6 100644 --- a/src/files.rs +++ b/src/files.rs @@ -401,7 +401,7 @@ impl Files { !(filter.is_some() && !f.name.contains(filter.as_ref().unwrap())) && (!filter_selected || f.selected)) - .filter(move |f| !(!show_hidden && f.name.starts_with("."))) + .filter(move |f| !(!show_hidden && f.hidden)) } pub fn iter_files_mut(&mut self) -> impl Iterator { @@ -416,7 +416,7 @@ impl Files { !(filter.is_some() && !f.name.contains(filter.as_ref().unwrap())) && (!filter_selected || f.selected)) - .filter(move |f| !(!show_hidden && f.name.starts_with("."))) + .filter(move |f| !(!show_hidden && f.hidden)) } #[allow(trivial_bounds)] @@ -750,12 +750,18 @@ impl std::fmt::Debug for File { } } +impl std::default::Default for File { + fn default() -> File { + File::new_placeholder(Path::new("")).unwrap() + } +} #[derive(Clone)] pub struct File { pub name: String, pub path: PathBuf, + pub hidden: bool, pub kind: Kind, pub dirsize: Option>, pub target: Option, @@ -772,6 +778,7 @@ impl File { name: &str, path: PathBuf, dirty_meta: Option) -> File { + let hidden = name.starts_with("."); let tag = check_tag(&path).ok(); let meta = File::make_async_meta(&path, dirty_meta.clone(), None); let dirsize = if path.is_dir() { @@ -780,6 +787,7 @@ impl File { File { name: name.to_string(), + hidden: hidden, kind: if path.is_dir() { Kind::Directory } else { Kind::File }, path: path, dirsize: dirsize, @@ -797,6 +805,7 @@ impl File { path: PathBuf, dirty_meta: Option, stale: Stale) -> File { + let hidden = name.starts_with("."); let tag = check_tag(&path).ok(); let meta = File::make_async_meta(&path, dirty_meta.clone(), @@ -809,6 +818,7 @@ impl File { File { name: name.to_string(), + hidden: hidden, kind: if path.is_dir() { Kind::Directory } else { Kind::File }, path: path, dirsize: dirsize, diff --git a/src/foldview.rs b/src/foldview.rs index 5310b85..b792721 100644 --- a/src/foldview.rs +++ b/src/foldview.rs @@ -326,6 +326,7 @@ where ListView>: FoldableWidgetExt, Bindings<> as ActingExt>::Action>: Default { + type Item = (); fn len(&self) -> usize { self.content.iter().map(|f| f.lines()).sum() diff --git a/src/fscache.rs b/src/fscache.rs index 9fbc1e8..ff41b0f 100644 --- a/src/fscache.rs +++ b/src/fscache.rs @@ -191,7 +191,22 @@ impl FsCache { } pub fn get_selection(&self, dir: &File) -> HResult { - Ok(self.tab_settings.read()?.get(&dir).as_ref()?.selection.as_ref()?.clone()) + Ok(self.tab_settings + .read()? + .get(&dir) + .as_ref()? + .selection + .as_ref()? + .clone()) + } + + pub fn set_selection(&self, dir: File, selection: File) -> HResult<()> { + self.tab_settings.write() + .map(|mut settings| { + let setting = settings.entry(dir).or_insert(TabSettings::new()); + setting.selection = Some(selection); + })?; + Ok(()) } pub fn save_settings(&self, files: &Files, selection: Option) -> HResult<()> { diff --git a/src/listview.rs b/src/listview.rs index be27dd8..d048b4f 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use termion::event::Key; use unicode_width::UnicodeWidthStr; @@ -10,6 +11,7 @@ use crate::widget::{Widget, WidgetCore}; use crate::dirty::Dirtyable; pub trait Listable { + type Item: Debug + PartialEq + Default; fn len(&self) -> usize; fn render(&self) -> Vec; fn render_header(&self) -> HResult { Ok("".to_string()) } @@ -32,6 +34,8 @@ impl Acting for ListView { fn movement(&mut self, movement: &Movement) -> HResult<()> { use Movement::*; + let pos = self.get_selection(); + match movement { Up(n) => { for _ in 0..*n { self.move_up(); }; self.refresh()?; } Down(n) => { for _ in 0..*n { self.move_down(); }; self.refresh()?; } @@ -42,12 +46,18 @@ impl Acting for ListView { Left | Right => {} } + if pos != self.get_selection() { + self.update_selected_file(); + } + Ok(()) } fn do_action(&mut self, action: &Self::Action) -> HResult<()> { use FileListAction::*; + let pos = self.get_selection(); + match action { Search => self.search_file()?, SearchNext => self.search_next()?, @@ -65,11 +75,18 @@ impl Acting for ListView { ToPrevMtime => self.select_prev_mtime(), ToggleDirsFirst => self.toggle_dirs_first(), } + + if pos != self.get_selection() { + self.update_selected_file(); + } + Ok(()) } } impl Listable for ListView { + type Item = File; + fn len(&self) -> usize { self.content.len() } @@ -81,6 +98,12 @@ impl Listable for ListView { fn on_new(&mut self) -> HResult<()> { let show_hidden = self.core.config().show_hidden(); self.content.show_hidden = show_hidden; + let file = self.content + .iter_files() + .nth(0) + .cloned() + .unwrap_or_default(); + self.current_item = Some(file); Ok(()) } @@ -117,9 +140,12 @@ impl Listable for ListView { } #[derive(Debug, PartialEq)] -pub struct ListView where ListView: Listable +pub struct ListView +where + ListView: Listable { pub content: T, + pub current_item: Option< as Listable>::Item>, pub lines: usize, selection: usize, pub offset: usize, @@ -137,6 +163,7 @@ where pub fn new(core: &WidgetCore, content: T) -> ListView { let mut view = ListView:: { content: content, + current_item: None, lines: 0, selection: 0, offset: 0, @@ -222,13 +249,19 @@ where impl ListView { - pub fn selected_file(&self) -> &File { - let selection = self.selection; + pub fn update_selected_file(&mut self) { + let pos = self.selection; - &self.content + let file = self.content .iter_files() - .nth(selection) - .unwrap_or(&self.content.directory) + .nth(pos) + .map(|f| f.clone()); + + self.current_item = file; + } + + pub fn selected_file(&self) -> &File { + self.current_item.as_ref().unwrap() } pub fn selected_file_mut(&mut self) -> &mut File { @@ -288,6 +321,8 @@ impl ListView } pub fn select_file(&mut self, file: &File) { + self.current_item = Some(file.clone()); + let pos = self .content .iter_files() @@ -375,6 +410,8 @@ impl ListView self.content.toggle_hidden(); self.select_file(&file); self.refresh().log(); + self.core.show_status(&format!("Showing hidden files: {}", + self.content.show_hidden)).log(); } fn toggle_dirs_first(&mut self) { @@ -390,9 +427,13 @@ impl ListView fn multi_select_file(&mut self) { self.selected_file_mut().toggle_selection(); + // Create mutable clone to render change + let mut file = self.clone_selected_file(); + file.toggle_selection(); + if !self.content.filter_selected { let selection = self.get_selection(); - let line = self.render_line(self.selected_file()); + let line = self.render_line(&file); self.buffer[selection] = line; self.move_down(); @@ -432,8 +473,12 @@ impl ListView fn toggle_tag(&mut self) -> HResult<()> { self.selected_file_mut().toggle_tag()?; + // Create a mutable clone to render changes into buffer + let mut file = self.clone_selected_file(); + file.toggle_tag()?; + + let line = self.render_line(&file); let selection = self.get_selection(); - let line = self.render_line(self.selected_file()); self.buffer[selection] = line; self.move_down(); @@ -689,7 +734,10 @@ impl ListView } -impl Widget for ListView where ListView: Listable { +impl Widget for ListView +where + ListView: Listable +{ fn get_core(&self) -> HResult<&WidgetCore> { Ok(&self.core) } diff --git a/src/proclist.rs b/src/proclist.rs index 8f4ca09..b2890cb 100644 --- a/src/proclist.rs +++ b/src/proclist.rs @@ -199,6 +199,7 @@ impl Process { } impl Listable for ListView> { + type Item = (); fn len(&self) -> usize { self.content.len() } fn render(&self) -> Vec { self.content.iter().map(|proc| { diff --git a/src/tabview.rs b/src/tabview.rs index 0b3ca93..388740f 100644 --- a/src/tabview.rs +++ b/src/tabview.rs @@ -5,6 +5,7 @@ use crate::fail::{HResult, HError, ErrorLog}; use crate::coordinates::Coordinates; pub trait Tabbable { + type Tab: Widget; fn new_tab(&mut self) -> HResult<()>; fn close_tab(&mut self) -> HResult<()>; fn next_tab(&mut self) -> HResult<()>; @@ -14,8 +15,8 @@ pub trait Tabbable { Ok(()) } fn get_tab_names(&self) -> Vec>; - fn active_tab(&self) -> &dyn Widget; - fn active_tab_mut(&mut self) -> &mut dyn Widget; + fn active_tab(&self) -> &Self::Tab; + fn active_tab_mut(&mut self) -> &mut Self::Tab; fn on_key_sub(&mut self, key: Key) -> HResult<()>; fn on_key(&mut self, key: Key) -> HResult<()> { self.on_key_sub(key) -- cgit v1.2.3