mirror of https://github.com/bobwen-dev/hunter
use async_value library
This commit is contained in:
parent
01d0c1d338
commit
99980ace6c
|
@ -38,6 +38,18 @@ dependencies = [
|
|||
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async_value"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"objekt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.2"
|
||||
|
@ -254,6 +266,7 @@ name = "hunter"
|
|||
version = "1.1.3"
|
||||
dependencies = [
|
||||
"alphanumeric-sort 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async_value 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs-2 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -476,6 +489,11 @@ name = "numtoa"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "objekt"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.3.5"
|
||||
|
@ -891,6 +909,7 @@ dependencies = [
|
|||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum async_value 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4cd683ef2421e8767b2a0c02b105707812a98a4e1eb0559f615a15e3a80183"
|
||||
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||
"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
|
@ -943,6 +962,7 @@ dependencies = [
|
|||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum objekt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2069a3ae3dad97a4ae47754e8f47e5d2f1fd32ab7ad8a84bb31d051faa59cc3c"
|
||||
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
||||
"checksum osstrtools 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63557d11f265b66ffcda9cc624d5f92315cfeebb7ee01c76257f890f7d730f5b"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
|
|
|
@ -31,6 +31,7 @@ signal-notify = "0.1.3"
|
|||
systemstat = "0.1.4"
|
||||
osstrtools = "0.1"
|
||||
pathbuftools = "0.1"
|
||||
async_value = "0.2.2"
|
||||
|
||||
[patch.crates-io]
|
||||
systemstat = { git = 'https://github.com/myfreeweb/systemstat' }
|
||||
|
|
|
@ -1 +1 @@
|
|||
nightly-2019-03-15
|
||||
nightly-2019-04-28
|
||||
|
|
55
src/fail.rs
55
src/fail.rs
|
@ -1,6 +1,8 @@
|
|||
use failure;
|
||||
use failure::Fail;
|
||||
//use failure::Backtrace;
|
||||
use async_value::AError;
|
||||
|
||||
|
||||
use termion::event::Key;
|
||||
|
||||
|
@ -47,6 +49,8 @@ pub enum HError {
|
|||
AsyncAlreadyStartedError,
|
||||
#[fail(display = "Async Error: {}", _0)]
|
||||
AsyncError(String),
|
||||
#[fail(display = "Async Error: {}", _0)]
|
||||
AError(async_value::AError),
|
||||
#[fail(display = "No widget found")]
|
||||
NoWidgetError,
|
||||
#[fail(display = "Path: {:?} not in this directory: {:?}", path, dir)]
|
||||
|
@ -209,7 +213,6 @@ pub trait ErrorLog where Self: Sized {
|
|||
impl<T> ErrorLog for HResult<T> {
|
||||
fn log(self) {
|
||||
if let Err(err) = self {
|
||||
// eprintln!("{:?}", err);
|
||||
put_log(&err).ok();
|
||||
}
|
||||
}
|
||||
|
@ -223,101 +226,97 @@ impl<T> ErrorLog for HResult<T> {
|
|||
}
|
||||
|
||||
|
||||
impl<T> ErrorLog for Result<T, AError> {
|
||||
fn log(self) {
|
||||
if let Err(err) = self {
|
||||
put_log(&err.into()).ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn log_and(self) -> Self {
|
||||
if let Err(err) = &self {
|
||||
put_log(&err.clone().into()).ok();
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// impl From<&HError> for HError {
|
||||
// fn from(error: &HError) -> Self {
|
||||
// dbg!(&error);
|
||||
// (error.clone())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl From<std::io::Error> for HError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::IoError(format!("{}", error));
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<failure::Error> for HError {
|
||||
fn from(error: failure::Error) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::Error(format!("{}", error));
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::sync::mpsc::TryRecvError> for HError {
|
||||
fn from(error: std::sync::mpsc::TryRecvError) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::ChannelTryRecvError { error: error };
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::sync::mpsc::RecvError> for HError {
|
||||
fn from(error: std::sync::mpsc::RecvError) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::ChannelRecvError { error: error };
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<std::sync::mpsc::SendError<T>> for HError {
|
||||
fn from(error: std::sync::mpsc::SendError<T>) -> Self {
|
||||
dbg!(&error);
|
||||
fn from(_error: std::sync::mpsc::SendError<T>) -> Self {
|
||||
let err = HError::ChannelSendError;
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<std::sync::PoisonError<T>> for HError {
|
||||
fn from(_: std::sync::PoisonError<T>) -> Self {
|
||||
// dbg!("Poisoned Mutex");
|
||||
let err = HError::MutexError;
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<std::sync::TryLockError<T>> for HError {
|
||||
fn from(_error: std::sync::TryLockError<T>) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::TryLockError;
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::option::NoneError> for HError {
|
||||
fn from(_error: std::option::NoneError) -> Self {
|
||||
//dbg!(&error);
|
||||
let err = HError::NoneError;
|
||||
//put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::path::StripPrefixError> for HError {
|
||||
fn from(error: std::path::StripPrefixError) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::StripPrefixError{error: error };
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<notify::Error> for HError {
|
||||
fn from(error: notify::Error) -> Self {
|
||||
// dbg!(&error);
|
||||
let err = HError::INotifyError(format!("{}", error));
|
||||
put_log(&err).ok();
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<async_value::AError> for HError {
|
||||
fn from(error: async_value::AError) -> Self {
|
||||
let err = HError::AError(error);
|
||||
err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use termion::event::Key;
|
||||
use pathbuftools::PathBufTools;
|
||||
use osstrtools::OsStrTools;
|
||||
use async_value::Stale;
|
||||
|
||||
use std::io::Write;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
@ -196,24 +197,33 @@ impl Tabbable for TabView<FileBrowser> {
|
|||
}
|
||||
|
||||
fn on_config_loaded(&mut self) -> HResult<()> {
|
||||
// hack: wait a bit for widget readyness...
|
||||
let duration = std::time::Duration::from_millis(100);
|
||||
std::thread::sleep(duration);
|
||||
|
||||
let show_hidden = self.config().show_hidden();
|
||||
for tab in self.widgets.iter_mut() {
|
||||
tab.left_widget_mut().map(|w| {
|
||||
w.content.show_hidden = show_hidden;
|
||||
w.content.dirty_meta.set_dirty();
|
||||
w.refresh().log();
|
||||
}).ok();
|
||||
|
||||
tab.main_widget_mut().map(|w| {
|
||||
w.content.show_hidden = show_hidden;
|
||||
w.content.dirty_meta.set_dirty();
|
||||
w.content.sort();
|
||||
w.refresh().log();
|
||||
}).ok();
|
||||
for tab in self.widgets.iter_mut() {
|
||||
tab.left_async_widget_mut().map(|async_w| {
|
||||
async_w.widget.on_ready(move |mut w, _| {
|
||||
w.as_mut()
|
||||
.map(|mut w| {
|
||||
w.content.show_hidden = show_hidden;
|
||||
w.content.dirty_meta.set_dirty();
|
||||
w.refresh().log();
|
||||
}).ok();
|
||||
Ok(())
|
||||
}).log();
|
||||
}).log();
|
||||
|
||||
tab.main_async_widget_mut().map(|async_w| {
|
||||
async_w.widget.on_ready(move |mut w, _| {
|
||||
w.as_mut()
|
||||
.map(|mut w| {
|
||||
w.content.show_hidden = show_hidden;
|
||||
w.content.dirty_meta.set_dirty();
|
||||
w.content.sort();
|
||||
w.refresh().log();
|
||||
}).ok();
|
||||
Ok(())
|
||||
}).log()
|
||||
}).log();
|
||||
|
||||
tab.preview_widget_mut().map(|w| w.config_loaded()).ok();
|
||||
}
|
||||
|
@ -252,7 +262,7 @@ impl FileBrowser {
|
|||
let left_path = main_path.parent().map(|p| p.to_path_buf());
|
||||
|
||||
let cache = fs_cache.clone();
|
||||
let main_widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let main_widget = AsyncWidget::new(&core, move |_| {
|
||||
let name = if main_path.parent().is_none() {
|
||||
"root".to_string()
|
||||
} else {
|
||||
|
@ -277,11 +287,11 @@ impl FileBrowser {
|
|||
list.refresh().log();
|
||||
|
||||
Ok(list)
|
||||
}));
|
||||
});
|
||||
|
||||
let cache = fs_cache.clone();
|
||||
if let Some(left_path) = left_path {
|
||||
let left_widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let left_widget = AsyncWidget::new(&core, move |_| {
|
||||
let name = if left_path.parent().is_none() {
|
||||
"root".to_string()
|
||||
} else {
|
||||
|
@ -303,14 +313,14 @@ impl FileBrowser {
|
|||
list.refresh().log();
|
||||
|
||||
Ok(list)
|
||||
}));
|
||||
});
|
||||
let left_widget = FileBrowserWidgets::FileList(left_widget);
|
||||
columns.push_widget(left_widget);
|
||||
} else {
|
||||
let left_widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let left_widget = AsyncWidget::new(&core, move |_| {
|
||||
let blank = TextView::new_blank(&core_l);
|
||||
Ok(blank)
|
||||
}));
|
||||
});
|
||||
|
||||
let left_widget = FileBrowserWidgets::Blank(left_widget);
|
||||
columns.push_widget(left_widget);
|
||||
|
@ -372,7 +382,7 @@ impl FileBrowser {
|
|||
let core = self.core.clone();
|
||||
let cache = self.fs_cache.clone();
|
||||
|
||||
let main_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
|
||||
let main_widget = AsyncWidget::new(&core.clone(), move |_| {
|
||||
let files = match previewer_files {
|
||||
Some(files) => files,
|
||||
None => cache.get_files_sync(&dir)?
|
||||
|
@ -389,7 +399,7 @@ impl FileBrowser {
|
|||
list.content.meta_all();
|
||||
|
||||
Ok(list)
|
||||
}));
|
||||
});
|
||||
|
||||
let main_widget = FileBrowserWidgets::FileList(main_widget);
|
||||
self.columns.insert_widget(1, main_widget);
|
||||
|
@ -492,9 +502,9 @@ impl FileBrowser {
|
|||
self.cwd = dir.clone();
|
||||
|
||||
let main_async_widget = self.main_async_widget_mut()?;
|
||||
main_async_widget.change_to(Box::new(move |stale, core| {
|
||||
let (selected_file, files) = cache.get_files(&dir, stale)?;
|
||||
let files = files.wait()?;
|
||||
main_async_widget.change_to(move |stale: &Stale, core| {
|
||||
let (selected_file, files) = cache.get_files(&dir, stale.clone())?;
|
||||
let files = files.run_sync()?;
|
||||
|
||||
let mut list = ListView::new(&core, files);
|
||||
|
||||
|
@ -505,14 +515,14 @@ impl FileBrowser {
|
|||
list.select_file(&file);
|
||||
}
|
||||
Ok(list)
|
||||
})).log();
|
||||
}).log();
|
||||
|
||||
if let Ok(grand_parent) = self.cwd()?.parent_as_file() {
|
||||
self.left_widget_goto(&grand_parent).log();
|
||||
} else {
|
||||
self.left_async_widget_mut()?.change_to(Box::new(move |_,_| {
|
||||
self.left_async_widget_mut()?.change_to(move |_,_| {
|
||||
HError::stale()?
|
||||
})).log();
|
||||
}).log();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -530,15 +540,15 @@ impl FileBrowser {
|
|||
let dir = dir.clone();
|
||||
|
||||
let left_async_widget = self.left_async_widget_mut()?;
|
||||
left_async_widget.change_to(Box::new(move |stale, core| {
|
||||
let cached_files = cache.get_files(&dir, stale)?;
|
||||
left_async_widget.change_to(move |stale, core| {
|
||||
let cached_files = cache.get_files(&dir, stale.clone())?;
|
||||
let (_, files) = cached_files;
|
||||
|
||||
let files = files.wait()?;
|
||||
let files = files.run_sync()?;
|
||||
|
||||
let list = ListView::new(&core, files);
|
||||
Ok(list)
|
||||
}))?;
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -552,19 +562,19 @@ impl FileBrowser {
|
|||
|
||||
if let Ok(left_dir) = new_cwd.parent_as_file() {
|
||||
let cache = self.fs_cache.clone();
|
||||
let left_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
|
||||
let left_widget = AsyncWidget::new(&core.clone(), move |_| {
|
||||
let files = cache.get_files_sync(&left_dir)?;
|
||||
let list = ListView::new(&core, files);
|
||||
Ok(list)
|
||||
}));
|
||||
});
|
||||
|
||||
let left_widget = FileBrowserWidgets::FileList(left_widget);
|
||||
self.columns.prepend_widget(left_widget);
|
||||
} else {
|
||||
let left_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
|
||||
let left_widget = AsyncWidget::new(&core.clone(), move |_| {
|
||||
let blank = TextView::new_blank(&core);
|
||||
Ok(blank)
|
||||
}));
|
||||
});
|
||||
|
||||
let left_widget = FileBrowserWidgets::Blank(left_widget);
|
||||
self.columns.prepend_widget(left_widget);
|
||||
|
@ -669,9 +679,9 @@ impl FileBrowser {
|
|||
|
||||
pub fn take_main_files(&mut self) -> HResult<Files> {
|
||||
let core = self.core.clone();
|
||||
let blank = AsyncWidget::new(&core.clone(), Box::new(move |_| {
|
||||
let blank = AsyncWidget::new(&core.clone(), move |_| {
|
||||
HError::no_files()
|
||||
}));
|
||||
});
|
||||
let blank = FileBrowserWidgets::Blank(blank);
|
||||
|
||||
let old_widget = self.columns.replace_widget(1, blank);
|
||||
|
@ -685,9 +695,9 @@ impl FileBrowser {
|
|||
|
||||
pub fn take_left_files(&mut self) -> HResult<Files> {
|
||||
let core = self.core.clone();
|
||||
let blank = AsyncWidget::new(&core.clone(), Box::new(move |_| {
|
||||
let blank = AsyncWidget::new(&core.clone(), move |_| {
|
||||
HError::no_files()
|
||||
}));
|
||||
});
|
||||
let blank = FileBrowserWidgets::FileList(blank);
|
||||
|
||||
let old_widget = self.columns.replace_widget(0, blank);
|
||||
|
@ -930,9 +940,14 @@ impl FileBrowser {
|
|||
let file = File::new_from_path(&path, None)?;
|
||||
let dir = file.parent_as_file()?;
|
||||
|
||||
self.main_widget_goto_wait(&dir).log();
|
||||
self.main_widget_goto(&dir).log();
|
||||
|
||||
self.main_widget_mut()?.select_file(&file);
|
||||
self.main_async_widget_mut()?
|
||||
.widget
|
||||
.on_ready(move |w, _| {
|
||||
w?.select_file(&file);
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
} else {
|
||||
let msg = format!("Can't access path: {}!",
|
||||
|
|
91
src/files.rs
91
src/files.rs
|
@ -19,10 +19,10 @@ use notify::DebouncedEvent;
|
|||
use rayon::{ThreadPool, ThreadPoolBuilder};
|
||||
use alphanumeric_sort::compare_str;
|
||||
use pathbuftools::PathBufTools;
|
||||
use async_value::{Async, Stale};
|
||||
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
use crate::dirty::{AsyncDirtyBit, DirtyBit, Dirtyable};
|
||||
use crate::preview::{Async, Stale};
|
||||
use crate::widget::Events;
|
||||
use crate::icon::Icons;
|
||||
|
||||
|
@ -186,7 +186,7 @@ impl Files {
|
|||
let files: Vec<_> = direntries?
|
||||
.iter()
|
||||
.map(|file| {
|
||||
if crate::preview::is_stale(&stale).unwrap() {
|
||||
if stale.is_stale().ok()? {
|
||||
None
|
||||
} else {
|
||||
let name = file.file_name();
|
||||
|
@ -202,7 +202,7 @@ impl Files {
|
|||
.flatten()
|
||||
.collect();
|
||||
|
||||
if crate::preview::is_stale(&stale).unwrap() {
|
||||
if stale.is_stale()? {
|
||||
return Err(crate::fail::HError::StalePreviewError {
|
||||
file: path.to_string_lossy().to_string()
|
||||
})?;
|
||||
|
@ -580,8 +580,15 @@ impl Hash for File {
|
|||
|
||||
impl Eq for File {}
|
||||
|
||||
impl std::fmt::Debug for File {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
write!(formatter, "{:?}", self.path)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct File {
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
|
@ -682,23 +689,20 @@ impl File {
|
|||
stale_preview: Option<Stale>) -> Async<Metadata> {
|
||||
let path = path.clone();
|
||||
|
||||
let meta_closure = Box::new(move |stale: Stale| {
|
||||
let mut meta = Async::new(move |stale: &Stale| {
|
||||
if stale.is_stale()? { HError::stale()? }
|
||||
Ok(std::fs::symlink_metadata(&path)?)
|
||||
});
|
||||
|
||||
let mut meta = match stale_preview {
|
||||
Some(stale) => Async::new_with_stale(meta_closure, stale),
|
||||
None => Async::new(meta_closure)
|
||||
};
|
||||
if let Some(dirty_meta) = dirty_meta {
|
||||
meta.on_ready(Box::new(move || {
|
||||
let mut dirty_meta = dirty_meta.clone();
|
||||
dirty_meta.set_dirty();
|
||||
stale_preview.map(|s| meta.put_stale(s));
|
||||
|
||||
dirty_meta.map(|mut d|
|
||||
meta.on_ready(move |_,_| {
|
||||
d.set_dirty();
|
||||
|
||||
Ok(())
|
||||
}));
|
||||
}
|
||||
}).log()
|
||||
);
|
||||
meta
|
||||
}
|
||||
|
||||
|
@ -707,29 +711,25 @@ impl File {
|
|||
stale_preview: Option<Stale>) -> Async<usize> {
|
||||
let path = path.clone();
|
||||
|
||||
let dirsize_closure = Box::new(move |stale: Stale| {
|
||||
let mut dirsize = Async::new(move |stale: &Stale| {
|
||||
if stale.is_stale()? { HError::stale()? }
|
||||
Ok(std::fs::read_dir(&path)?.count())
|
||||
});
|
||||
|
||||
let mut dirsize = match stale_preview {
|
||||
Some(stale) => Async::new_with_stale(dirsize_closure, stale),
|
||||
None => Async::new(dirsize_closure)
|
||||
};
|
||||
stale_preview.map(|s| dirsize.put_stale(s));
|
||||
|
||||
if let Some(dirty_meta) = dirty_meta {
|
||||
dirsize.on_ready(Box::new(move || {
|
||||
let mut dirty_meta = dirty_meta.clone();
|
||||
dirty_meta.set_dirty();
|
||||
dirty_meta.map(|mut d|
|
||||
dirsize.on_ready(move |_,_| {
|
||||
d.set_dirty();
|
||||
|
||||
Ok(())
|
||||
}));
|
||||
}
|
||||
}).log()
|
||||
);
|
||||
dirsize
|
||||
}
|
||||
|
||||
pub fn meta(&self) -> HResult<&Metadata> {
|
||||
self.meta.get()
|
||||
Ok(self.meta.get()?)
|
||||
}
|
||||
|
||||
fn take_dirsize(&mut self,
|
||||
|
@ -738,13 +738,15 @@ impl File {
|
|||
let dirsize = self.dirsize.as_mut()?;
|
||||
if let Ok(_) = dirsize.value { return Ok(()) }
|
||||
|
||||
match dirsize.take_async() {
|
||||
Ok(_) => { *meta_updated = true; },
|
||||
Err(HError::AsyncNotReadyError) => { dirsize.run_pooled(&*pool).ok(); },
|
||||
Err(HError::AsyncAlreadyTakenError) => {},
|
||||
Err(HError::NoneError) => {},
|
||||
err @ Err(_) => { err?; }
|
||||
if !dirsize.is_running() {
|
||||
dirsize.run_pooled(Some(&*pool))?;
|
||||
}
|
||||
|
||||
if dirsize.is_ready() {
|
||||
dirsize.pull_async()?;
|
||||
*meta_updated = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -753,15 +755,15 @@ impl File {
|
|||
meta_updated: &mut bool) -> HResult<()> {
|
||||
if self.meta_processed { return Ok(()) }
|
||||
|
||||
match self.meta.take_async() {
|
||||
Ok(_) => { *meta_updated = true; },
|
||||
Err(HError::AsyncNotReadyError) => { self.meta.run_pooled(&*pool).ok(); },
|
||||
Err(HError::AsyncAlreadyTakenError) => {},
|
||||
Err(HError::NoneError) => {},
|
||||
err @ Err(_) => { err?; }
|
||||
if !self.meta.is_running() {
|
||||
self.meta.run_pooled(Some(&*pool))?;
|
||||
}
|
||||
|
||||
self.process_meta()?;
|
||||
if self.meta.is_ready() {
|
||||
self.meta.pull_async()?;
|
||||
self.process_meta()?;
|
||||
*meta_updated = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -785,12 +787,13 @@ impl File {
|
|||
self.meta = File::make_async_meta(&self.path,
|
||||
self.dirty_meta.clone(),
|
||||
None);
|
||||
self.meta.run().log();
|
||||
self.meta.run()?;
|
||||
|
||||
if self.dirsize.is_some() {
|
||||
self.dirsize
|
||||
= Some(File::make_async_dirsize(&self.path, self.dirty_meta.clone(), None));
|
||||
self.dirsize.as_mut()?.run().log();
|
||||
self.dirsize = Some(File::make_async_dirsize(&self.path,
|
||||
self.dirty_meta.clone(),
|
||||
None));
|
||||
self.dirsize.as_mut()?.run()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use notify::{RecommendedWatcher, Watcher, DebouncedEvent, RecursiveMode};
|
||||
|
||||
use async_value::{Async, Stale};
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::time::Duration;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::preview::{Async, Stale};
|
||||
use crate::files::{Files, File, SortBy};
|
||||
use crate::widget::Events;
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
|
@ -116,11 +117,11 @@ impl FsCache {
|
|||
let dir = dir.clone();
|
||||
let selection = self.get_selection(&dir).ok();
|
||||
let cache = self.clone();
|
||||
let files = Async::new(Box::new(move |_| {
|
||||
let files = Async::new(move |_| {
|
||||
let mut files = Files::new_from_path_cancellable(&dir.path, stale)?;
|
||||
FsCache::apply_settingss(&cache, &mut files).ok();
|
||||
Ok(files)
|
||||
}));
|
||||
});
|
||||
Ok((selection, files))
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ impl FsCache {
|
|||
pub fn get_files_sync(&self, dir: &File) -> HResult<Files> {
|
||||
self.add_watch(&dir).log();
|
||||
let files = self.get_files(&dir, Stale::new())?.1;
|
||||
let mut files = files.wait()?;
|
||||
let mut files = files.run_sync()?;
|
||||
FsCache::apply_settingss(&self, &mut files).ok();
|
||||
let files = FsCache::ensure_not_empty(files)?;
|
||||
Ok(files)
|
||||
|
@ -210,8 +211,12 @@ impl FsCache {
|
|||
let file_cache = self.files.clone();
|
||||
let dir = dir.clone();
|
||||
|
||||
let files = Async::new(Box::new(move |_| {
|
||||
let mut files = file_cache.read()?.get(&dir)?.clone();
|
||||
let files = Async::new(move |_| {
|
||||
let mut files = file_cache.read()
|
||||
.map_err(|e| HError::from(e))?
|
||||
.get(&dir)
|
||||
.ok_or(HError::NoneError)?
|
||||
.clone();
|
||||
let tab_settings = &tab_settings;
|
||||
|
||||
files.sort = tab_settings.dir_settings.sort;
|
||||
|
@ -233,7 +238,7 @@ impl FsCache {
|
|||
files.sort();
|
||||
let files = FsCache::ensure_not_empty(files)?;
|
||||
Ok(files)
|
||||
}));
|
||||
});
|
||||
|
||||
Ok((selection, files))
|
||||
}
|
||||
|
@ -301,7 +306,7 @@ fn watch_fs(rx_fs_events: Receiver<DebouncedEvent>,
|
|||
for event in rx_fs_events.iter() {
|
||||
apply_event(&fs_cache, &fs_changes, event).log();
|
||||
|
||||
Ok(sender.send(Events::WidgetReady)?).log();
|
||||
sender.send(Events::WidgetReady).ok();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#![feature(vec_remove_item)]
|
||||
#![feature(trivial_bounds)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(fnbox)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate termion;
|
||||
|
@ -24,6 +23,7 @@ extern crate tree_magic;
|
|||
extern crate systemstat;
|
||||
extern crate osstrtools;
|
||||
extern crate pathbuftools;
|
||||
extern crate async_value;
|
||||
|
||||
use failure::Fail;
|
||||
|
||||
|
|
364
src/preview.rs
364
src/preview.rs
|
@ -1,7 +1,6 @@
|
|||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::boxed::FnBox;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use rayon::ThreadPool;
|
||||
use async_value::{Async, Stale};
|
||||
|
||||
use crate::files::{File, Files, Kind};
|
||||
use crate::fscache::FsCache;
|
||||
|
@ -13,14 +12,8 @@ use crate::fail::{HResult, HError, ErrorLog};
|
|||
use crate::dirty::Dirtyable;
|
||||
|
||||
|
||||
pub type AsyncValueFn<T> = Box<dyn FnBox(Stale) -> HResult<T> + Send + Sync>;
|
||||
pub type AsyncValue<T> = Arc<Mutex<Option<HResult<T>>>>;
|
||||
pub type AsyncReadyFn = Box<dyn FnBox() -> HResult<()> + Send + Sync>;
|
||||
pub type AsyncWidgetFn<W> = Box<dyn FnBox(Stale, WidgetCore)
|
||||
-> HResult<W> + Send + Sync>;
|
||||
|
||||
|
||||
type WidgetO = Box<dyn Widget + Send>;
|
||||
pub type AsyncWidgetFn<W> = FnOnce(&Stale, WidgetCore)
|
||||
-> HResult<W> + Send + Sync;
|
||||
|
||||
lazy_static! {
|
||||
static ref SUBPROC: Arc<Mutex<Option<u32>>> = { Arc::new(Mutex::new(None)) };
|
||||
|
@ -35,232 +28,9 @@ fn kill_proc() -> HResult<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Stale(Arc<RwLock<bool>>);
|
||||
|
||||
impl Stale {
|
||||
pub fn new() -> Stale {
|
||||
Stale(Arc::new(RwLock::new(false)))
|
||||
}
|
||||
pub fn is_stale(&self) -> HResult<bool> {
|
||||
Ok(*self.0.read()?)
|
||||
}
|
||||
pub fn set_stale(&self) -> HResult<()> {
|
||||
*self.0.write()? = true;
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_fresh(&self) -> HResult<()> {
|
||||
*self.0.write()? = false;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn is_stale(stale: &Stale) -> HResult<bool> {
|
||||
let stale = stale.is_stale()?;
|
||||
Ok(stale)
|
||||
}
|
||||
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
impl<T: Send + Debug> Debug for Async<T> {
|
||||
fn fmt(&self, formatter: &mut Formatter) -> Result<(), std::fmt::Error> {
|
||||
write!(formatter,
|
||||
"{:?}, {:?} {:?}",
|
||||
self.value,
|
||||
self.async_value,
|
||||
self.stale)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Async<T: Send> {
|
||||
pub value: HResult<T>,
|
||||
async_value: AsyncValue<T>,
|
||||
async_closure: Arc<Mutex<Option<AsyncValueFn<T>>>>,
|
||||
on_ready: Arc<Mutex<Option<AsyncReadyFn>>>,
|
||||
started: bool,
|
||||
stale: Stale,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<T: Send + 'static> Async<T> {
|
||||
pub fn new(closure: AsyncValueFn<T>)
|
||||
-> Async<T> {
|
||||
let async_value = Async {
|
||||
value: HError::async_not_ready(),
|
||||
async_value: Arc::new(Mutex::new(None)),
|
||||
async_closure: Arc::new(Mutex::new(Some(closure))),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
started: false,
|
||||
stale: Stale::new() };
|
||||
|
||||
async_value
|
||||
}
|
||||
|
||||
pub fn new_with_stale(closure: AsyncValueFn<T>,
|
||||
stale: Stale)
|
||||
-> Async<T> {
|
||||
let async_value = Async {
|
||||
value: HError::async_not_ready(),
|
||||
async_value: Arc::new(Mutex::new(None)),
|
||||
async_closure: Arc::new(Mutex::new(Some(closure))),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
started: false,
|
||||
stale: stale };
|
||||
|
||||
async_value
|
||||
}
|
||||
|
||||
pub fn new_with_value(val: T) -> Async<T> {
|
||||
Async {
|
||||
value: Ok(val),
|
||||
async_value: Arc::new(Mutex::new(None)),
|
||||
async_closure: Arc::new(Mutex::new(None)),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
started: false,
|
||||
stale: Stale::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_async(async_fn: Arc<Mutex<Option<AsyncValueFn<T>>>>,
|
||||
async_value: AsyncValue<T>,
|
||||
on_ready_fn: Arc<Mutex<Option<AsyncReadyFn>>>,
|
||||
stale: Stale) -> HResult<()> {
|
||||
let value_fn = async_fn.lock()?.take()?;
|
||||
let value = value_fn.call_box((stale.clone(),));
|
||||
async_value.lock()?.replace(value);
|
||||
on_ready_fn.lock()?
|
||||
.take()
|
||||
.map(|on_ready| on_ready.call_box(()).log());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> HResult<()> {
|
||||
if self.started {
|
||||
HError::async_started()?
|
||||
}
|
||||
|
||||
let closure = self.async_closure.clone();
|
||||
let async_value = self.async_value.clone();
|
||||
let stale = self.stale.clone();
|
||||
let on_ready_fn = self.on_ready.clone();
|
||||
self.started = true;
|
||||
|
||||
std::thread::spawn(move || {
|
||||
Async::run_async(closure,
|
||||
async_value,
|
||||
on_ready_fn,
|
||||
stale).log();
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_pooled(&mut self, pool: &ThreadPool) -> HResult<()> {
|
||||
if self.started {
|
||||
HError::async_started()?
|
||||
}
|
||||
|
||||
let closure = self.async_closure.clone();
|
||||
let async_value = self.async_value.clone();
|
||||
let stale = self.stale.clone();
|
||||
let on_ready_fn = self.on_ready.clone();
|
||||
self.started = true;
|
||||
|
||||
pool.spawn(move || {
|
||||
Async::run_async(closure,
|
||||
async_value,
|
||||
on_ready_fn,
|
||||
stale).log();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn wait(self) -> HResult<T> {
|
||||
Async::run_async(self.async_closure,
|
||||
self.async_value.clone(),
|
||||
self.on_ready,
|
||||
self.stale).log();
|
||||
let value = self.async_value.lock()?.take()?;
|
||||
value
|
||||
}
|
||||
|
||||
pub fn set_stale(&mut self) -> HResult<()> {
|
||||
self.stale.set_stale()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_fresh(&self) -> HResult<()> {
|
||||
self.stale.set_fresh()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_stale(&self) -> HResult<bool> {
|
||||
self.stale.is_stale()
|
||||
}
|
||||
|
||||
pub fn get_stale(&self) -> Stale {
|
||||
self.stale.clone()
|
||||
}
|
||||
|
||||
pub fn put_stale(&mut self, stale: Stale) {
|
||||
self.stale = stale;
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.started
|
||||
}
|
||||
|
||||
pub fn set_unstarted(&mut self) {
|
||||
self.started = false;
|
||||
}
|
||||
|
||||
pub fn take_async(&mut self) -> HResult<()> {
|
||||
if self.value.is_ok() { HError::async_taken()? }
|
||||
|
||||
let mut async_value = self.async_value.lock()?;
|
||||
match async_value.as_ref() {
|
||||
Some(Ok(_)) => {
|
||||
let value = async_value.take()?;
|
||||
self.value = value;
|
||||
}
|
||||
Some(Err(HError::AsyncAlreadyTakenError)) => HError::async_taken()?,
|
||||
Some(Err(_)) => {
|
||||
let value = async_value.take()?;
|
||||
self.value = value;
|
||||
}
|
||||
None => HError::async_not_ready()?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get(&self) -> HResult<&T> {
|
||||
match self.value {
|
||||
Ok(ref value) => Ok(value),
|
||||
Err(ref err) => HError::async_error(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> HResult<&mut T> {
|
||||
self.take_async().ok();
|
||||
|
||||
match self.value {
|
||||
Ok(ref mut value) => Ok(value),
|
||||
Err(ref err) => HError::async_error(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_ready(&mut self,
|
||||
fun: AsyncReadyFn) {
|
||||
*self.on_ready.lock().unwrap() = Some(fun);
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget + Send + 'static> PartialEq for AsyncWidget<W> {
|
||||
fn eq(&self, other: &AsyncWidget<W>) -> bool {
|
||||
if self.get_coordinates().unwrap() ==
|
||||
|
@ -274,19 +44,21 @@ impl<W: Widget + Send + 'static> PartialEq for AsyncWidget<W> {
|
|||
|
||||
|
||||
pub struct AsyncWidget<W: Widget + Send + 'static> {
|
||||
widget: Async<W>,
|
||||
pub widget: Async<W>,
|
||||
core: WidgetCore
|
||||
}
|
||||
|
||||
impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
||||
pub fn new(core: &WidgetCore, closure: AsyncValueFn<W>) -> AsyncWidget<W> {
|
||||
let sender = Mutex::new(core.get_sender());
|
||||
let mut widget = Async::new(Box::new(move |stale|
|
||||
closure.call_box((stale,))));
|
||||
widget.on_ready(Box::new(move || {
|
||||
sender.lock()?.send(crate::widget::Events::WidgetReady)?;
|
||||
pub fn new(core: &WidgetCore,
|
||||
closure: impl FnOnce(&Stale) -> HResult<W> + Send + Sync + 'static)
|
||||
-> AsyncWidget<W> {
|
||||
let sender = Arc::new(Mutex::new(core.get_sender()));
|
||||
let mut widget = Async::new(move |stale|
|
||||
closure(stale).map_err(|e| e.into()));
|
||||
widget.on_ready(move |_, _| {
|
||||
sender.lock().map(|s| s.send(crate::widget::Events::WidgetReady)).ok();
|
||||
Ok(())
|
||||
}));
|
||||
}).log();
|
||||
widget.run().log();
|
||||
|
||||
AsyncWidget {
|
||||
|
@ -294,20 +66,24 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
|||
core: core.clone()
|
||||
}
|
||||
}
|
||||
pub fn change_to(&mut self, closure: AsyncWidgetFn<W>) -> HResult<()> {
|
||||
pub fn change_to(&mut self,
|
||||
closure: impl FnOnce(&Stale,
|
||||
WidgetCore)
|
||||
-> HResult<W> + Send + Sync + 'static)
|
||||
-> HResult<()> {
|
||||
self.set_stale().log();
|
||||
|
||||
let sender = Mutex::new(self.get_core()?.get_sender());
|
||||
let core = self.get_core()?.clone();
|
||||
|
||||
let mut widget = Async::new(Box::new(move |stale| {
|
||||
closure.call_box((stale, core.clone(),))
|
||||
}));
|
||||
let mut widget = Async::new(move |stale| {
|
||||
Ok(closure(stale, core.clone())?)
|
||||
});
|
||||
|
||||
widget.on_ready(Box::new(move || {
|
||||
sender.lock()?.send(crate::widget::Events::WidgetReady)?;
|
||||
widget.on_ready(move |_, _| {
|
||||
sender.lock().map(|s| s.send(crate::widget::Events::WidgetReady)).ok();
|
||||
Ok(())
|
||||
}));
|
||||
}).log();
|
||||
|
||||
widget.run().log();
|
||||
|
||||
|
@ -316,11 +92,11 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
|||
}
|
||||
|
||||
pub fn set_stale(&mut self) -> HResult<()> {
|
||||
self.widget.set_stale()
|
||||
Ok(self.widget.set_stale()?)
|
||||
}
|
||||
|
||||
pub fn is_stale(&self) -> HResult<bool> {
|
||||
self.widget.is_stale()
|
||||
Ok(self.widget.is_stale()?)
|
||||
}
|
||||
|
||||
pub fn get_stale(&self) -> Stale {
|
||||
|
@ -328,11 +104,11 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
|||
}
|
||||
|
||||
pub fn widget(&self) -> HResult<&W> {
|
||||
self.widget.get()
|
||||
Ok(self.widget.get()?)
|
||||
}
|
||||
|
||||
pub fn widget_mut(&mut self) -> HResult<&mut W> {
|
||||
self.widget.get_mut()
|
||||
Ok(self.widget.get_mut()?)
|
||||
}
|
||||
|
||||
pub fn take_widget(self) -> HResult<W> {
|
||||
|
@ -363,7 +139,7 @@ impl<T: Widget + Send + 'static> Widget for AsyncWidget<T> {
|
|||
}
|
||||
|
||||
fn refresh(&mut self) -> HResult<()> {
|
||||
self.widget.take_async().ok();
|
||||
self.widget.pull_async().ok();
|
||||
|
||||
let coords = self.get_coordinates()?.clone();
|
||||
if let Ok(widget) = self.widget_mut() {
|
||||
|
@ -415,7 +191,6 @@ enum PreviewWidget {
|
|||
}
|
||||
|
||||
|
||||
|
||||
pub struct Previewer {
|
||||
widget: AsyncWidget<PreviewWidget>,
|
||||
core: WidgetCore,
|
||||
|
@ -428,11 +203,12 @@ pub struct Previewer {
|
|||
impl Previewer {
|
||||
pub fn new(core: &WidgetCore, cache: FsCache) -> Previewer {
|
||||
let core_ = core.clone();
|
||||
let widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let widget = AsyncWidget::new(&core, move |_| {
|
||||
let blank = TextView::new_blank(&core_);
|
||||
let blank = PreviewWidget::TextView(blank);
|
||||
Ok(blank)
|
||||
}));
|
||||
});
|
||||
|
||||
Previewer { widget: widget,
|
||||
core: core.clone(),
|
||||
file: None,
|
||||
|
@ -457,16 +233,16 @@ impl Previewer {
|
|||
}
|
||||
|
||||
pub fn cancel_animation(&self) -> HResult<()> {
|
||||
self.animator.set_stale()
|
||||
Ok(self.animator.set_stale()?)
|
||||
}
|
||||
|
||||
pub fn take_files(&mut self) -> HResult<Files> {
|
||||
let core = self.core.clone();
|
||||
let mut widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
|
||||
let mut widget = AsyncWidget::new(&core.clone(), move |_| {
|
||||
let widget = TextView::new_blank(&core);
|
||||
let widget = PreviewWidget::TextView(widget);
|
||||
Ok(widget)
|
||||
}));
|
||||
});
|
||||
std::mem::swap(&mut self.widget, &mut widget);
|
||||
|
||||
match widget.take_widget() {
|
||||
|
@ -501,19 +277,24 @@ impl Previewer {
|
|||
let cache = self.cache.clone();
|
||||
self.file = Some(dir);
|
||||
|
||||
self.widget = AsyncWidget::new(&self.core, Box::new(move |_| {
|
||||
self.widget = AsyncWidget::new(&self.core, move |_| {
|
||||
let selected_file = cache.get_selection(&files.directory);
|
||||
let mut filelist = ListView::new(&core, files);
|
||||
|
||||
selected_file.map(|file| filelist.select_file(&file)).log();
|
||||
|
||||
Ok(PreviewWidget::FileList(filelist))
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_file(&mut self,
|
||||
file: &File) -> HResult<()> {
|
||||
if Some(file) == self.file.as_ref() && !self.widget.is_stale()? { return Ok(()) }
|
||||
|
||||
let same_dir = self.file
|
||||
.as_ref()
|
||||
.map(|f| f.path.parent() == file.path.parent())
|
||||
.unwrap_or(true);
|
||||
self.file = Some(file.clone());
|
||||
|
||||
let coordinates = self.get_coordinates().unwrap().clone();
|
||||
|
@ -523,41 +304,46 @@ impl Previewer {
|
|||
let animator = self.animator.clone();
|
||||
|
||||
self.widget.set_stale().ok();
|
||||
self.animator.set_fresh().log();
|
||||
|
||||
if same_dir {
|
||||
self.animator.set_fresh().ok();
|
||||
} else {
|
||||
self.animator.set_stale().ok();
|
||||
}
|
||||
|
||||
self.become_preview(Ok(AsyncWidget::new(&self.core,
|
||||
Box::new(move |stale: Stale| {
|
||||
move |stale: &Stale| {
|
||||
kill_proc().unwrap();
|
||||
|
||||
if file.kind == Kind::Directory {
|
||||
let preview = Previewer::preview_dir(&file,
|
||||
cache,
|
||||
&core,
|
||||
stale,
|
||||
animator);
|
||||
return preview;
|
||||
&stale,
|
||||
&animator);
|
||||
return Ok(preview?);
|
||||
}
|
||||
|
||||
if file.is_text() {
|
||||
return Previewer::preview_text(&file,
|
||||
return Ok(Previewer::preview_text(&file,
|
||||
&core,
|
||||
stale,
|
||||
animator);
|
||||
&stale,
|
||||
&animator)?);
|
||||
}
|
||||
|
||||
let preview = Previewer::preview_external(&file,
|
||||
&core,
|
||||
stale,
|
||||
animator.clone());
|
||||
if preview.is_ok() { return preview; }
|
||||
&stale,
|
||||
&animator);
|
||||
if preview.is_ok() { return Ok(preview?); }
|
||||
else {
|
||||
let mut blank = TextView::new_blank(&core);
|
||||
blank.set_coordinates(&coordinates).log();
|
||||
blank.refresh().log();
|
||||
blank.animate_slide_up(Some(animator)).log();
|
||||
blank.animate_slide_up(Some(&animator)).log();
|
||||
return Ok(PreviewWidget::TextView(blank))
|
||||
}
|
||||
}))))
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn reload(&mut self) {
|
||||
|
@ -576,14 +362,14 @@ impl Previewer {
|
|||
fn preview_dir(file: &File,
|
||||
cache: FsCache,
|
||||
core: &WidgetCore,
|
||||
stale: Stale,
|
||||
animator: Stale)
|
||||
stale: &Stale,
|
||||
animator: &Stale)
|
||||
-> HResult<PreviewWidget> {
|
||||
let (selection, cached_files) = cache.get_files(&file, stale.clone())?;
|
||||
|
||||
let files = cached_files.wait()?;
|
||||
let files = cached_files.run_sync()?;
|
||||
|
||||
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
|
||||
if stale.is_stale()? { return Previewer::preview_failed(&file) }
|
||||
|
||||
let mut file_list = ListView::new(&core, files);
|
||||
if let Some(selection) = selection {
|
||||
|
@ -591,27 +377,27 @@ impl Previewer {
|
|||
}
|
||||
file_list.set_coordinates(&core.coordinates)?;
|
||||
file_list.refresh()?;
|
||||
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
|
||||
if stale.is_stale()? { return Previewer::preview_failed(&file) }
|
||||
file_list.animate_slide_up(Some(animator))?;
|
||||
Ok(PreviewWidget::FileList(file_list))
|
||||
}
|
||||
|
||||
fn preview_text(file: &File,
|
||||
core: &WidgetCore,
|
||||
stale: Stale,
|
||||
animator: Stale)
|
||||
stale: &Stale,
|
||||
animator: &Stale)
|
||||
-> HResult<PreviewWidget> {
|
||||
let lines = core.coordinates.ysize() as usize;
|
||||
let mut textview
|
||||
= TextView::new_from_file_limit_lines(&core,
|
||||
&file,
|
||||
lines)?;
|
||||
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
|
||||
if stale.is_stale()? { return Previewer::preview_failed(&file) }
|
||||
|
||||
textview.set_coordinates(&core.coordinates)?;
|
||||
textview.refresh()?;
|
||||
|
||||
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
|
||||
if stale.is_stale()? { return Previewer::preview_failed(&file) }
|
||||
|
||||
textview.animate_slide_up(Some(animator))?;
|
||||
Ok(PreviewWidget::TextView(textview))
|
||||
|
@ -619,8 +405,8 @@ impl Previewer {
|
|||
|
||||
fn preview_external(file: &File,
|
||||
core: &WidgetCore,
|
||||
stale: Stale,
|
||||
animator: Stale)
|
||||
stale: &Stale,
|
||||
animator: &Stale)
|
||||
-> HResult<PreviewWidget> {
|
||||
let process =
|
||||
std::process::Command::new("scope.sh")
|
||||
|
@ -640,11 +426,11 @@ impl Previewer {
|
|||
*pid_ = Some(pid);
|
||||
}
|
||||
|
||||
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
|
||||
if stale.is_stale()? { return Previewer::preview_failed(&file) }
|
||||
|
||||
let output = process.wait_with_output()?;
|
||||
|
||||
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
|
||||
if stale.is_stale()? { return Previewer::preview_failed(&file) }
|
||||
{
|
||||
let mut pid_ = SUBPROC.lock()?;
|
||||
*pid_ = None;
|
||||
|
@ -652,7 +438,7 @@ impl Previewer {
|
|||
|
||||
//let status = output.status.code()?;
|
||||
|
||||
if !is_stale(&stale)? {
|
||||
if stale.is_stale()? {
|
||||
let output = std::str::from_utf8(&output.stdout)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
|
|
@ -9,12 +9,13 @@ use std::os::unix::ffi::OsStringExt;
|
|||
use termion::event::Key;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use osstrtools::OsStrTools;
|
||||
use async_value::Stale;
|
||||
|
||||
use crate::listview::{Listable, ListView};
|
||||
use crate::textview::TextView;
|
||||
use crate::widget::{Widget, Events, WidgetCore};
|
||||
use crate::coordinates::Coordinates;
|
||||
use crate::preview::{AsyncWidget, Stale};
|
||||
use crate::preview::AsyncWidget;
|
||||
use crate::dirty::Dirtyable;
|
||||
use crate::hbox::HBox;
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
|
@ -368,10 +369,10 @@ impl ProcView {
|
|||
pub fn new(core: &WidgetCore) -> ProcView {
|
||||
let tcore = core.clone();
|
||||
let listview = ListView::new(&core, vec![]);
|
||||
let textview = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let textview = AsyncWidget::new(&core, move |_| {
|
||||
let textview = TextView::new_blank(&tcore);
|
||||
Ok(textview)
|
||||
}));
|
||||
});
|
||||
let mut hbox = HBox::new(&core);
|
||||
hbox.push_widget(ProcViewWidgets::List(listview));
|
||||
hbox.push_widget(ProcViewWidgets::TextView(textview));
|
||||
|
@ -425,12 +426,12 @@ impl ProcView {
|
|||
let animator = self.animator.clone();
|
||||
animator.set_fresh().log();
|
||||
|
||||
self.get_textview().change_to(Box::new(move |_, core| {
|
||||
self.get_textview().change_to(move |_, core| {
|
||||
let mut textview = TextView::new_blank(&core);
|
||||
textview.set_text(&output).log();
|
||||
textview.animate_slide_up(Some(animator)).log();
|
||||
textview.animate_slide_up(Some(&animator)).log();
|
||||
Ok(textview)
|
||||
})).log();
|
||||
}).log();
|
||||
|
||||
self.viewing = Some(self.get_listview_mut().get_selection());
|
||||
Ok(())
|
||||
|
|
|
@ -4,6 +4,8 @@ use std::io::{Write, stdin};
|
|||
|
||||
use termion::event::{Event, Key, MouseEvent};
|
||||
use termion::input::TermRead;
|
||||
use async_value::{Async, Stale};
|
||||
|
||||
|
||||
use crate::coordinates::{Coordinates, Position, Size};
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
|
@ -11,10 +13,8 @@ use crate::minibuffer::MiniBuffer;
|
|||
use crate::term;
|
||||
use crate::term::{Screen, ScreenExt};
|
||||
use crate::dirty::{Dirtyable, DirtyBit};
|
||||
use crate::preview::Stale;
|
||||
use crate::signal_notify::{notify, Signal};
|
||||
use crate::config::Config;
|
||||
use crate::preview::Async;
|
||||
|
||||
|
||||
|
||||
|
@ -75,12 +75,12 @@ impl WidgetCore {
|
|||
let (sender, receiver) = channel();
|
||||
let status_bar_content = Arc::new(Mutex::new(None));
|
||||
|
||||
let mut config = Async::new(Box::new(|_| Config::load()));
|
||||
let mut config = Async::new(|_| Ok(Config::load()?));
|
||||
let confsender = Arc::new(Mutex::new(sender.clone()));
|
||||
config.on_ready(Box::new(move || {
|
||||
confsender.lock()?.send(Events::ConfigLoaded).ok();
|
||||
config.on_ready(move |_, _| {
|
||||
confsender.lock().map(|s| s.send(Events::ConfigLoaded)).ok();
|
||||
Ok(())
|
||||
}));
|
||||
}).log();
|
||||
config.run().log();
|
||||
|
||||
let core = WidgetCore {
|
||||
|
@ -296,7 +296,7 @@ pub trait Widget {
|
|||
HError::input_updated(input)?
|
||||
}
|
||||
Events::ConfigLoaded => {
|
||||
self.get_core_mut()?.config.write()?.take_async().log();
|
||||
self.get_core_mut()?.config.write()?.pull_async()?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ pub trait Widget {
|
|||
.unwrap_or(Config::new())
|
||||
}
|
||||
|
||||
fn animate_slide_up(&mut self, animator: Option<Stale>) -> HResult<()> {
|
||||
fn animate_slide_up(&mut self, animator: Option<&Stale>) -> HResult<()> {
|
||||
if !self.config().animate() { return Ok(()); }
|
||||
|
||||
self.config();
|
||||
|
@ -398,7 +398,7 @@ pub trait Widget {
|
|||
self.screen()?.clear().log();
|
||||
}
|
||||
Events::ConfigLoaded => {
|
||||
self.get_core_mut()?.config.write()?.take_async().log();
|
||||
self.get_core_mut()?.config.write()?.pull_async()?;
|
||||
self.config_loaded().log();
|
||||
}
|
||||
_ => {}
|
||||
|
@ -555,7 +555,7 @@ fn input_thread(tx: Sender<Events>, rx_input_request: Receiver<()>) {
|
|||
input.map(|input| {
|
||||
tx.send(Events::InputEvent(input)).unwrap();
|
||||
rx_input_request.recv().unwrap();
|
||||
}).map_err(|e| e.into()).log();
|
||||
}).map_err(|e| HError::from(e)).log();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue