the fastest file manager in the galaxy

This commit is contained in:
rabite 2020-02-11 23:37:38 +01:00
parent 800592338d
commit 74e43ee965
9 changed files with 746 additions and 589 deletions

23
Cargo.lock generated
View File

@ -34,6 +34,14 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "argon2rs"
version = "0.2.5"
@ -63,7 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "async_value"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -580,7 +588,7 @@ name = "hunter"
version = "1.3.5"
dependencies = [
"alphanumeric-sort 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"async_value 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"async_value 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -597,7 +605,7 @@ dependencies = [
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"lscolors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lscolors 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@ -726,10 +734,10 @@ dependencies = [
[[package]]
name = "lscolors"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1553,11 +1561,12 @@ dependencies = [
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum alphanumeric-sort 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f37ce94154d73f6961f87571a3ab7814e1608f373bd55a933e3e771b6dd59fc4"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
"checksum async_value 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "35a62a04436ffd962e78a3301658eac900480d425ea36ec42553aadc572742be"
"checksum async_value 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "82d81baa3badf6d557265cedafc6fc83b4b79567360bbadcfc5ea6eb934885ae"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
@ -1625,7 +1634,7 @@ dependencies = [
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lscolors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9938fd8c379393454f73ec4c9c5b40f3d8332d80b25a29da05e41ee0ecbb559"
"checksum lscolors 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea3b3414b2d015c4fd689815f2551797f3c2296bb241dd709c7da233ec7cba4b"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3"
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"

View File

@ -17,8 +17,8 @@ default-run = "hunter"
termion = "1.5"
unicode-width = "0.1.5"
lazy_static = "1"
alphanumeric-sort = "1.0.6"
lscolors = { version = "0.5.0", features = [ "ansi_term" ] }
alphanumeric-sort = "1.0.11"
lscolors = { version = "0.6.0", features = [ "ansi_term" ] }
tree_magic = "0.2.1"
rayon = "1.3"
dirs-2 = "1.1.0"
@ -32,7 +32,7 @@ parse-ansi = "0.1.6"
signal-notify = "0.1.3"
systemstat = "0.1.5"
mime_guess = "2.0"
async_value = "0.2.6"
async_value = "0.2.7"
osstrtools = "0.2"
pathbuftools = "0.1"
clap = "2.33"

View File

@ -103,7 +103,9 @@ pub enum HError {
#[fail(display = "{}", _0)]
KeyBind(KeyBindError),
#[fail(display = "FileBrowser needs to know about all tab's files to run exec!")]
FileBrowserNeedTabFiles
FileBrowserNeedTabFiles,
#[fail(display = "{}", _0)]
FileError(crate::files::FileError)
}
impl HError {
@ -425,3 +427,9 @@ impl From<ini::ini::Error> for KeyBindError {
KeyBindError::IniError(Arc::new(err))
}
}
impl From<crate::files::FileError> for HError {
fn from(err: crate::files::FileError) -> Self {
HError::FileError(err)
}
}

View File

@ -197,7 +197,7 @@ impl Tabbable for TabView<FileBrowser> {
tab.left_async_widget_mut().map(|async_w| {
async_w.widget.on_ready(move |mut w, _| {
w.as_mut()
.map(|mut w| {
.map(|w| {
if w.content.show_hidden != show_hidden {
w.content.show_hidden = show_hidden;
w.content.recalculate_len();
@ -211,7 +211,7 @@ impl Tabbable for TabView<FileBrowser> {
tab.main_async_widget_mut().map(|async_w| {
async_w.widget.on_ready(move |mut w, _| {
w.as_mut()
.map(|mut w| {
.map(|w| {
if w.content.show_hidden != show_hidden {
w.content.show_hidden = show_hidden;
w.content.recalculate_len();
@ -262,11 +262,9 @@ impl FileBrowser {
let cache = fs_cache.clone();
let main_widget = AsyncWidget::new(&core, move |stale| {
let dir = File::new_from_path(&main_path, None)?;
let dir = File::new_from_path(&main_path)?;
let source = FileSource::Path(dir);
ListView::builder(core_m, source)
.meta_all()
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()
@ -275,11 +273,9 @@ impl FileBrowser {
let cache = fs_cache.clone();
if let Some(left_path) = left_path {
let left_widget = AsyncWidget::new(&core_l.clone(), move |stale| {
let dir = File::new_from_path(&left_path, None)?;
let dir = File::new_from_path(&left_path)?;
let source = FileSource::Path(dir);
ListView::builder(core_l, source)
// .meta_all()
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()
@ -311,7 +307,7 @@ impl FileBrowser {
columns.refresh().log();
let cwd = File::new_from_path(&cwd, None).unwrap();
let cwd = File::new_from_path(&cwd).unwrap();
let proc_view = ProcView::new(&core);
let bookmarks = BMPopup::new(&core);
@ -363,8 +359,6 @@ impl FileBrowser {
};
ListView::builder(core, source)
.meta_all()
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()
@ -380,7 +374,6 @@ impl FileBrowser {
};
ListView::builder(core, source)
.prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()
@ -479,6 +472,10 @@ impl FileBrowser {
}
pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
self.preview_widget_mut()
.map(|p| p.set_stale())
.ok();
let dir = dir.clone();
let cache = self.fs_cache.clone();
@ -489,8 +486,6 @@ impl FileBrowser {
let main_async_widget = self.main_async_widget_mut()?;
main_async_widget.change_to(move |stale: &Stale, core| {
let view = ListView::builder(core, file_source)
.meta_all()
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()?;
@ -507,9 +502,7 @@ impl FileBrowser {
}).log();
}
self.preview_widget_mut()
.map(|p| p.set_stale())
.ok();
Ok(())
}
@ -527,8 +520,6 @@ impl FileBrowser {
let left_async_widget = self.left_async_widget_mut()?;
left_async_widget.change_to(move |stale, core| {
let view = ListView::builder(core, file_source)
// .meta_all()
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()?;
@ -559,8 +550,6 @@ impl FileBrowser {
self.main_async_widget_mut()?.change_to(move |stale, core| {
ListView::builder(core, file_source)
.select(main_selection)
.meta_all()
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()
@ -571,7 +560,6 @@ impl FileBrowser {
let cache = self.fs_cache.clone();
self.left_async_widget_mut()?.change_to(move |stale, core| {
ListView::builder(core, file_source)
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()
@ -612,7 +600,7 @@ impl FileBrowser {
pub fn go_home(&mut self) -> HResult<()> {
let home = crate::paths::home_path().unwrap_or(PathBuf::from("~/"));
let home = File::new_from_path(&home, None)?;
let home = File::new_from_path(&home)?;
self.main_widget_goto(&home)
}
@ -649,7 +637,7 @@ impl FileBrowser {
pub fn goto_bookmark(&mut self) -> HResult<()> {
let path = self.get_boomark()?;
let path = File::new_from_path(&PathBuf::from(path), None)?;
let path = File::new_from_path(&PathBuf::from(path))?;
self.main_widget_goto(&path)?;
Ok(())
}
@ -700,23 +688,35 @@ impl FileBrowser {
let selection = self.cwd()?.clone();
self.cwd.parent_as_file()
.map(|dir| self.fs_cache
.set_selection(dir.clone(), selection.clone())).log();
// Saves doing iteration to find file's position
if let Some(ref current_selection) = self.left_widget()?.current_item {
if current_selection.name == selection.name {
return Ok(());
}
}
self.left_widget_mut()?.select_file(&selection);
let selected_file = self.left_widget()?.selected_file();
self.cwd.parent_as_file()
.map(|dir| {
self.fs_cache
.set_selection(dir.clone(), selected_file.clone())
}).log();
Ok(())
}
pub fn take_main_files(&mut self) -> HResult<Files> {
let mut w = self.main_widget_mut()?;
let w = self.main_widget_mut()?;
let files = std::mem::take(&mut w.content);
w.content.len = 0;
Ok(files)
}
pub fn take_left_files(&mut self) -> HResult<Files> {
let mut w = self.left_widget_mut()?;
let w = self.left_widget_mut()?;
let files = std::mem::take(&mut w.content);
w.content.len = 0;
Ok(files)
@ -879,7 +879,7 @@ impl FileBrowser {
let dir = self.core.minibuffer("cd")?;
let path = std::path::PathBuf::from(&dir);
let dir = File::new_from_path(&path.canonicalize()?, None)?;
let dir = File::new_from_path(&path.canonicalize()?)?;
self.main_widget_goto(&dir)?;
Ok(())
@ -931,11 +931,11 @@ impl FileBrowser {
let path = &paths[0];
if path.exists() {
if path.is_dir() {
let dir = File::new_from_path(&path, None)?;
let dir = File::new_from_path(&path)?;
self.main_widget_goto(&dir).log();
} else if path.is_file() {
let file = File::new_from_path(&path, None)?;
let file = File::new_from_path(&path)?;
let dir = file.parent_as_file()?;
self.main_widget_goto(&dir).log();
@ -964,7 +964,7 @@ impl FileBrowser {
let dir_path = file_path.parent()?;
if self.cwd.path != dir_path {
let file_dir = File::new_from_path(&dir_path, None);
let file_dir = File::new_from_path(&dir_path);
self.main_widget_goto_wait(&file_dir?).log();
}
@ -1033,7 +1033,7 @@ impl FileBrowser {
if path.exists() {
if path.is_dir() {
let dir = File::new_from_path(&path, None)?;
let dir = File::new_from_path(&path)?;
self.main_widget_goto(&dir).log();
}
else {
@ -1231,12 +1231,15 @@ impl Widget for FileBrowser {
let file = self.selected_file()?;
let name = &file.name;
let fcolor = file.get_color();
let color = if file.is_dir() {
crate::term::highlight_color() }
else if file.color.is_none() {
crate::term::normal_color()
} else {
crate::term::from_lscolor(file.color.as_ref().unwrap())
else {
match fcolor {
Some(color) => color,
None => crate::term::normal_color()
}
};
let path = self.cwd.short_string();

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ use std::sync::{Arc, RwLock, Weak};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use crate::files::{Files, File, SortBy};
use crate::widget::Events;
@ -123,10 +123,12 @@ impl FsEventDispatcher {
// fn remove_unnecessary
}
use std::sync::atomic::{AtomicBool, AtomicUsize};
#[derive(Clone)]
pub struct FsCache {
files: Arc<RwLock<HashMap<File, Files>>>,
dirsizes: Arc<RwLock<HashMap<PathBuf, HashMap<PathBuf,
Arc<(AtomicBool, AtomicUsize)>>>>>,
pub tab_settings: Arc<RwLock<HashMap<File, TabSettings>>>,
watched_dirs: Arc<RwLock<HashSet<File>>>,
watcher: Arc<RwLock<RecommendedWatcher>>,
@ -142,6 +144,7 @@ impl FsCache {
let fs_cache = FsCache {
files: Arc::new(RwLock::new(HashMap::new())),
dirsizes: Arc::new(RwLock::new(HashMap::new())),
tab_settings: Arc::new(RwLock::new(HashMap::new())),
watched_dirs: Arc::new(RwLock::new(HashSet::new())),
watcher: Arc::new(RwLock::new(watcher)),
@ -176,7 +179,6 @@ impl FsCache {
cache.fs_event_dispatcher.add_target(&dir,
&files.pending_events).log();
FsCache::apply_settingss(&cache, &mut files).ok();
files.sort();
Ok(files)
});
Ok((selection, files))
@ -227,6 +229,67 @@ impl FsCache {
Ok(self.files.read()?.contains_key(dir))
}
pub fn get_dirsize(&self, dir: &File) -> Option<Arc<(AtomicBool, AtomicUsize)>> {
let parent_dir = dir.parent()
.unwrap_or_else(|| Path::new("/"));
self.dirsizes
.read()
.unwrap()
.get(parent_dir)
.map(|parent_map| {
parent_map.get(&dir.path)
})
.flatten()
.cloned()
}
pub fn make_dirsize(&self, dir: &File) -> Arc<(AtomicBool, AtomicUsize)> {
let parent_dir = dir.parent()
.unwrap_or_else(|| Path::new("/"));
let dir = dir.path.as_path();
let mut dirsizes = self.dirsizes
.write()
.unwrap();
match dirsizes.contains_key(parent_dir) {
false => {
let mut dir_map = HashMap::new();
let ready = AtomicBool::new(false);
let size = AtomicUsize::default();
let dirsize = Arc::new((ready, size));
dir_map.insert(dir.to_path_buf(),
dirsize);
dirsizes.insert(parent_dir.to_path_buf(),
dir_map);
return dirsizes.get(parent_dir)
.unwrap()
.get(dir)
.unwrap()
.clone();
}
true => {
let pmap = dirsizes.get_mut(parent_dir).unwrap();
match pmap.get(dir) {
Some(dirsize) => dirsize.clone(),
None => {
let ready = AtomicBool::new(false);
let size = AtomicUsize::default();
let dirsize = Arc::new((ready, size));
pmap.insert(dir.to_path_buf(), dirsize);
return pmap.get(dir)
.unwrap()
.clone()
}
}
}
}
}
pub fn watch_only(&self, open_dirs: HashSet<File>) -> HResult<()> {
let removable = self.watched_dirs
.read()?
@ -399,18 +462,18 @@ impl TryFrom<DebouncedEvent> for FsEvent {
fn try_from(event: DebouncedEvent) -> HResult<Self> {
let event = match event {
DebouncedEvent::Create(path)
=> FsEvent::Create(File::new_from_path(&path, None)?),
=> FsEvent::Create(File::new_from_path(&path)?),
DebouncedEvent::Remove(path)
=> FsEvent::Remove(File::new_from_path(&path, None)?),
=> FsEvent::Remove(File::new_from_path(&path)?),
DebouncedEvent::Write(path) |
DebouncedEvent::Chmod(path)
=> FsEvent::Change(File::new_from_path(&path, None)?),
=> FsEvent::Change(File::new_from_path(&path)?),
DebouncedEvent::Rename(old_path, new_path)
=> FsEvent::Rename(File::new_from_path(&old_path, None)?,
File::new_from_path(&new_path, None)?),
=> FsEvent::Rename(File::new_from_path(&old_path)?,
File::new_from_path(&new_path)?),
DebouncedEvent::Error(err, path)
=> Err(HError::INotifyError(format!("{}, {:?}", err, path)))?,
@ -435,7 +498,7 @@ fn watch_fs(rx_fs_events: Receiver<DebouncedEvent>,
let dirpath = path.parent()
.map(|path| path)
.unwrap_or(std::path::Path::new("/"));
let dir = File::new_from_path(&dirpath, None)?;
let dir = File::new_from_path(&dirpath)?;
let event = FsEvent::try_from(event)?;
Ok((dir, event))
};

View File

@ -1,11 +1,11 @@
use std::fmt::Debug;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use termion::event::Key;
use unicode_width::UnicodeWidthStr;
use rayon::prelude::*;
use async_value::{Stale, StopIter};
use async_value::Stale;
use crate::files::{File, Files};
use crate::fail::{HResult, HError, ErrorLog};
@ -103,17 +103,6 @@ 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 mut file = self.content
.iter_files()
.nth(0)
.cloned()
.unwrap_or_default();
if file.meta.is_none() {
file.meta_sync().log();
}
self.current_item = Some(file);
Ok(())
}
@ -125,6 +114,17 @@ impl Listable for ListView<Files> {
self.content.len = 1;
}
let meta_upto = self.content.meta_upto.unwrap_or(0);
let ysize = self.core.coordinates.ysize_u();
if self.offset + ysize >= meta_upto {
let sender = self.core.get_sender();
let njobs = self.offset + ysize;
self.content.enqueue_jobs(njobs);
self.content.run_jobs(sender);
}
self.refresh_files().log();
if self.content.is_dirty() {
@ -147,10 +147,8 @@ where
{
pub content: T,
pub current_item: Option<<ListView<T> as Listable>::Item>,
// pub lines: usize,
selection: usize,
pub offset: usize,
//pub buffer: Vec<String>,
pub core: WidgetCore,
seeking: bool,
searching: Option<String>,
@ -165,10 +163,8 @@ where
let mut view = ListView::<T> {
content: content,
current_item: None,
// lines: 0,
selection: 0,
offset: 0,
// buffer: Vec::new(),
core: core.clone(),
seeking: false,
searching: None
@ -248,6 +244,7 @@ where
}
#[derive(PartialEq)]
pub enum FileSource {
Path(File),
Files(Files)
@ -262,7 +259,6 @@ pub struct FileListBuilder {
stale: Option<Stale>,
meta_upto: usize,
meta_all: bool,
prerender: bool
}
impl FileListBuilder {
@ -275,7 +271,6 @@ impl FileListBuilder {
stale: None,
meta_upto: 0,
meta_all: false,
prerender: false
}
}
@ -304,77 +299,58 @@ impl FileListBuilder {
self
}
pub fn prerender(mut self) -> Self {
self.prerender = true;
self
}
pub fn build(mut self) -> HResult<ListView<Files>> {
// Create new IO pool to not block the main render pool, or other busy IO pools
let pool = crate::files::get_pool();
pub fn build(self) -> HResult<ListView<Files>> {
let c = &self.cache;
let s = self.stale.clone();
let files = match self.source {
FileSource::Files(f) => Ok(f),
FileSource::Path(f) => {
c.as_ref()
.map_or_else(| | Files::new_from_path(&f.path),
|c| s.map_or_else(| | c.get_files_sync(&f),
|s| c.get_files_sync_stale(&f, s)))
}
}?;
let core = self.core;
let cfg = core.config();
let source = self.source;
let selected_file = self.selected_file.take();
let mut view = ListView::new(&self.core, files);
let selected_file = match self.selected_file {
Some(f) => Some(f),
None => {
c.as_ref()
.map(|c| c.get_selection(&view.content.directory).ok())
.flatten()
}
// Already sorted
let nosort = match source {
FileSource::Files(_) => true,
_ => false
};
selected_file.map(|mut f| {
f.meta_sync().log();
view.select_file(&f);
});
let from = match self.meta_all {
true => 0,
false => view.offset,
};
let ysize = view.core.coordinates.ysize_u();
let upto = match self.meta_all {
true => view.content.len,
false => from + ysize + 1
};
view.content
.iter_files_mut()
.skip(from)
.take(upto)
.par_bridge()
.for_each(|f| {
f.meta_sync().log();
if f.is_dir() {
f.run_dirsize();
let files = pool.install(|| -> HResult<Files> {
let mut files = match source {
FileSource::Files(f) => Ok(f),
FileSource::Path(f) => {
c.as_ref()
.map_or_else(| | unreachable!(),
|c| s.map_or_else(| | c.get_files_sync(&f),
|s| c.get_files_sync_stale(&f, s)))
}
});
view.content.meta_upto = Some(upto);
}?;
// if self.prerender {
// match self.stale {
// Some(s) => view.render_buffer_stale(s)?,
// None => view.render_buffer()?
// }
// Check/set hidden flag and recalculate number of files if it's different
if !files.show_hidden == cfg.show_hidden() {
files.show_hidden = cfg.show_hidden();
files.recalculate_len();
}
// if view.buffer.len() > 0 {
// view.lines = view.buffer.len() - 1;
// }
// };
// TODO: Fix sorting so it works with lazy/partial sorting
if !nosort {
files.sort();
}
Ok(files)
})?;
let mut view = ListView::new(&core, files);
selected_file
.or_else(|| c.as_ref()
.and_then(|c| c.get_selection(&view.content.directory).ok()))
.map(|f| view.select_file(&f));
self.stale.map(|s| view.content.stale = Some(s));
self.cache.map(|c| view.content.cache = Some(c));
view.content.set_clean();
// view.content.dirty_meta.set_clean();
view.core.set_clean();
Ok(view)
@ -386,6 +362,7 @@ impl ListView<Files>
pub fn builder(core: WidgetCore, source: FileSource) -> FileListBuilder {
FileListBuilder::new(core, source)
}
pub fn update_selected_file(&mut self) {
let pos = self.selection;
@ -398,7 +375,10 @@ impl ListView<Files>
}
pub fn selected_file(&self) -> &File {
self.current_item.as_ref().unwrap()
self.current_item
.as_ref()
.or_else(|| self.content.iter_files().nth(0))
.unwrap()
}
pub fn selected_file_mut(&mut self) -> &mut File {
@ -430,43 +410,39 @@ impl ListView<Files>
self.selected_file().grand_parent()
}
pub fn goto_grand_parent(&mut self) -> HResult<()> {
match self.grand_parent() {
Some(grand_parent) => self.goto_path(&grand_parent),
None => { self.core.show_status("Can't go further!") },
}
}
fn goto_selected(&mut self) -> HResult<()> {
let path = self.selected_file().path();
self.goto_path(&path)
}
pub fn goto_path(&mut self, path: &Path) -> HResult<()> {
match crate::files::Files::new_from_path(path) {
Ok(files) => {
self.content = files;
self.selection = 0;
self.offset = 0;
self.refresh()
}
Err(err) => {
self.core.show_status(&format!("Can't open this path: {}", err))
}
}
}
pub fn select_file(&mut self, file: &File) {
let file = file.clone();
self.current_item = Some(file);
let pos = self
let posfile = self
.content
.iter_files()
.position(|item| item == self.selected_file())
.unwrap_or(0);
self.set_selection(pos);
.collect::<Vec<&File>>()
.into_par_iter()
.enumerate()
.find_any(|(_, item)| item == &&file);
match posfile {
Some((i, file)) => {
self.current_item = Some(file.clone());
self.set_selection(i);
}
// Something went wrong?
None => {
let dir = &self.content.directory.path;
let file = file.path;
HError::wrong_directory::<()>(dir.clone(),
file.clone()).log();
let file = self.content
.iter_files()
.nth(0)
.cloned()
.or_else(|| File::new_placeholder(dir).ok())
.unwrap();
self.current_item = Some(file);
self.set_selection(0);
}
}
}
fn cycle_sort(&mut self) {
@ -570,10 +546,6 @@ impl ListView<Files>
file.toggle_selection();
if !self.content.filter_selected {
//let selection = self.get_selection();
//let line = self.render_line(&file);
//self.buffer[selection] = line;
self.move_down();
} else {
if self.content.filter_selected && self.content.len() == 0 {
@ -610,15 +582,6 @@ 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();
// self.buffer[selection] = line;
self.move_down();
Ok(())
}
@ -773,6 +736,8 @@ impl ListView<Files>
#[allow(trivial_bounds)]
fn render_line_fn(&self) -> impl Fn(&File) -> String {
use std::fmt::Write;
use crate::files::FileError;
let xsize = self.get_coordinates().unwrap().xsize();
let icons = self.core.config().icons;
@ -788,8 +753,13 @@ impl ListView<Files>
let size = file.calculate_size();
let (size, unit) = match size {
Ok((size, unit)) => (size, unit),
Err(_) => (0 as u32, "")
Ok((size, unit)) => (size.to_string(), unit),
Err(HError::FileError(FileError::MetaPending)) => {
// Using mod 5 explicitly here for that nice nonlinear look
let ticks = crate::files::tick_str();
(String::from(ticks), "")
},
Err(_) => (String::from("ERR"), "")
};
let (tag, tag_len) = match file.is_tagged() {
@ -834,18 +804,18 @@ impl ListView<Files>
write!(&mut line, "{}", termion::cursor::Save).unwrap();
match &file.color {
match file.get_color() {
Some(color) => write!(&mut line,
"{}{}{}{}{}{:padding$}{}",
tag,
term::from_lscolor(color),
&color,
selection_color,
selection_gap,
icon,
&sized_string,
term::normal_color(),
padding = padding as usize),
None => write!(&mut line,
_ => write!(&mut line,
"{}{}{}{}{}{:padding$}{}",
tag,
term::normal_color(),
@ -885,55 +855,17 @@ impl ListView<Files>
.collect()
}
fn render_buffer(&mut self) -> HResult<()> {
// let render_fn = self.render_line_fn();
// self.buffer = self.content
// .iter_files()
// .enumerate()
// .map(|(_, file)| {
// render_fn(file)
// })
// .collect();
Ok(())
}
fn render_buffer_stale(&mut self, stale: Stale) -> HResult<()> {
// let render_fn = self.render_line_fn();
// let buffer = self.content
// .iter_files()
// .stop_stale(stale.clone())
// .enumerate()
// .map(|(_, file)| {
// render_fn(file)
// })
// .collect();
// if stale.is_stale()
// .unwrap_or(true) {
// return HError::stale();
// } else {
// self.buffer = buffer;
// return Ok(())
// }
Ok(())
}
fn refresh_files(&mut self) -> HResult<()> {
// if let Ok(Some(mut refresh)) = self.content.get_refresh() {
// let file = self.clone_selected_file();
let file = self.clone_selected_file();
// self.buffer = refresh.new_buffer.take()?;
// self.lines = self.buffer.len() - 1;
if let Ok(Some(_)) = self.content.get_refresh() {
self.select_file(&file);
self.content.run_jobs(self.core.get_sender());
}
// self.select_file(&file);
// }
// if self.content.ready_to_refresh()? {
// let render_fn = self.render_line_fn();
// self.content.process_fs_events(self.buffer.clone(),
// self.core.get_sender(),
// render_fn)?;
// }
if self.content.ready_to_refresh()? {
self.content.process_fs_events(self.core.get_sender())?;
}
Ok(())
}
@ -953,18 +885,10 @@ where
fn refresh(&mut self) -> HResult<()> {
self.on_refresh().log();
// let buffer_len = self.buffer.len();
// self.lines = buffer_len;
if self.selection >= self.len() && self.len() != 0 {
self.selection = self.len() - 1;
}
// if self.core.is_dirty() {
// self.buffer = self.render();
// self.core.set_clean();
// }
Ok(())
}

View File

@ -460,10 +460,9 @@ impl Previewer {
let source = FileSource::Path(file.clone());
let mut file_list = ListView::builder(core.clone(), source)
// .prerender()
.with_cache(cache)
.with_stale(stale.clone())
.build()?;
.with_cache(cache)
.with_stale(stale.clone())
.build()?;
if stale.is_stale()? { return Previewer::preview_failed(&file) }

View File

@ -33,11 +33,8 @@ pub trait PathBufMime {
impl PathBufMime for PathBuf {
fn get_mime(&self) -> HResult<String> {
let mut file = File::new_from_path(&self, None)
let file = File::new_from_path(&self)
.map_err(|e| MimeError::AccessFailed(Box::new(e)))?;
file.meta_sync()
.map_err(|e| MimeError::AccessFailed(Box::new(e)))?;
file.get_mime()
.map(|mime| {