diff --git a/core/src/files/files.rs b/core/src/files/files.rs index 6f3abcbd..c7149069 100644 --- a/core/src/files/files.rs +++ b/core/src/files/files.rs @@ -1,28 +1,27 @@ -use std::{collections::{BTreeMap, BTreeSet}, ops::Range, path::{Path, PathBuf}}; +use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, path::{Path, PathBuf}}; use anyhow::Result; use config::MANAGER; use tokio::fs; -use super::{File, FilesSorter, NonHiddenFiles}; +use super::{File, FilesSorter}; pub struct Files { items: Vec, - length: usize, + hidden: Vec, sizes: BTreeMap, selected: BTreeSet, - pub sorter: FilesSorter, - // TODO: XXX - pub show_hidden: bool, + pub sorter: FilesSorter, + show_hidden: bool, } impl Default for Files { fn default() -> Self { Self { items: Default::default(), - length: Default::default(), + hidden: Default::default(), sizes: Default::default(), selected: Default::default(), @@ -33,6 +32,12 @@ impl Default for Files { } } +impl Deref for Files { + type Target = Vec; + + fn deref(&self) -> &Self::Target { &self.items } +} + impl Files { pub async fn read(paths: &[impl AsRef]) -> Vec { let mut items = Vec::with_capacity(paths.len()); @@ -54,7 +59,9 @@ impl Files { } Ok(items) } +} +impl Files { #[inline] pub fn select(&mut self, path: &Path, state: Option) -> bool { let old = self.selected.contains(path); @@ -104,21 +111,31 @@ impl Files { } #[inline] - pub fn set_show_hidden(&mut self, state: bool) -> bool { - if self.show_hidden == state { + pub fn set_show_hidden(&mut self, state: Option) -> bool { + let state = state.unwrap_or(!self.show_hidden); + if state == self.show_hidden { + return false; + } else if state && self.hidden.is_empty() { return false; } - self.length = - if state { self.items.len() } else { self.items.iter().filter(|f| !f.is_hidden).count() }; + if state { + self.items.append(&mut self.hidden); + self.sorter.sort(&mut self.items); + } else { + let items = mem::take(&mut self.items); + (self.hidden, self.items) = items.into_iter().partition(|f| f.is_hidden); + } + self.show_hidden = state; true } pub fn update_read(&mut self, mut items: Vec) -> bool { + if !self.show_hidden { + (self.hidden, items) = items.into_iter().partition(|f| f.is_hidden); + } self.sorter.sort(&mut items); - self.length = - if self.show_hidden { items.len() } else { items.iter().filter(|f| !f.is_hidden).count() }; self.items = items; true } @@ -131,15 +148,16 @@ impl Files { pub fn update_search(&mut self, items: Vec) -> bool { if !items.is_empty() { - self.length = items.len(); + let (hidden, items): (Vec<_>, Vec<_>) = items.into_iter().partition(|f| f.is_hidden); self.items.extend(items); + self.hidden.extend(hidden); self.sorter.sort(&mut self.items); return true; } if !self.items.is_empty() { - self.length = 0; self.items.clear(); + self.hidden.clear(); return true; } @@ -148,23 +166,7 @@ impl Files { } impl Files { - #[inline] - pub fn len(&self) -> usize { self.length } - - #[inline] - pub fn iter<'a>(&'a self) -> Box + 'a> { - if self.show_hidden { - return Box::new(self.items.iter()); - } - Box::new(NonHiddenFiles::new(&self.items, self.length)) - } - - #[inline] - pub fn range(&self, range: Range) -> Vec<&File> { - self.iter().skip(range.start).take(range.end - range.start).collect() - } - - pub fn pick<'a>(&'a self, indices: &BTreeSet) -> Vec<&'a File> { + pub fn pick(&self, indices: &BTreeSet) -> Vec<&File> { let mut items = Vec::with_capacity(indices.len()); for (i, item) in self.iter().enumerate() { if indices.contains(&i) { @@ -185,7 +187,9 @@ impl Files { return Default::default(); } - let mut items = Vec::with_capacity(self.selected.len() + pending.len()); + let mut items = + Vec::with_capacity(self.selected.len() + if !unset { pending.len() } else { 0 }); + for (i, item) in self.iter().enumerate() { let b = self.selected.contains(&item.path); if !unset && (b || pending.contains(&i)) { @@ -208,3 +212,8 @@ impl Files { self.iter().any(|f| self.selected.contains(&f.path)) } } + +impl Files { + #[inline] + pub fn show_hidden(&self) -> bool { self.show_hidden } +} diff --git a/core/src/files/iterator.rs b/core/src/files/iterator.rs deleted file mode 100644 index 090400dc..00000000 --- a/core/src/files/iterator.rs +++ /dev/null @@ -1,29 +0,0 @@ -use super::File; - -pub struct NonHiddenFiles<'a> { - items: &'a Vec, - - cur: usize, - max: usize, -} - -impl<'a> NonHiddenFiles<'a> { - pub fn new(items: &'a Vec, max: usize) -> Self { Self { items, cur: 0, max } } -} - -impl<'a> Iterator for NonHiddenFiles<'a> { - type Item = &'a File; - - fn next(&mut self) -> Option { - while self.cur < self.items.len() { - let item = &self.items[self.cur]; - self.cur += 1; - if !item.is_hidden { - return Some(&item); - } - } - None - } - - fn size_hint(&self) -> (usize, Option) { (self.max, Some(self.max)) } -} diff --git a/core/src/files/mod.rs b/core/src/files/mod.rs index e3e55b87..59df8d54 100644 --- a/core/src/files/mod.rs +++ b/core/src/files/mod.rs @@ -1,11 +1,9 @@ mod file; mod files; -mod iterator; mod op; mod sorter; pub use file::*; pub use files::*; -pub use iterator::*; pub use op::*; pub use sorter::*; diff --git a/core/src/manager/folder.rs b/core/src/manager/folder.rs index 750ddadc..9b976d64 100644 --- a/core/src/manager/folder.rs +++ b/core/src/manager/folder.rs @@ -93,25 +93,23 @@ impl Folder { } pub fn hidden(&mut self, show: Option) -> bool { - if show.is_none() || self.files.show_hidden != show.unwrap() { - self.files.show_hidden = !self.files.show_hidden; + if self.files.set_show_hidden(show) { emit!(Refresh); } - false } #[inline] - pub fn window(&self) -> Vec<&File> { + pub fn window(&self) -> &[File] { let end = (self.offset + MANAGER.layout.folder_height()).min(self.files.len()); - self.files.range(self.offset..end) + &self.files[self.offset..end] } #[inline] - pub fn window_for(&self, offset: usize) -> Vec<&File> { + pub fn window_for(&self, offset: usize) -> &[File] { let start = offset.min(self.files.len().saturating_sub(1)); let end = (offset + MANAGER.layout.folder_height()).min(self.files.len()); - self.files.range(start..end) + &self.files[start..end] } pub fn hover(&mut self, path: &Path) -> bool { @@ -136,13 +134,13 @@ impl Folder { #[inline] pub fn cursor(&self) -> usize { self.cursor } - pub fn paginate(&self) -> Vec<&File> { + pub fn paginate(&self) -> &[File] { let len = self.files.len(); let limit = MANAGER.layout.folder_height(); let start = (self.page * limit).min(len.saturating_sub(1)); let end = (start + limit).min(len); - self.files.range(start..end) + &self.files[start..end] } pub fn rect_current(&self, path: &Path) -> Option { diff --git a/core/src/manager/tab.rs b/core/src/manager/tab.rs index ac8ff7f4..b381739a 100644 --- a/core/src/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -230,7 +230,7 @@ impl Tab { } let cwd = self.current.cwd.clone(); - let hidden = self.current.files.show_hidden; + let hidden = self.current.files.show_hidden(); self.search = Some(tokio::spawn(async move { let subject = emit!(Input(InputOpt::top("Search:"))).await?; diff --git a/core/src/tasks/tasks.rs b/core/src/tasks/tasks.rs index 82ffe6bc..1428a522 100644 --- a/core/src/tasks/tasks.rs +++ b/core/src/tasks/tasks.rs @@ -227,9 +227,9 @@ impl Tasks { } #[inline] - pub fn precache_mime(&self, targets: Vec<&File>, mimetype: &HashMap) -> bool { + pub fn precache_mime(&self, targets: &[File], mimetype: &HashMap) -> bool { let targets = targets - .into_iter() + .iter() .filter(|f| f.meta.is_file() && !mimetype.contains_key(&f.path)) .map(|f| f.path.clone()) .collect::>();