summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2020-01-23 20:44:10 +0100
committerrabite <rabite@posteo.de>2020-01-23 20:44:10 +0100
commit8fc070b71b0347faa514f3e82f80b009c77201d1 (patch)
treeb612d1c6101e45ce3e475a1a8dfdeb44fe63db01
parentcd773727ebd3fe76f776598b55b3d1f22e8e2b87 (diff)
speedup: make hunter handle directories with 1M files
-rw-r--r--src/file_browser.rs38
-rw-r--r--src/files.rs14
-rw-r--r--src/foldview.rs1
-rw-r--r--src/fscache.rs17
-rw-r--r--src/listview.rs66
-rw-r--r--src/proclist.rs1
-rw-r--r--src/tabview.rs5
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<FileBrowser> {
+ 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<FileBrowser> {
}).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<String> {
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<Item=&mut File> {
@@ -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<Async<usize>>,
pub target: Option<PathBuf>,
@@ -772,6 +778,7 @@ impl File {
name: &str,
path: PathBuf,
dirty_meta: Option<AsyncDirtyBit>) -> 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<AsyncDirtyBit>,
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<Vec<F>>: FoldableWidgetExt,
Bindings<<ListView<Vec<F>> 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<File> {
- 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<File>) -> 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<String>;
fn render_header(&self) -> HResult<String> { Ok("".to_string()) }
@@ -32,6 +34,8 @@ impl Acting for ListView<Files> {
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<Files> {
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<Files> {
ToPrevMtime => self.select_prev_mtime(),
ToggleDirsFirst => self.toggle_dirs_first(),
}
+
+ if pos != self.get_selection() {
+ self.update_selected_file();
+ }
+
Ok(())
}
}
impl Listable for ListView<Files> {
+ type Item = File;
+
fn len(&self) -> usize {
self.content.len()
}
@@ -81,6 +98,12 @@ impl Listable for ListView<Files> {
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<Files> {
}
#[derive(Debug, PartialEq)]
-pub struct ListView<T> where ListView<T>: Listable
+pub struct ListView<T>
+where
+ ListView<T>: Listable
{
pub content: T,
+ pub current_item: Option<<ListView<T> as Listable>::Item>,
pub lines: usize,
selection: usize,
pub offset: usize,
@@ -137,6 +163,7 @@ where
pub fn new(core: &WidgetCore, content: T) -> ListView<T> {
let mut view = ListView::<T> {
content: content,
+ current_item: None,
lines: 0,
selection: 0,
offset: 0,
@@ -222,13 +249,19 @@ where
impl ListView<Files>
{
- 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<Files>
}
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<Files>
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<Files>
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<Files>
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<Files>
}
-impl<T> Widget for ListView<T> where ListView<T>: Listable {
+impl<T> Widget for ListView<T>
+where
+ ListView<T>: 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<Vec<Process>> {
+ type Item = ();
fn len(&self) -> usize { self.content.len() }
fn render(&self) -> Vec<String> {
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<Option<String>>;
- 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)