mirror of https://github.com/bobwen-dev/hunter
async stuff much improved
This commit is contained in:
parent
bb917a0dad
commit
fd366a26dc
20
src/fail.rs
20
src/fail.rs
|
@ -37,6 +37,12 @@ pub enum HError {
|
|||
NoneError(Backtrace),
|
||||
#[fail(display = "Not ready yet!")]
|
||||
WillBeNotReady(Backtrace),
|
||||
#[fail(display = "Not ready yet!")]
|
||||
AsyncNotReadyError(Backtrace),
|
||||
#[fail(display = "Value has already been taken!")]
|
||||
AsyncAlreadyTakenError(Backtrace),
|
||||
#[fail(display = "Async Error: {}", _0)]
|
||||
AsyncError(String),
|
||||
#[fail(display = "No widget found")]
|
||||
NoWidgetError(Backtrace),
|
||||
#[fail(display = "Path: {:?} not in this directory: {:?}", path, dir)]
|
||||
|
@ -72,7 +78,7 @@ pub enum HError {
|
|||
#[fail(display = "Terminal has been resized!")]
|
||||
TerminalResizedError,
|
||||
#[fail(display = "{}", _0)]
|
||||
Log(String)
|
||||
Log(String),
|
||||
}
|
||||
|
||||
impl HError {
|
||||
|
@ -126,6 +132,18 @@ impl HError {
|
|||
pub fn stale<T>() -> HResult<T> {
|
||||
Err(HError::StaleError(Backtrace::new()))
|
||||
}
|
||||
|
||||
pub fn async_not_ready<T>() -> HResult<T> {
|
||||
Err(HError::AsyncNotReadyError(Backtrace::new()))
|
||||
}
|
||||
|
||||
pub fn async_taken<T>() -> HResult<T> {
|
||||
Err(HError::AsyncAlreadyTakenError(Backtrace::new()))
|
||||
}
|
||||
|
||||
pub fn async_error<T>(error: &HError) -> HResult<T> {
|
||||
Err(HError::AsyncError(format!("{}", error)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,15 +7,14 @@ use std::sync::mpsc::{channel, Receiver, Sender};
|
|||
use std::time::Duration;
|
||||
use std::path::PathBuf;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::{OsString, OsStr};
|
||||
use std::ffi::OsString;
|
||||
|
||||
use crate::files::{File, Files, PathBufExt, OsStrTools};
|
||||
use crate::files::{File, Files, PathBufExt};
|
||||
use crate::listview::ListView;
|
||||
use crate::hbox::HBox;
|
||||
use crate::widget::Widget;
|
||||
use crate::dirty::Dirtyable;
|
||||
use crate::tabview::{TabView, Tabbable};
|
||||
use crate::preview::{Previewer, WillBeWidget};
|
||||
use crate::preview::{Previewer, AsyncWidget};
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
use crate::widget::{Events, WidgetCore};
|
||||
use crate::proclist::ProcView;
|
||||
|
@ -27,7 +26,7 @@ use crate::coordinates::Coordinates;
|
|||
|
||||
#[derive(PartialEq)]
|
||||
pub enum FileBrowserWidgets {
|
||||
FileList(WillBeWidget<ListView<Files>>),
|
||||
FileList(AsyncWidget<ListView<Files>>),
|
||||
Previewer(Previewer),
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,7 @@ impl FileBrowser {
|
|||
}).last()?;
|
||||
let left_path = main_path.parent().map(|p| p.to_path_buf());
|
||||
|
||||
let main_widget = WillBeWidget::new(&core, Box::new(move |_| {
|
||||
let main_widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let mut list = ListView::new(&core_m,
|
||||
Files::new_from_path(&main_path)?);
|
||||
list.animate_slide_up().log();
|
||||
|
@ -199,7 +198,7 @@ impl FileBrowser {
|
|||
}));
|
||||
|
||||
if let Some(left_path) = left_path {
|
||||
let left_widget = WillBeWidget::new(&core, Box::new(move |_| {
|
||||
let left_widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
let mut list = ListView::new(&core_l,
|
||||
Files::new_from_path(&left_path)?);
|
||||
list.animate_slide_up().log();
|
||||
|
@ -314,8 +313,8 @@ impl FileBrowser {
|
|||
self.prev_cwd = Some(self.cwd.clone());
|
||||
self.cwd = dir.clone();
|
||||
|
||||
let main_widget = self.main_widget_mut()?;
|
||||
main_widget.change_to(Box::new(move |stale, core| {
|
||||
let main_async_widget = self.main_async_widget_mut()?;
|
||||
main_async_widget.change_to(Box::new(move |stale, core| {
|
||||
let path = dir.path();
|
||||
let cached_files = cached_files.clone();
|
||||
|
||||
|
@ -334,7 +333,7 @@ impl FileBrowser {
|
|||
if let Ok(grand_parent) = self.cwd()?.parent_as_file() {
|
||||
self.left_widget_goto(&grand_parent).log();
|
||||
} else {
|
||||
self.left_widget_mut()?.set_stale().log();
|
||||
self.left_async_widget_mut()?.set_stale().log();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -345,8 +344,8 @@ impl FileBrowser {
|
|||
let cached_files = self.get_cached_files(&dir).ok();
|
||||
let dir = dir.clone();
|
||||
|
||||
let left_widget = self.left_widget_mut()?;
|
||||
left_widget.change_to(Box::new(move |stale, core| {
|
||||
let left_async_widget = self.left_async_widget_mut()?;
|
||||
left_async_widget.change_to(Box::new(move |stale, core| {
|
||||
let path = dir.path();
|
||||
let cached_files = cached_files.clone();
|
||||
|
||||
|
@ -415,34 +414,29 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn update_preview(&mut self) -> HResult<()> {
|
||||
if !self.main_widget()?.ready() { return Ok(()) }
|
||||
if !self.main_async_widget_mut()?.ready() { return Ok(()) }
|
||||
if self.main_widget()?
|
||||
.widget()?
|
||||
.lock()?
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.content
|
||||
.len() == 0 {
|
||||
self.preview_widget_mut()?.set_stale();
|
||||
self.preview_widget_mut()?.set_stale().log();
|
||||
return Ok(());
|
||||
}
|
||||
let file = self.selected_file()?.clone();
|
||||
let selection = self.get_selection(&file).ok().cloned();
|
||||
let cached_files = self.get_cached_files(&file).ok();
|
||||
let preview = self.preview_widget_mut()?;
|
||||
preview.set_file(&file, selection, cached_files);
|
||||
preview.set_file(&file, selection, cached_files).log();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_left_selection(&mut self) -> HResult<()> {
|
||||
if !self.left_widget()?.ready() { return Ok(()) }
|
||||
if !self.left_async_widget_mut()?.ready() { return Ok(()) }
|
||||
if self.cwd.parent().is_none() { return Ok(()) }
|
||||
|
||||
let parent = self.cwd()?.parent_as_file();
|
||||
|
||||
if let Ok(left_selection) = self.get_selection(&parent?) {
|
||||
self.left_widget()?.widget()?.lock()?.as_mut()?.select_file(&left_selection);
|
||||
}
|
||||
let left_selection = self.get_selection(&parent?)?.clone();
|
||||
self.left_widget_mut()?.select_file(&left_selection);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -452,11 +446,11 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn get_files(&mut self) -> HResult<Files> {
|
||||
Ok(self.main_widget()?.widget()?.lock()?.as_ref()?.content.clone())
|
||||
Ok(self.main_widget()?.content.clone())
|
||||
}
|
||||
|
||||
pub fn get_left_files(&mut self) -> HResult<Files> {
|
||||
Ok(self.left_widget()?.widget()?.lock()?.as_ref()?.content.clone())
|
||||
Ok(self.left_widget()?.content.clone())
|
||||
}
|
||||
|
||||
pub fn cache_files(&mut self, files: Files) -> HResult<()> {
|
||||
|
@ -491,13 +485,14 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn left_dir(&self) -> HResult<File> {
|
||||
let widget = self.left_widget()?.widget()?;
|
||||
let dir = widget.lock()?.as_ref()?.content.directory.clone();
|
||||
let widget = self.left_widget()?;
|
||||
let dir = widget.content.directory.clone();
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
fn update_watches(&mut self) -> HResult<()> {
|
||||
if !self.left_widget()?.ready() || !self.main_widget()?.ready() {
|
||||
if !self.left_async_widget_mut()?.ready() ||
|
||||
!self.main_async_widget_mut()?.ready() {
|
||||
return Ok(())
|
||||
}
|
||||
let watched_dirs = self.watches.clone();
|
||||
|
@ -539,13 +534,11 @@ impl FileBrowser {
|
|||
fn handle_dir_events(&mut self) -> HResult<()> {
|
||||
let dir_events = self.dir_events.clone();
|
||||
for event in dir_events.lock()?.iter() {
|
||||
let main_widget = self.main_widget()?.widget()?;
|
||||
let mut main_widget = main_widget.lock()?;
|
||||
let main_result = main_widget.as_mut()?.content.handle_event(event);
|
||||
let main_widget = self.main_widget_mut()?;
|
||||
let main_result = main_widget.content.handle_event(event);
|
||||
|
||||
let left_widget = self.left_widget()?.widget()?;
|
||||
let mut left_files = left_widget.lock()?;
|
||||
let left_result = left_files.as_mut()?.content.handle_event(event);
|
||||
let left_widget = self.left_widget_mut()?;
|
||||
let left_result = left_widget.content.handle_event(event);
|
||||
|
||||
match main_result {
|
||||
Err(HError::WrongDirectoryError { .. }) => {
|
||||
|
@ -563,62 +556,80 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn selected_file(&self) -> HResult<File> {
|
||||
let widget = self.main_widget()?.widget()?;
|
||||
let file = widget.lock()?.as_ref()?.selected_file().clone();
|
||||
let widget = self.main_widget()?;
|
||||
let file = widget.selected_file().clone();
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
pub fn selected_files(&self) -> HResult<Vec<File>> {
|
||||
let widget = self.main_widget()?.widget()?;
|
||||
let files = widget.lock()?.as_ref()?.content.get_selected().into_iter().map(|f| {
|
||||
let widget = self.main_widget()?;
|
||||
let files = widget.content.get_selected().into_iter().map(|f| {
|
||||
f.clone()
|
||||
}).collect();
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
pub fn main_widget(&self) -> HResult<&WillBeWidget<ListView<Files>>> {
|
||||
let widget = self.columns.active_widget()?;
|
||||
|
||||
let widget = match widget {
|
||||
FileBrowserWidgets::FileList(filelist) => Ok(filelist),
|
||||
_ => { HError::wrong_widget("previewer", "filelist")? }
|
||||
};
|
||||
widget
|
||||
}
|
||||
|
||||
pub fn main_widget_mut(&mut self) -> HResult<&mut WillBeWidget<ListView<Files>>> {
|
||||
pub fn main_async_widget_mut(&mut self) -> HResult<&mut AsyncWidget<ListView<Files>>> {
|
||||
let widget = self.columns.active_widget_mut()?;
|
||||
|
||||
let widget = match widget {
|
||||
FileBrowserWidgets::FileList(filelist) => Ok(filelist),
|
||||
FileBrowserWidgets::FileList(filelist) => filelist,
|
||||
_ => { HError::wrong_widget("previewer", "filelist")? }
|
||||
};
|
||||
Ok(widget)
|
||||
}
|
||||
|
||||
pub fn main_widget(&self) -> HResult<&ListView<Files>> {
|
||||
let widget = self.columns.active_widget()?;
|
||||
|
||||
let widget = match widget {
|
||||
FileBrowserWidgets::FileList(filelist) => filelist.widget(),
|
||||
_ => { HError::wrong_widget("previewer", "filelist")? }
|
||||
};
|
||||
widget
|
||||
}
|
||||
|
||||
pub fn left_widget(&self) -> HResult<&WillBeWidget<ListView<Files>>> {
|
||||
let widget = match self.columns.widgets.get(0)? {
|
||||
FileBrowserWidgets::FileList(filelist) => Ok(filelist),
|
||||
_ => { return HError::wrong_widget("previewer", "filelist"); }
|
||||
pub fn main_widget_mut(&mut self) -> HResult<&mut ListView<Files>> {
|
||||
let widget = self.columns.active_widget_mut()?;
|
||||
|
||||
let widget = match widget {
|
||||
FileBrowserWidgets::FileList(filelist) => filelist.widget_mut(),
|
||||
_ => { HError::wrong_widget("previewer", "filelist")? }
|
||||
};
|
||||
widget
|
||||
}
|
||||
|
||||
pub fn left_widget_mut(&mut self) -> HResult<&mut WillBeWidget<ListView<Files>>> {
|
||||
pub fn left_async_widget_mut(&mut self) -> HResult<&mut AsyncWidget<ListView<Files>>> {
|
||||
let widget = match self.columns.widgets.get_mut(0)? {
|
||||
FileBrowserWidgets::FileList(filelist) => Ok(filelist),
|
||||
FileBrowserWidgets::FileList(filelist) => filelist,
|
||||
_ => { return HError::wrong_widget("previewer", "filelist"); }
|
||||
};
|
||||
Ok(widget)
|
||||
}
|
||||
|
||||
pub fn left_widget(&self) -> HResult<&ListView<Files>> {
|
||||
let widget = match self.columns.widgets.get(0)? {
|
||||
FileBrowserWidgets::FileList(filelist) => filelist.widget(),
|
||||
_ => { return HError::wrong_widget("previewer", "filelist"); }
|
||||
};
|
||||
widget
|
||||
}
|
||||
|
||||
pub fn preview_widget(&self) -> HResult<&Previewer> {
|
||||
match self.columns.widgets.get(2)? {
|
||||
FileBrowserWidgets::Previewer(previewer) => Ok(previewer),
|
||||
_ => { return HError::wrong_widget("filelist", "previewer"); }
|
||||
}
|
||||
pub fn left_widget_mut(&mut self) -> HResult<&mut ListView<Files>> {
|
||||
let widget = match self.columns.widgets.get_mut(0)? {
|
||||
FileBrowserWidgets::FileList(filelist) => filelist.widget_mut(),
|
||||
_ => { return HError::wrong_widget("previewer", "filelist"); }
|
||||
};
|
||||
widget
|
||||
}
|
||||
|
||||
// pub fn preview_widget(&self) -> HResult<&Previewer> {
|
||||
// match self.columns.widgets.get(2)? {
|
||||
// FileBrowserWidgets::Previewer(previewer) => Ok(previewer),
|
||||
// _ => { return HError::wrong_widget("filelist", "previewer"); }
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn preview_widget_mut(&mut self) -> HResult<&mut Previewer> {
|
||||
match self.columns.widgets.get_mut(2)? {
|
||||
FileBrowserWidgets::Previewer(previewer) => Ok(previewer),
|
||||
|
@ -660,14 +671,14 @@ impl FileBrowser {
|
|||
let mcore = self.main_widget()?.get_core()?.clone();
|
||||
let lcore = self.left_widget()?.get_core()?.clone();;
|
||||
|
||||
let middle = WillBeWidget::new(&self.core, Box::new(move |_| {
|
||||
let middle = AsyncWidget::new(&self.core, Box::new(move |_| {
|
||||
let files = Files::new_from_path(&dir.clone())?;
|
||||
let listview = ListView::new(&mcore, files);
|
||||
Ok(listview)
|
||||
}));
|
||||
let middle = FileBrowserWidgets::FileList(middle);
|
||||
|
||||
let left = WillBeWidget::new(&self.core, Box::new(move |_| {
|
||||
let left = AsyncWidget::new(&self.core, Box::new(move |_| {
|
||||
let files = Files::new_from_path(&left_dir.parent()?)?;
|
||||
let listview = ListView::new(&lcore, files);
|
||||
Ok(listview)
|
||||
|
@ -751,9 +762,9 @@ impl FileBrowser {
|
|||
"--> ".to_string() + &target.short_string()
|
||||
} else { "".to_string() };
|
||||
|
||||
let main_widget = self.main_widget()?.widget()?;
|
||||
let selection = main_widget.lock()?.as_ref().unwrap().get_selection();
|
||||
let file_count = main_widget.lock()?.as_ref().unwrap().content.len();
|
||||
let main_widget = self.main_widget()?;
|
||||
let selection = main_widget.get_selection();
|
||||
let file_count = main_widget.content.len();
|
||||
let file_count = format!("{}", file_count);
|
||||
let digits = file_count.len();
|
||||
let file_count = format!("{:digits$}/{:digits$}",
|
||||
|
|
|
@ -58,6 +58,7 @@ use term::ScreenExt;
|
|||
use fail::{HResult, HError};
|
||||
use file_browser::FileBrowser;
|
||||
use tabview::TabView;
|
||||
use preview::Async;
|
||||
|
||||
|
||||
fn main() -> HResult<()> {
|
||||
|
|
238
src/preview.rs
238
src/preview.rs
|
@ -1,7 +1,5 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use failure::Backtrace;
|
||||
|
||||
use crate::files::{File, Files, Kind};
|
||||
use crate::listview::ListView;
|
||||
use crate::textview::TextView;
|
||||
|
@ -10,9 +8,14 @@ use crate::coordinates::Coordinates;
|
|||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
|
||||
|
||||
pub type Stale = Arc<Mutex<bool>>;
|
||||
|
||||
pub type AsyncValueFn<T> = Box<Fn(Stale) -> HResult<T> + Send>;
|
||||
pub type AsyncValue<T> = Arc<Mutex<Option<HResult<T>>>>;
|
||||
pub type AsyncReadyFn<T> = Box<Fn(&mut T) -> HResult<()> + Send>;
|
||||
pub type AsyncWidgetFn<W> = Box<Fn(Stale, WidgetCore) -> HResult<W> + Send>;
|
||||
|
||||
|
||||
type HClosure<T> = Box<Fn(Arc<Mutex<bool>>) -> Result<T, HError> + Send>;
|
||||
type HCClosure<T> = Box<Fn(Arc<Mutex<bool>>, WidgetCore) -> Result<T, HError> + Send>;
|
||||
type WidgetO = Box<dyn Widget + Send>;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -33,49 +36,49 @@ pub fn is_stale(stale: &Arc<Mutex<bool>>) -> HResult<bool> {
|
|||
Ok(stale)
|
||||
}
|
||||
|
||||
enum State {
|
||||
Is,
|
||||
Becoming,
|
||||
Fail(HError)
|
||||
|
||||
pub struct Async<T: Send> {
|
||||
pub value: HResult<T>,
|
||||
async_value: AsyncValue<T>,
|
||||
async_closure: Option<AsyncValueFn<T>>,
|
||||
on_ready: Arc<Mutex<Option<AsyncReadyFn<T>>>>,
|
||||
stale: Stale
|
||||
}
|
||||
|
||||
struct WillBe<T: Send> {
|
||||
pub state: Arc<Mutex<State>>,
|
||||
pub thing: Arc<Mutex<Option<T>>>,
|
||||
on_ready: Arc<Mutex<Option<Box<Fn(Arc<Mutex<Option<T>>>) -> HResult<()> + Send>>>>,
|
||||
stale: Arc<Mutex<bool>>
|
||||
}
|
||||
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: Some(closure),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
stale: Arc::new(Mutex::new(false)) };
|
||||
|
||||
impl<T: Send + 'static> WillBe<T> where {
|
||||
pub fn new_become(closure: HClosure<T>)
|
||||
-> WillBe<T> {
|
||||
let mut willbe = WillBe { state: Arc::new(Mutex::new(State::Becoming)),
|
||||
thing: Arc::new(Mutex::new(None)),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
stale: Arc::new(Mutex::new(false)) };
|
||||
willbe.run(closure);
|
||||
willbe
|
||||
async_value
|
||||
}
|
||||
|
||||
fn run(&mut self, closure: HClosure<T>) {
|
||||
let state = self.state.clone();
|
||||
fn run(&mut self) -> HResult<()> {
|
||||
let closure = self.async_closure.take()?;
|
||||
let async_value = self.async_value.clone();
|
||||
let stale = self.stale.clone();
|
||||
let thing = self.thing.clone();
|
||||
let on_ready_fn = self.on_ready.clone();
|
||||
std::thread::spawn(move|| {
|
||||
let got_thing = closure(stale);
|
||||
match got_thing {
|
||||
Ok(got_thing) => {
|
||||
*thing.lock().unwrap() = Some(got_thing);
|
||||
*state.lock().unwrap() = State::Is;
|
||||
match *on_ready_fn.lock().unwrap() {
|
||||
Some(ref on_ready) => { on_ready(thing.clone()).ok(); },
|
||||
|
||||
std::thread::spawn(move|| -> HResult<()> {
|
||||
let value = closure(stale);
|
||||
match value {
|
||||
Ok(mut value) => {
|
||||
match *on_ready_fn.lock()? {
|
||||
Some(ref on_ready) => { on_ready(&mut value).log(); },
|
||||
None => {}
|
||||
}
|
||||
async_value.lock()?.replace(Ok(value));
|
||||
},
|
||||
Err(err) => *state.lock().unwrap() = State::Fail(err)
|
||||
Err(err) => *async_value.lock()? = Some(Err(err))
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_stale(&mut self) -> HResult<()> {
|
||||
|
@ -87,23 +90,46 @@ impl<T: Send + 'static> WillBe<T> where {
|
|||
is_stale(&self.stale)
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> HResult<T> {
|
||||
self.check()?;
|
||||
Ok(self.thing.lock()?.take()?)
|
||||
pub fn take_async(&mut self) -> HResult<()> {
|
||||
if self.value.is_ok() { return Ok(()) }
|
||||
|
||||
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 check(&self) -> HResult<()> {
|
||||
match *self.state.lock()? {
|
||||
State::Is => Ok(()),
|
||||
_ => Err(HError::WillBeNotReady(Backtrace::new()))
|
||||
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: Box<Fn(Arc<Mutex<Option<T>>>) -> HResult<()> + Send>)
|
||||
fun: AsyncReadyFn<T>)
|
||||
-> HResult<()> {
|
||||
if self.check().is_ok() {
|
||||
fun(self.thing.clone())?;
|
||||
if self.value.is_ok() {
|
||||
fun(self.value.as_mut().unwrap())?;
|
||||
} else {
|
||||
*self.on_ready.lock()? = Some(fun);
|
||||
}
|
||||
|
@ -111,8 +137,8 @@ impl<T: Send + 'static> WillBe<T> where {
|
|||
}
|
||||
}
|
||||
|
||||
impl<W: Widget + Send + 'static> PartialEq for WillBeWidget<W> {
|
||||
fn eq(&self, other: &WillBeWidget<W>) -> bool {
|
||||
impl<W: Widget + Send + 'static> PartialEq for AsyncWidget<W> {
|
||||
fn eq(&self, other: &AsyncWidget<W>) -> bool {
|
||||
if self.get_coordinates().unwrap() ==
|
||||
other.get_coordinates().unwrap() {
|
||||
true
|
||||
|
@ -122,65 +148,66 @@ impl<W: Widget + Send + 'static> PartialEq for WillBeWidget<W> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct WillBeWidget<T: Widget + Send + 'static> {
|
||||
willbe: WillBe<T>,
|
||||
|
||||
pub struct AsyncWidget<W: Widget + Send + 'static> {
|
||||
widget: Async<W>,
|
||||
core: WidgetCore
|
||||
}
|
||||
|
||||
impl<T: Widget + Send + 'static> WillBeWidget<T> {
|
||||
pub fn new(core: &WidgetCore, closure: HClosure<T>) -> WillBeWidget<T> {
|
||||
impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
||||
pub fn new(core: &WidgetCore, closure: AsyncValueFn<W>) -> AsyncWidget<W> {
|
||||
let sender = core.get_sender();
|
||||
let mut willbe = WillBe::new_become(Box::new(move |stale| closure(stale)));
|
||||
willbe.on_ready(Box::new(move |_| {
|
||||
let mut widget = Async::new(Box::new(move |stale| closure(stale)));
|
||||
widget.on_ready(Box::new(move |_| {
|
||||
sender.send(crate::widget::Events::WidgetReady)?;
|
||||
Ok(()) })).ok();
|
||||
Ok(())
|
||||
})).log();
|
||||
widget.run().log();
|
||||
|
||||
WillBeWidget {
|
||||
willbe: willbe,
|
||||
AsyncWidget {
|
||||
widget: widget,
|
||||
core: core.clone()
|
||||
}
|
||||
}
|
||||
pub fn change_to(&mut self, closure: HCClosure<T>) -> HResult<()> {
|
||||
pub fn change_to(&mut self, closure: AsyncWidgetFn<W>) -> HResult<()> {
|
||||
self.set_stale().log();
|
||||
|
||||
let sender = self.get_core()?.get_sender();
|
||||
let core = self.get_core()?.clone();
|
||||
|
||||
let mut willbe = WillBe::new_become(Box::new(move |stale| {
|
||||
let core = core.clone();
|
||||
closure(stale, core)
|
||||
let mut widget = Async::new(Box::new(move |stale| {
|
||||
closure(stale, core.clone())
|
||||
}));
|
||||
willbe.on_ready(Box::new(move |_| {
|
||||
|
||||
widget.on_ready(Box::new(move |_| {
|
||||
sender.send(crate::widget::Events::WidgetReady)?;
|
||||
Ok(())
|
||||
}))?;
|
||||
|
||||
self.willbe = willbe;
|
||||
widget.run().log();
|
||||
|
||||
self.widget = widget;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_stale(&mut self) -> HResult<()> {
|
||||
self.willbe.set_stale()
|
||||
self.widget.set_stale()
|
||||
}
|
||||
|
||||
pub fn is_stale(&self) -> HResult<bool> {
|
||||
self.willbe.is_stale()
|
||||
self.widget.is_stale()
|
||||
}
|
||||
|
||||
pub fn widget(&self) -> HResult<Arc<Mutex<Option<T>>>> {
|
||||
self.willbe.check()?;
|
||||
Ok(self.willbe.thing.clone())
|
||||
pub fn widget(&self) -> HResult<&W> {
|
||||
self.widget.get()
|
||||
}
|
||||
|
||||
pub fn widget_mut(&mut self) -> HResult<&mut W> {
|
||||
self.widget.get_mut()
|
||||
}
|
||||
|
||||
pub fn ready(&self) -> bool {
|
||||
match self.willbe.check() {
|
||||
Ok(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> HResult<T> {
|
||||
self.willbe.take()
|
||||
self.widget().is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +222,7 @@ impl<T: Widget + Send + 'static> WillBeWidget<T> {
|
|||
// }
|
||||
//}
|
||||
|
||||
impl<T: Widget + Send + 'static> Widget for WillBeWidget<T> {
|
||||
impl<T: Widget + Send + 'static> Widget for AsyncWidget<T> {
|
||||
fn get_core(&self) -> HResult<&WidgetCore> {
|
||||
Ok(&self.core)
|
||||
}
|
||||
|
@ -205,22 +232,19 @@ impl<T: Widget + Send + 'static> Widget for WillBeWidget<T> {
|
|||
|
||||
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
|
||||
self.core.coordinates = coordinates.clone();
|
||||
if let Ok(widget) = self.widget() {
|
||||
let mut widget = widget.lock()?;
|
||||
let widget = widget.as_mut()?;
|
||||
if let Ok(widget) = self.widget_mut() {
|
||||
widget.set_coordinates(&coordinates)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn refresh(&mut self) -> HResult<()> {
|
||||
let coords = self.get_coordinates()?;
|
||||
if let Ok(widget) = self.widget() {
|
||||
let mut widget = widget.lock()?;
|
||||
let widget = widget.as_mut()?;
|
||||
self.widget.take_async().log();
|
||||
|
||||
if widget.get_coordinates()? != coords {
|
||||
widget.set_coordinates(self.get_coordinates()?)?;
|
||||
let coords = self.get_coordinates()?.clone();
|
||||
if let Ok(widget) = self.widget_mut() {
|
||||
if widget.get_coordinates()? != &coords {
|
||||
widget.set_coordinates(&coords)?;
|
||||
widget.refresh()?;
|
||||
} else {
|
||||
widget.refresh()?;
|
||||
|
@ -229,7 +253,7 @@ impl<T: Widget + Send + 'static> Widget for WillBeWidget<T> {
|
|||
Ok(())
|
||||
}
|
||||
fn get_drawlist(&self) -> HResult<String> {
|
||||
if self.willbe.check().is_err() {
|
||||
if self.widget().is_err() {
|
||||
let clear = self.get_clearlist()?;
|
||||
let (xpos, ypos) = self.get_coordinates()?.u16position();
|
||||
let pos = crate::term::goto_xy(xpos, ypos);
|
||||
|
@ -240,17 +264,11 @@ impl<T: Widget + Send + 'static> Widget for WillBeWidget<T> {
|
|||
return self.get_clearlist()
|
||||
}
|
||||
|
||||
let widget = self.widget()?;
|
||||
let widget = widget.lock()?;
|
||||
let widget = widget.as_ref()?;
|
||||
widget.get_drawlist()
|
||||
self.widget()?.get_drawlist()
|
||||
}
|
||||
fn on_key(&mut self, key: termion::event::Key) -> HResult<()> {
|
||||
if self.willbe.check().is_err() { return Ok(()) }
|
||||
let widget = self.widget()?;
|
||||
let mut widget = widget.lock()?;
|
||||
let widget = widget.as_mut()?;
|
||||
widget.on_key(key)
|
||||
if self.widget().is_err() { return Ok(()) }
|
||||
self.widget_mut()?.on_key(key)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +285,7 @@ impl PartialEq for Previewer {
|
|||
}
|
||||
|
||||
pub struct Previewer {
|
||||
widget: WillBeWidget<Box<dyn Widget + Send>>,
|
||||
widget: AsyncWidget<Box<dyn Widget + Send>>,
|
||||
core: WidgetCore,
|
||||
file: Option<File>,
|
||||
selection: Option<File>,
|
||||
|
@ -278,11 +296,10 @@ pub struct Previewer {
|
|||
impl Previewer {
|
||||
pub fn new(core: &WidgetCore) -> Previewer {
|
||||
let core_ = core.clone();
|
||||
let willbe = WillBeWidget::new(&core, Box::new(move |_| {
|
||||
Ok(Box::new(crate::textview::TextView::new_blank(&core_))
|
||||
as Box<dyn Widget + Send>)
|
||||
let widget = AsyncWidget::new(&core, Box::new(move |_| {
|
||||
Ok(Box::new(TextView::new_blank(&core_)) as Box<dyn Widget + Send>)
|
||||
}));
|
||||
Previewer { widget: willbe,
|
||||
Previewer { widget: widget,
|
||||
core: core.clone(),
|
||||
file: None,
|
||||
selection: None,
|
||||
|
@ -290,10 +307,11 @@ impl Previewer {
|
|||
}
|
||||
|
||||
fn become_preview(&mut self,
|
||||
widget: HResult<WillBeWidget<WidgetO>>) {
|
||||
let coordinates = self.get_coordinates().unwrap().clone();
|
||||
self.widget = widget.unwrap();
|
||||
self.widget.set_coordinates(&coordinates).ok();
|
||||
widget: HResult<AsyncWidget<WidgetO>>) -> HResult<()> {
|
||||
let coordinates = self.get_coordinates()?.clone();
|
||||
self.widget = widget?;
|
||||
self.widget.set_coordinates(&coordinates)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_stale(&mut self) -> HResult<()> {
|
||||
|
@ -315,7 +333,8 @@ impl Previewer {
|
|||
|
||||
self.widget.set_stale().ok();
|
||||
|
||||
self.become_preview(Ok(WillBeWidget::new(&self.core, Box::new(move |stale| {
|
||||
self.become_preview(Ok(AsyncWidget::new(&self.core,
|
||||
Box::new(move |stale| {
|
||||
kill_proc().unwrap();
|
||||
|
||||
let file = file.clone();
|
||||
|
@ -344,15 +363,14 @@ impl Previewer {
|
|||
blank.animate_slide_up().log();
|
||||
return Ok(blank)
|
||||
}
|
||||
}))));
|
||||
Ok(())
|
||||
}))))
|
||||
}
|
||||
|
||||
pub fn reload(&mut self) {
|
||||
if let Some(file) = self.file.clone() {
|
||||
self.file = None;
|
||||
let cache = self.cached_files.take();
|
||||
self.set_file(&file, self.selection.clone(), cache);
|
||||
self.set_file(&file, self.selection.clone(), cache).log();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,7 +421,9 @@ impl Previewer {
|
|||
Ok(Box::new(textview))
|
||||
}
|
||||
|
||||
fn preview_external(file: &File, core: &WidgetCore, stale: Arc<Mutex<bool>>)
|
||||
fn preview_external(file: &File,
|
||||
core: &WidgetCore,
|
||||
stale: Arc<Mutex<bool>>)
|
||||
-> Result<Box<dyn Widget + Send>, HError> {
|
||||
let process =
|
||||
std::process::Command::new("scope.sh")
|
||||
|
|
|
@ -15,7 +15,6 @@ use crate::widget::{Widget, Events, WidgetCore};
|
|||
use crate::coordinates::Coordinates;
|
||||
use crate::dirty::Dirtyable;
|
||||
use crate::hbox::HBox;
|
||||
use crate::preview::WillBeWidget;
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
use crate::term;
|
||||
use crate::files::{File, OsStrTools};
|
||||
|
@ -299,7 +298,7 @@ impl ListView<Vec<Process>> {
|
|||
#[derive(PartialEq)]
|
||||
enum ProcViewWidgets {
|
||||
List(ListView<Vec<Process>>),
|
||||
TextView(WillBeWidget<TextView>),
|
||||
TextView(TextView),
|
||||
}
|
||||
|
||||
impl Widget for ProcViewWidgets {
|
||||
|
@ -348,7 +347,7 @@ impl HBox<ProcViewWidgets> {
|
|||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
fn get_textview(&mut self) -> &mut WillBeWidget<TextView> {
|
||||
fn get_textview(&mut self) -> &mut TextView {
|
||||
match &mut self.widgets[1] {
|
||||
ProcViewWidgets::TextView(textview) => textview,
|
||||
_ => unreachable!()
|
||||
|
@ -360,8 +359,7 @@ impl ProcView {
|
|||
pub fn new(core: &WidgetCore) -> ProcView {
|
||||
let tcore = core.clone();
|
||||
let listview = ListView::new(&core, vec![]);
|
||||
let textview = Box::new(move |_| Ok(TextView::new_blank(&tcore)));
|
||||
let textview = WillBeWidget::new(&core, textview);
|
||||
let textview = TextView::new_blank(&tcore);
|
||||
let mut hbox = HBox::new(&core);
|
||||
hbox.push_widget(ProcViewWidgets::List(listview));
|
||||
hbox.push_widget(ProcViewWidgets::TextView(textview));
|
||||
|
@ -382,7 +380,7 @@ impl ProcView {
|
|||
self.hbox.get_listview_mut()
|
||||
}
|
||||
|
||||
fn get_textview(&mut self) -> &mut WillBeWidget<TextView> {
|
||||
fn get_textview(&mut self) -> &mut TextView {
|
||||
self.hbox.get_textview()
|
||||
}
|
||||
|
||||
|
@ -399,13 +397,8 @@ impl ProcView {
|
|||
pub fn remove_proc(&mut self) -> HResult<()> {
|
||||
if self.get_listview_mut().content.len() == 0 { return Ok(()) }
|
||||
self.get_listview_mut().remove_proc()?;
|
||||
self.get_textview().change_to(Box::new(move |_, core| {
|
||||
let mut textview = TextView::new_blank(&core);
|
||||
textview.refresh().log();
|
||||
textview.animate_slide_up().log();
|
||||
Ok(textview)
|
||||
})).log();
|
||||
Ok(())
|
||||
self.get_textview().clear();
|
||||
self.get_textview().set_text("")
|
||||
}
|
||||
|
||||
fn show_output(&mut self) -> HResult<()> {
|
||||
|
@ -414,48 +407,45 @@ impl ProcView {
|
|||
}
|
||||
let output = self.get_listview_mut().selected_proc()?.output.lock()?.clone();
|
||||
|
||||
self.get_textview().change_to(Box::new(move |_, core| {
|
||||
let mut textview = TextView::new_blank(&core);
|
||||
textview.set_text(&output).log();
|
||||
textview.animate_slide_up().log();
|
||||
Ok(textview)
|
||||
})).log();
|
||||
self.get_textview().set_text(&output).log();
|
||||
self.get_textview().animate_slide_up().log();
|
||||
|
||||
self.viewing = Some(self.get_listview_mut().get_selection());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn toggle_follow(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.toggle_follow();
|
||||
self.get_textview().toggle_follow();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn scroll_up(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.scroll_up();
|
||||
self.get_textview().scroll_up();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn scroll_down(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.scroll_down();
|
||||
self.get_textview().scroll_down();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn page_up(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.page_up();
|
||||
self.get_textview().page_up();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn page_down(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.page_down();
|
||||
self.get_textview().page_down();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn scroll_top(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.scroll_top();
|
||||
self.get_textview().scroll_top();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn scroll_bottom(&mut self) -> HResult<()> {
|
||||
self.get_textview().widget()?.lock()?.as_mut()?.scroll_bottom();
|
||||
self.get_textview().scroll_bottom();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue