summaryrefslogtreecommitdiffstats
path: root/src/file_browser.rs
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-04-06 17:22:28 +0200
committerrabite <rabite@posteo.de>2019-04-06 17:22:28 +0200
commit7f70fa29046e09be414b52ba572eb9675979cd46 (patch)
tree49c753d75c71c43b6ca2d3093e5b361822e7361a /src/file_browser.rs
parentcab0de7a05fd446e68fc10d37253d67400c33417 (diff)
parent6098ad301595c0c808634fe03e2d194d3fc65c3c (diff)
Merge branch 'master' into evil
Diffstat (limited to 'src/file_browser.rs')
-rw-r--r--src/file_browser.rs708
1 files changed, 449 insertions, 259 deletions
diff --git a/src/file_browser.rs b/src/file_browser.rs
index d083896..9458da7 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -1,21 +1,19 @@
use termion::event::Key;
-use notify::{INotifyWatcher, Watcher, DebouncedEvent, RecursiveMode};
use std::io::Write;
-use std::sync::{Arc, Mutex};
-use std::sync::mpsc::{channel, Receiver, Sender};
-use std::time::Duration;
+use std::sync::{Arc, Mutex, RwLock};
use std::path::PathBuf;
-use std::collections::HashMap;
-use std::ffi::{OsString, OsStr};
+use std::ffi::OsString;
+use std::collections::HashSet;
-use crate::files::{File, Files, PathBufExt, OsStrTools};
+use crate::files::{File, Files, PathBufExt};
+use crate::fscache::FsCache;
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::textview::TextView;
use crate::fail::{HResult, HError, ErrorLog};
use crate::widget::{Events, WidgetCore};
use crate::proclist::ProcView;
@@ -24,42 +22,50 @@ use crate::term;
use crate::term::ScreenExt;
use crate::foldview::LogView;
use crate::coordinates::Coordinates;
+use crate::dirty::Dirtyable;
+use crate::stats::{FsStat, FsExt};
#[derive(PartialEq)]
pub enum FileBrowserWidgets {
- FileList(WillBeWidget<ListView<Files>>),
+ FileList(AsyncWidget<ListView<Files>>),
Previewer(Previewer),
+ Blank(AsyncWidget<TextView>),
}
impl Widget for FileBrowserWidgets {
fn get_core(&self) -> HResult<&WidgetCore> {
match self {
FileBrowserWidgets::FileList(widget) => widget.get_core(),
- FileBrowserWidgets::Previewer(widget) => widget.get_core()
+ FileBrowserWidgets::Previewer(widget) => widget.get_core(),
+ FileBrowserWidgets::Blank(widget) => widget.get_core(),
}
}
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
match self {
FileBrowserWidgets::FileList(widget) => widget.get_core_mut(),
- FileBrowserWidgets::Previewer(widget) => widget.get_core_mut()
+ FileBrowserWidgets::Previewer(widget) => widget.get_core_mut(),
+ FileBrowserWidgets::Blank(widget) => widget.get_core_mut(),
}
}
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
match self {
FileBrowserWidgets::FileList(widget) => widget.set_coordinates(coordinates),
FileBrowserWidgets::Previewer(widget) => widget.set_coordinates(coordinates),
+ FileBrowserWidgets::Blank(widget) => widget.set_coordinates(coordinates),
}
}
fn refresh(&mut self) -> HResult<()> {
match self {
FileBrowserWidgets::FileList(widget) => widget.refresh(),
- FileBrowserWidgets::Previewer(widget) => widget.refresh()
+ FileBrowserWidgets::Previewer(widget) => widget.refresh(),
+ FileBrowserWidgets::Blank(widget) => widget.refresh(),
}
}
fn get_drawlist(&self) -> HResult<String> {
match self {
FileBrowserWidgets::FileList(widget) => widget.get_drawlist(),
- FileBrowserWidgets::Previewer(widget) => widget.get_drawlist()
+ FileBrowserWidgets::Previewer(widget) => widget.get_drawlist(),
+ FileBrowserWidgets::Blank(widget) => widget.get_drawlist(),
}
}
}
@@ -68,35 +74,39 @@ pub struct FileBrowser {
pub columns: HBox<FileBrowserWidgets>,
pub cwd: File,
pub prev_cwd: Option<File>,
- selections: HashMap<File, File>,
- cached_files: HashMap<File, Files>,
core: WidgetCore,
- watcher: INotifyWatcher,
- watches: Vec<PathBuf>,
- dir_events: Arc<Mutex<Vec<DebouncedEvent>>>,
proc_view: Arc<Mutex<ProcView>>,
bookmarks: Arc<Mutex<BMPopup>>,
- log_view: Arc<Mutex<LogView>>
+ log_view: Arc<Mutex<LogView>>,
+ fs_cache: FsCache,
+ fs_stat: Arc<RwLock<FsStat>>
}
impl Tabbable for TabView<FileBrowser> {
fn new_tab(&mut self) -> HResult<()> {
- let mut tab = FileBrowser::new_cored(&self.active_tab_().core)?;
+ let cur_tab = self.active_tab_();
+
+ let settings = cur_tab.fs_cache.tab_settings.read()?.clone();
+ let cache = cur_tab.fs_cache.new_client(settings).ok();
- let proc_view = self.active_tab_().proc_view.clone();
- let bookmarks = self.active_tab_().bookmarks.clone();
- let log_view = self.active_tab_().log_view.clone();
+ let mut tab = FileBrowser::new(&self.active_tab_().core, cache)?;
+
+ let proc_view = cur_tab.proc_view.clone();
+ let bookmarks = cur_tab.bookmarks.clone();
+ let log_view = cur_tab.log_view.clone();
tab.proc_view = proc_view;
tab.bookmarks = bookmarks;
tab.log_view = log_view;
+ tab.fs_stat = cur_tab.fs_stat.clone();
self.push_widget(tab)?;
- self.active += 1;
+ self.active = self.widgets.len() - 1;
Ok(())
}
fn close_tab(&mut self) -> HResult<()> {
- self.close_tab_()
+ self.close_tab_().log();
+ Ok(())
}
fn next_tab(&mut self) -> HResult<()> {
@@ -148,29 +158,79 @@ impl Tabbable for TabView<FileBrowser> {
_ => { self.active_tab_mut().on_key(key) }
}
}
-}
-
+ fn on_refresh(&mut self) -> HResult<()> {
+ let fs_changes = self.active_tab_()
+ .fs_cache
+ .fs_changes
+ .write()?
+ .drain(..)
+ .collect::<Vec<_>>();
+
+ for tab in &mut self.widgets {
+ for (dir, old_file, new_file) in fs_changes.iter() {
+ tab.replace_file(&dir,
+ old_file.as_ref(),
+ new_file.as_ref()).log()
+ }
+ }
+ let open_dirs = self.widgets
+ .iter()
+ .fold(HashSet::new(), |mut dirs, tab| {
+ tab.left_dir().map(|dir| dirs.insert(dir.clone())).ok();
+ dirs.insert(tab.cwd.clone());
+ tab.preview_widget()
+ .map(|preview| preview.get_file().map(|file| {
+ if file.is_dir() {
+ dirs.insert(file.clone());
+ }
+ })).ok();
+ dirs
+ });
+ self.active_tab_mut_().fs_cache.watch_only(open_dirs).log();
+ self.active_tab_mut_().fs_stat.write()?.refresh().log();
+ Ok(())
+ }
-fn watch_dir(rx: Receiver<DebouncedEvent>,
- dir_events: Arc<Mutex<Vec<DebouncedEvent>>>,
- sender: Sender<Events>) {
- std::thread::spawn(move || {
- for event in rx.iter() {
- dir_events.lock().unwrap().push(event);
- sender.send(Events::WidgetReady).unwrap();
+ 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();
+
+ tab.preview_widget_mut().map(|w| w.config_loaded()).ok();
}
- });
+ Ok(())
+ }
}
+
+
impl FileBrowser {
- pub fn new_cored(core: &WidgetCore) -> HResult<FileBrowser> {
+ pub fn new(core: &WidgetCore, cache: Option<FsCache>) -> HResult<FileBrowser> {
+ let startup = cache.is_none();
+ let fs_cache = cache.unwrap_or_else(|| FsCache::new(core.get_sender()));
+
let cwd = std::env::current_dir().unwrap();
let mut core_m = core.clone();
let mut core_l = core.clone();
@@ -191,25 +251,80 @@ 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 mut list = ListView::new(&core_m,
- Files::new_from_path(&main_path)?);
- list.animate_slide_up().log();
+ let cache = fs_cache.clone();
+ let main_widget = AsyncWidget::new(&core, Box::new(move |_| {
+ let name = if main_path.parent().is_none() {
+ "root".to_string()
+ } else {
+ main_path.file_name()?
+ .to_string_lossy()
+ .to_string()
+ };
+ let main_dir = File::new(&name,
+ main_path.clone(),
+ None);
+ let files = cache.get_files_sync(&main_dir)?;
+ let selection = cache.get_selection(&main_dir).ok();
+ let mut list = ListView::new(&core_m.clone(),
+ files);
+ if let Some(file) = selection {
+ list.select_file(&file);
+ }
+
+ list.content.meta_all();
+ list.content.dirty_meta.set_dirty();
+ list.refresh().log();
+
+ if startup {
+ list.animate_slide_up(None).log();
+ }
+
+ list.content.meta_all();
Ok(list)
}));
+ let cache = fs_cache.clone();
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 name = if left_path.parent().is_none() {
+ "root".to_string()
+ } else {
+ left_path.file_name()?
+ .to_string_lossy()
+ .to_string()
+ };
+ let left_dir = File::new(&name,
+ left_path.clone(),
+ None);
+ let files = cache.get_files_sync(&left_dir)?;
+ let selection = cache.get_selection(&left_dir).ok();
let mut list = ListView::new(&core_l,
- Files::new_from_path(&left_path)?);
- list.animate_slide_up().log();
+ files);
+ if let Some(file) = selection {
+ list.select_file(&file);
+ }
+
+ list.refresh().log();
+
+ if startup {
+ list.animate_slide_up(None).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 blank = TextView::new_blank(&core_l);
+ Ok(blank)
+ }));
+
+ let left_widget = FileBrowserWidgets::Blank(left_widget);
+ columns.push_widget(left_widget);
}
- let previewer = Previewer::new(&core_p);
+ let previewer = Previewer::new(&core_p, fs_cache.clone());
columns.push_widget(FileBrowserWidgets::FileList(main_widget));
columns.push_widget(FileBrowserWidgets::Previewer(previewer));
@@ -217,38 +332,76 @@ impl FileBrowser {
columns.refresh().log();
- let cwd = File::new_from_path(&cwd).unwrap();
- let dir_events = Arc::new(Mutex::new(vec![]));
-
- let (tx_watch, rx_watch) = channel();
- let watcher = INotifyWatcher::new(tx_watch, Duration::from_secs(2)).unwrap();
- watch_dir(rx_watch, dir_events.clone(), core.get_sender());
+ let cwd = File::new_from_path(&cwd, None).unwrap();
let proc_view = ProcView::new(&core);
let bookmarks = BMPopup::new(&core);
let log_view = LogView::new(&core, vec![]);
+ let fs_stat = FsStat::new().unwrap();
Ok(FileBrowser { columns: columns,
cwd: cwd,
prev_cwd: None,
- selections: HashMap::new(),
- cached_files: HashMap::new(),
core: core.clone(),
- watcher: watcher,
- watches: vec![],
- dir_events: dir_events,
proc_view: Arc::new(Mutex::new(proc_view)),
bookmarks: Arc::new(Mutex::new(bookmarks)),
- log_view: Arc::new(Mutex::new(log_view)) })
+ log_view: Arc::new(Mutex::new(log_view)),
+ fs_cache: fs_cache,
+ fs_stat: Arc::new(RwLock::new(fs_stat))
+ })
}
pub fn enter_dir(&mut self) -> HResult<()> {
let file = self.selected_file()?;
if file.is_dir() {
- self.main_widget_goto(&file).log();
+ let dir = file;
+ match dir.is_readable() {
+ Ok(true) => {},
+ Ok(false) => {
+ let status =
+ format!("{}Stop right there, cowboy! Check your permisions!",
+ term::color_red());
+ self.show_status(&status).log();
+ return Ok(());
+ }
+ err @ Err(_) => err.log()
+ }
+
+ let previewer_files = self.preview_widget_mut()?.take_files().ok();
+
+ self.columns.remove_widget(0);
+
+ self.prev_cwd = Some(self.cwd.clone());
+ self.cwd = dir.clone();
+
+ let core = self.core.clone();
+ let cache = self.fs_cache.clone();
+
+ let main_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
+ let files = match previewer_files {
+ Some(files) => files,
+ None => cache.get_files_sync(&dir)?
+ };
+
+ let selection = cache.get_selection(&dir).ok();
+
+ let mut list = ListView::new(&core, files);
+
+ if let Some(file) = selection {
+ list.select_file(&file);
+ }
+
+ list.content.meta_all();
+
+ Ok(list)
+ }));
+
+ let main_widget = FileBrowserWidgets::FileList(main_widget);
+ self.columns.insert_widget(1, main_widget);
+
} else {
self.core.get_sender().send(Events::InputEnabled(false))?;
@@ -293,40 +446,26 @@ impl FileBrowser {
}
pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
- match dir.is_readable() {
- Ok(true) => {},
- Ok(false) => {
- let status =
- format!("{}Stop right there, cowboy! Check your permisions!",
- term::color_red());
- self.show_status(&status).log();
- return Ok(());
- }
- err @ Err(_) => err.log()
- }
+ self.cache_files().log();
let dir = dir.clone();
- let selected_file = self.get_selection(&dir).ok().cloned();
-
- self.get_files().and_then(|files| self.cache_files(files)).log();
- let cached_files = self.get_cached_files(&dir).ok();
+ let cache = self.fs_cache.clone();
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 path = dir.path();
- let cached_files = cached_files.clone();
-
- let files = cached_files.or_else(|| {
- Files::new_from_path_cancellable(&path, stale).ok()
- })?;
+ 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()?;
let mut list = ListView::new(&core, files);
- if let Some(file) = &selected_file {
- list.select_file(file);
+ list.content.meta_set_fresh().log();
+ list.content.meta_all();
+
+ if let Some(file) = selected_file {
+ list.select_file(&file);
}
Ok(list)
})).log();
@@ -334,25 +473,24 @@ 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()?.change_to(Box::new(move |_,_| {
+ HError::stale()?
+ })).log();
}
Ok(())
}
pub fn left_widget_goto(&mut self, dir: &File) -> HResult<()> {
- self.get_left_files().and_then(|files| self.cache_files(files)).log();
- let cached_files = self.get_cached_files(&dir).ok();
+ let cache = self.fs_cache.clone();
let dir = dir.clone();
- let left_widget = self.left_widget_mut()?;
- left_widget.change_to(Box::new(move |stale, core| {
- let path = dir.path();
- let cached_files = cached_files.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)?;
+ let (_, files) = cached_files;
- let files = cached_files.or_else(|| {
- Files::new_from_path_cancellable(&path, stale).ok()
- })?;
+ let files = files.wait()?;
let list = ListView::new(&core, files);
Ok(list)
@@ -362,9 +500,42 @@ impl FileBrowser {
pub fn go_back(&mut self) -> HResult<()> {
if let Ok(new_cwd) = self.cwd.parent_as_file() {
- self.main_widget_goto(&new_cwd).log();
+ let core = self.core.clone();
+ let preview_files = self.take_main_files();
+ let old_left = self.columns.remove_widget(0);
+ self.prev_cwd = Some(self.cwd.clone());
+ self.cwd = new_cwd.clone();
+
+ 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 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 blank = TextView::new_blank(&core);
+ Ok(blank)
+ }));
+
+ let left_widget = FileBrowserWidgets::Blank(left_widget);
+ self.columns.prepend_widget(left_widget);
+ }
+ self.columns.replace_widget(1, old_left);
+ self.main_widget_mut()?.content.meta_all();
+
+ if let Ok(preview_files) = preview_files {
+ self.preview_widget_mut().map(|preview| {
+ preview.put_preview_files(preview_files)
+ }).ok();
+ }
}
+ self.columns.resize_children().log();
self.refresh()
}
@@ -380,15 +551,26 @@ impl FileBrowser {
None => &self.cwd
}.path.to_string_lossy().to_string();
+ self.bookmarks.lock()?.set_coordinates(&self.core.coordinates).log();
+
loop {
let bookmark = self.bookmarks.lock()?.pick(cwd.to_string());
if let Err(HError::TerminalResizedError) = bookmark {
- self.core.screen.clear().log();
- self.resize().log();
- self.refresh().log();
- self.draw().log();
- continue;
+ self.core.screen.clear().log();
+ self.resize().log();
+ self.refresh().log();
+ self.draw().log();
+ continue;
+ }
+
+ if let Err(HError::WidgetResizedError) = bookmark {
+ let coords = &self.core.coordinates;
+ self.bookmarks.lock()?.set_coordinates(&coords).log();
+ self.core.screen.clear().log();
+ self.refresh().log();
+ self.draw().log();
+ continue;
}
return bookmark;
}
@@ -396,13 +578,15 @@ impl FileBrowser {
pub fn goto_bookmark(&mut self) -> HResult<()> {
let path = self.get_boomark()?;
- let path = File::new_from_path(&PathBuf::from(path))?;
+ let path = File::new_from_path(&PathBuf::from(path), None)?;
self.main_widget_goto(&path)?;
Ok(())
}
pub fn add_bookmark(&mut self) -> HResult<()> {
let cwd = self.cwd.path.to_string_lossy().to_string();
+ let coords = &self.core.coordinates;
+ self.bookmarks.lock()?.set_coordinates(&coords).log();
self.bookmarks.lock()?.add(&cwd)?;
Ok(())
}
@@ -415,71 +599,88 @@ 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).log();
Ok(())
}
pub fn set_left_selection(&mut self) -> HResult<()> {
- if !self.left_widget()?.ready() { return Ok(()) }
if self.cwd.parent().is_none() { return Ok(()) }
+ if !self.left_async_widget_mut()?.ready() { return Ok(()) }
- let parent = self.cwd()?.parent_as_file();
+ let selection = self.cwd()?.clone();
- if let Ok(left_selection) = self.get_selection(&parent?) {
- self.left_widget()?.widget()?.lock()?.as_mut()?.select_file(&left_selection);
- }
+ self.left_widget_mut()?.select_file(&selection);
Ok(())
}
- pub fn get_selection(&self, dir: &File) -> HResult<&File> {
- Ok(self.selections.get(dir)?)
- }
+ pub fn take_main_files(&mut self) -> HResult<Files> {
+ let core = self.core.clone();
+ let blank = AsyncWidget::new(&core.clone(), Box::new(move |_| {
+ HError::no_files()
+ }));
+ let blank = FileBrowserWidgets::Blank(blank);
+
+ let old_widget = self.columns.replace_widget(1, blank);
- pub fn get_files(&mut self) -> HResult<Files> {
- Ok(self.main_widget()?.widget()?.lock()?.as_ref()?.content.clone())
+ if let FileBrowserWidgets::FileList(main_widget) = old_widget {
+ let files = main_widget.take_widget()?.content;
+ return Ok(files)
+ }
+ HError::no_files()
}
- pub fn get_left_files(&mut self) -> HResult<Files> {
- Ok(self.left_widget()?.widget()?.lock()?.as_ref()?.content.clone())
+ pub fn take_left_files(&mut self) -> HResult<Files> {
+ let core = self.core.clone();
+ let blank = AsyncWidget::new(&core.clone(), Box::new(move |_| {
+ HError::no_files()
+ }));
+ let blank = FileBrowserWidgets::FileList(blank);
+
+ let old_widget = self.columns.replace_widget(0, blank);
+
+ if let FileBrowserWidgets::FileList(left_widget) = old_widget {
+ let files = left_widget.take_widget()?.content;
+ return Ok(files)
+ }
+ HError::no_files()
}
- pub fn cache_files(&mut self, files: Files) -> HResult<()> {
- let dir = files.directory.clone();
- self.cached_files.insert(dir, files);
- Ok(())
+ pub fn get_files(&self) -> HResult<&Files> {
+ Ok(&self.main_widget()?.content)
}
- pub fn get_cached_files(&mut self, dir: &File) -> HResult<Files> {
- Ok(self.cached_files.get(dir)?.clone())
+ pub fn get_left_files(&self) -> HResult<&Files> {
+ Ok(&self.left_widget()?.content)
}
- pub fn save_selection(&mut self) -> HResult<()> {
- let cwd = self.cwd()?.clone();
- if let Ok(main_selection) = self.selected_file() {
- self.selections.insert(cwd.clone(), main_selection);
- }
- if let Ok(left_dir) = self.cwd()?.parent_as_file() {
- self.selections.insert(left_dir, cwd);
- }
+ pub fn cache_files(&mut self) -> HResult<()> {
+ let files = self.get_files()?;
+ let selected_file = self.selected_file().ok();
+ self.fs_cache.put_files(files, selected_file).log();
+ self.main_widget_mut()?.content.meta_updated = false;
+
+
+ // if self.cwd.parent().is_some() {
+ // let left_selection = self.left_widget()?.clone_selected_file();
+ // let left_files = self.get_left_files()?;
+ // self.fs_cache.put_files(left_files, Some(left_selection)).log();
+ // self.left_widget_mut()?.content.meta_updated = false;
+ // }
+
Ok(())
}
+
pub fn cwd(&self) -> HResult<&File> {
Ok(&self.cwd)
}
@@ -490,123 +691,91 @@ impl FileBrowser {
Ok(())
}
- pub fn left_dir(&self) -> HResult<File> {
- let widget = self.left_widget()?.widget()?;
- let dir = widget.lock()?.as_ref()?.content.directory.clone();
+ pub fn left_dir(&self) -> HResult<&File> {
+ let widget = self.left_widget()?;
+ let dir = &widget.content.directory;
Ok(dir)
}
- fn update_watches(&mut self) -> HResult<()> {
- if !self.left_widget()?.ready() || !self.main_widget()?.ready() {
- return Ok(())
- }
- let watched_dirs = self.watches.clone();
- let cwd = self.cwd()?.clone();
- let left_dir = self.left_dir()?;
- let preview_dir = self.selected_file().ok().map(|f| f.path);
-
- for watched_dir in watched_dirs.iter() {
- if watched_dir != &cwd.path && watched_dir != &left_dir.path &&
- Some(watched_dir.clone()) != preview_dir {
- self.watcher.unwatch(&watched_dir).ok();
- self.watches.remove_item(&watched_dir);
- }
- }
- if !watched_dirs.contains(&cwd.path) {
- self.watcher.watch(&cwd.path, RecursiveMode::NonRecursive)?;
- self.watches.push(cwd.path);
- }
- if !watched_dirs.contains(&left_dir.path) {
- self.watcher.watch(&left_dir.path, RecursiveMode::NonRecursive)?;
- self.watches.push(left_dir.path);
- }
- if let Some(preview_dir) = preview_dir {
- if !watched_dirs.contains(&preview_dir) && preview_dir.is_dir() {
- match self.watcher.watch(&preview_dir, RecursiveMode::NonRecursive) {
- Ok(_) => self.watches.push(preview_dir),
- Err(notify::Error::Io(ioerr)) => {
- if ioerr.kind() != std::io::ErrorKind::PermissionDenied {
- Err(ioerr)?
- }
- }
- err @ _ => err?
- }
- }
+ fn replace_file(&mut self,
+ dir: &File,
+ old: Option<&File>,
+ new: Option<&File>) -> HResult<()> {
+ if &self.cwd == dir {
+ self.main_widget_mut()?.content.replace_file(old, new.cloned()).log();
}
- Ok(())
- }
- 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 left_widget = self.left_widget()?.widget()?;
- let mut left_files = left_widget.lock()?;
- let left_result = left_files.as_mut()?.content.handle_event(event);
-
- match main_result {
- Err(HError::WrongDirectoryError { .. }) => {
- match left_result {
- Err(HError::WrongDirectoryError { .. }) => {
- let preview = self.preview_widget_mut()?;
- preview.reload();
- }, _ => {}
- }
- }, _ => {}
- }
+ self.preview_widget_mut()?.replace_file(dir, old, new).ok();
+
+ if &self.left_dir()? == &dir {
+ self.left_widget_mut()?.content.replace_file(old, new.cloned()).log();
}
- dir_events.lock()?.clear();
Ok(())
}
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>>> {
+ 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) => 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) => Ok(filelist),
+ FileBrowserWidgets::FileList(filelist) => filelist.widget(),
_ => { HError::wrong_widget("previewer", "filelist")? }
};
widget
}
- pub fn main_widget_mut(&mut self) -> HResult<&mut WillBeWidget<ListView<Files>>> {
+ 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) => Ok(filelist),
+ FileBrowserWidgets::FileList(filelist) => filelist.widget_mut(),
_ => { HError::wrong_widget("previewer", "filelist")? }
};
widget
}
- pub fn left_widget(&self) -> HResult<&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) => 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) => Ok(filelist),
+ FileBrowserWidgets::FileList(filelist) => filelist.widget(),
_ => { return HError::wrong_widget("previewer", "filelist"); }
};
widget
}
- pub fn left_widget_mut(&mut self) -> HResult<&mut WillBeWidget<ListView<Files>>> {
+ pub fn left_widget_mut(&mut self) -> HResult<&mut ListView<Files>> {
let widget = match self.columns.widgets.get_mut(0)? {
- FileBrowserWidgets::FileList(filelist) => Ok(filelist),
+ FileBrowserWidgets::FileList(filelist) => filelist.widget_mut(),
_ => { return HError::wrong_widget("previewer", "filelist"); }
};
widget
@@ -627,6 +796,7 @@ impl FileBrowser {
}
pub fn toggle_colums(&mut self) {
+ self.preview_widget().map(|preview| preview.cancel_animation()).log();
self.columns.toggle_zoom().log();
}
@@ -634,13 +804,19 @@ impl FileBrowser {
let cwd = self.cwd()?.clone().path;
let selected_file = self.selected_file()?;
let selected_file = selected_file.path.to_string_lossy();
+ let selected_files = self.selected_files()?;
+
+ let selected_files = selected_files.iter().map(|f| {
+ format!("\"{}\" ", &f.path.to_string_lossy())
+ }).collect::<String>();
let mut filepath = dirs_2::home_dir()?;
filepath.push(".hunter_cwd");
- let output = format!("HUNTER_CWD=\"{}\"\nF=\"{}\"",
+ let output = format!("HUNTER_CWD=\"{}\"\nF=\"{}\"\nMF=({})\n",
cwd.to_str()?,
- selected_file);
+ selected_file,
+ selected_files);
let mut file = std::fs::File::create(filepath)?;
file.write(output.as_bytes())?;
@@ -648,36 +824,12 @@ impl FileBrowser {
}
pub fn turbo_cd(&mut self) -> HResult<()> {
- let dir = self.minibuffer("cd");
-
- match dir {
- Ok(dir) => {
- self.columns.widgets.clear();
- let cwd = File::new_from_path(&std::path::PathBuf::from(&dir))?;
- self.cwd = cwd;
- let dir = std::path::PathBuf::from(&dir);
- let left_dir = std::path::PathBuf::from(&dir);
- 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 files = Files::new_from_path(&dir.clone())?;
- let listview = ListView::new(&mcore, files);
- Ok(listview)
- }));
- let middle = FileBrowserWidgets::FileList(middle);
+ let dir = self.minibuffer("cd")?;
+
+ let path = std::path::PathBuf::from(&dir);
+ let dir = File::new_from_path(&path.canonicalize()?, None)?;
+ self.main_widget_goto(&dir)?;
- let left = WillBeWidget::new(&self.core, Box::new(move |_| {
- let files = Files::new_from_path(&left_dir.parent()?)?;