diff options
author | rabite <rabite@posteo.de> | 2019-04-03 15:35:29 +0200 |
---|---|---|
committer | rabite <rabite@posteo.de> | 2019-04-03 15:35:29 +0200 |
commit | 10d9a5462cd3c64ce8a1e3e6f724fb1528cc99ce (patch) | |
tree | f6acef7291ffcdacc88b2086bb590964041d18eb /src | |
parent | 8bfc707a596c45ce134a427d8c800620042ba78c (diff) |
configurable hidden files/animation
Diffstat (limited to 'src')
-rw-r--r-- | src/config.rs | 58 | ||||
-rw-r--r-- | src/fail.rs | 6 | ||||
-rw-r--r-- | src/file_browser.rs | 15 | ||||
-rw-r--r-- | src/files.rs | 19 | ||||
-rw-r--r-- | src/listview.rs | 26 | ||||
-rw-r--r-- | src/main.rs | 3 | ||||
-rw-r--r-- | src/preview.rs | 10 | ||||
-rw-r--r-- | src/tabview.rs | 7 | ||||
-rw-r--r-- | src/widget.rs | 41 |
9 files changed, 168 insertions, 17 deletions
diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..4801286 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,58 @@ +use crate::paths; +use crate::fail::{HError, HResult, ErrorLog}; + +#[derive(Debug, Clone)] +pub struct Config { + pub animation: bool, + pub show_hidden: bool, +} + + +impl Config { + pub fn new() -> Config { + Config { + animation: true, + show_hidden: false + } + } + + pub fn load() -> HResult<Config> { + let config_path = paths::config_path()?; + + if !config_path.exists() { + return Ok(Config::new()); + } + + let config_string = std::fs::read_to_string(config_path)?; + + let config = config_string.lines().fold(Config::new(), |mut config, line| { + match Config::prep_line(line) { + Ok(("animation", "on")) => { config.animation = true; }, + Ok(("animation", "off")) => { config.animation = false; }, + Ok(("show_hidden", "on")) => { config.show_hidden = true; }, + Ok(("show_hidden", "off")) => { config.show_hidden = false; }, + _ => { HError::config_error::<Config>(line.to_string()).log(); } + } + config + }); + Ok(config) + } + + fn prep_line<'a>(line: &'a str) -> HResult<(&'a str, &'a str)> { + let setting = line.split("=").collect::<Vec<&str>>(); + if setting.len() == 2 { + Ok((setting[0], setting[1])) + } else { + HError::config_error(line.to_string()) + } + + } + + pub fn animate(&self) -> bool { + self.animation + } + + pub fn show_hidden(&self) -> bool { + self.show_hidden + } +} diff --git a/src/fail.rs b/src/fail.rs index 064f721..a189855 100644 --- a/src/fail.rs +++ b/src/fail.rs @@ -89,6 +89,8 @@ pub enum HError { MetadataProcessedError, #[fail(display = "No files to take from widget")] WidgetNoFilesError, + #[fail(display = "Invalid line in settings file: {}", _0)] + ConfigLineError(String), } impl HError { @@ -147,6 +149,10 @@ impl HError { Err(HError::StaleError) } + pub fn config_error<T>(line: String) -> HResult<T> { + Err(HError::ConfigLineError(line)) + } + pub fn async_not_ready<T>() -> HResult<T> { Err(HError::AsyncNotReadyError) } diff --git a/src/file_browser.rs b/src/file_browser.rs index 17e7b05..a7f4b19 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -22,6 +22,7 @@ use crate::term; use crate::term::ScreenExt; use crate::foldview::LogView; use crate::coordinates::Coordinates; +use crate::dirty::Dirtyable; #[derive(PartialEq)] pub enum FileBrowserWidgets { @@ -188,6 +189,20 @@ impl Tabbable for TabView<FileBrowser> { self.active_tab_mut_().fs_cache.watch_only(open_dirs).log(); Ok(()) } + + fn on_config_loaded(&mut self) -> HResult<()> { + 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).ok(); + tab.preview_widget_mut().map(|w| w.config_loaded()).ok(); + } + Ok(()) + } } diff --git a/src/files.rs b/src/files.rs index afe684d..b3c13e4 100644 --- a/src/files.rs +++ b/src/files.rs @@ -229,6 +229,19 @@ impl Files { Ok(files) } + pub fn get_file_mut(&mut self, index: usize) -> Option<&mut File> { + let filter = self.filter.clone(); + let show_hidden = self.show_hidden; + + let file = self.files + .iter_mut() + .filter(|f| !(filter.is_some() && + !f.name.contains(filter.as_ref().unwrap()))) + .filter(|f| !(!show_hidden && f.name.starts_with("."))) + .nth(index); + file + } + pub fn get_files(&self) -> Vec<&File> { self.files .iter() @@ -406,8 +419,12 @@ impl Files { self.dirty_meta.set_clean(); let meta_pool = make_pool(sender.clone()); + let show_hidden = self.show_hidden; - for file in self.files.iter_mut().take(meta_files) { + for file in self.files + .iter_mut() + .filter(|f| !(!show_hidden && f.name.starts_with("."))) + .take(meta_files) { if !file.meta_processed { file.take_meta(&meta_pool, &mut self.meta_updated).ok(); } diff --git a/src/listview.rs b/src/listview.rs index 125683f..ddf8c90 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -14,6 +14,7 @@ pub trait Listable { fn render(&self) -> Vec<String>; fn render_header(&self) -> HResult<String> { Ok("".to_string()) } fn render_footer(&self) -> HResult<String> { Ok("".to_string()) } + fn on_new(&mut self) -> HResult<()> { Ok(()) } fn on_refresh(&mut self) -> HResult<()> { Ok(()) } fn on_key(&mut self, _key: Key) -> HResult<()> { Ok(()) } } @@ -27,6 +28,12 @@ impl Listable for ListView<Files> { self.render() } + fn on_new(&mut self) -> HResult<()> { + let show_hidden = self.config().show_hidden(); + self.content.show_hidden = show_hidden; + Ok(()) + } + fn on_refresh(&mut self) -> HResult<()> { let sender = self.core.get_sender(); @@ -97,7 +104,7 @@ where ListView<T>: Listable { pub fn new(core: &WidgetCore, content: T) -> ListView<T> { - let view = ListView::<T> { + let mut view = ListView::<T> { content: content, lines: 0, selection: 0, @@ -107,6 +114,7 @@ where seeking: false, searching: None }; + view.on_new().log(); view } @@ -161,19 +169,18 @@ impl ListView<Files> { pub fn selected_file(&self) -> &File { let selection = self.selection; - let file = &self.content[selection]; + let file = &self.content.get_files()[selection]; file } pub fn selected_file_mut(&mut self) -> &mut File { let selection = self.selection; - let file = &mut self.content.files[selection]; - file + let mut file = self.content.get_file_mut(selection); + file.unwrap() } pub fn clone_selected_file(&self) -> File { - let selection = self.selection; - let file = self.content[selection].clone(); + let file = self.selected_file().clone(); file } @@ -211,9 +218,9 @@ impl ListView<Files> pub fn select_file(&mut self, file: &File) { let pos = self .content - .files + .get_files() .iter() - .position(|item| item == file) + .position(|item| item == &file) .unwrap_or(0); self.set_selection(pos); } @@ -291,10 +298,9 @@ impl ListView<Files> self.refresh().log(); } - fn toggle_hidden(&mut self) { + pub fn toggle_hidden(&mut self) { let file = self.clone_selected_file(); self.content.toggle_hidden(); - //self.content.reload_files(); self.select_file(&file); self.refresh().log(); } diff --git a/src/main.rs b/src/main.rs index 5a22635..4d77667 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,8 +49,7 @@ mod paths; mod foldview; mod dirty; mod fscache; - - +mod config; diff --git a/src/preview.rs b/src/preview.rs index c395e86..a6a99a7 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -10,6 +10,7 @@ use crate::textview::TextView; use crate::widget::{Widget, WidgetCore}; use crate::coordinates::Coordinates; use crate::fail::{HResult, HError, ErrorLog}; +use crate::dirty::Dirtyable; pub type AsyncValueFn<T> = Box<dyn FnBox(Stale) -> HResult<T> + Send + Sync>; @@ -682,6 +683,15 @@ impl Widget for Previewer { Ok(&mut self.core) } + fn config_loaded(&mut self) -> HResult<()> { + let show_hidden = self.config().show_hidden(); + if let PreviewWidget::FileList(filelist) = self.widget.widget_mut()? { + filelist.content.show_hidden = show_hidden; + filelist.content.dirty_meta.set_dirty(); + } + Ok(()) + } + fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> { self.core.coordinates = coordinates.clone(); self.widget.set_coordinates(&coordinates) diff --git a/src/tabview.rs b/src/tabview.rs index 4563332..f3fe9bc 100644 --- a/src/tabview.rs +++ b/src/tabview.rs @@ -26,6 +26,9 @@ pub trait Tabbable { } } fn on_refresh(&mut self) -> HResult<()> { Ok(()) } + fn on_config_loaded(&mut self) -> HResult<()> { Ok(()) } + + } @@ -108,6 +111,10 @@ impl<T> Widget for TabView<T> where T: Widget, TabView<T>: Tabbable { Ok(&mut self.core) } + fn config_loaded(&mut self) -> HResult<()> { + self.on_config_loaded() + } + fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> { self.core.coordinates = coordinates.clone(); for widget in &mut self.widgets { diff --git a/src/widget.rs b/src/widget.rs index fbcb6df..0d9b72a 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, RwLock}; use std::sync::mpsc::{Sender, Receiver, channel}; use std::io::{Write, stdin}; @@ -13,6 +13,8 @@ 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; @@ -24,7 +26,8 @@ pub enum Events { ExclusiveEvent(Option<Mutex<Option<Sender<Events>>>>), InputEnabled(bool), RequestInput, - Status(String) + Status(String), + ConfigLoaded, } impl PartialEq for WidgetCore { @@ -56,7 +59,8 @@ pub struct WidgetCore { event_receiver: Arc<Mutex<Option<Receiver<Events>>>>, pub status_bar_content: Arc<Mutex<Option<String>>>, term_size: (usize, usize), - dirty: DirtyBit + dirty: DirtyBit, + pub config: Arc<RwLock<Async<Config>>> } impl WidgetCore { @@ -70,6 +74,14 @@ 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 confsender = Arc::new(Mutex::new(sender.clone())); + config.on_ready(Box::new(move || { + confsender.lock()?.send(Events::ConfigLoaded).ok(); + Ok(()) + })); + config.run().log(); + let core = WidgetCore { screen: screen, coordinates: coords, @@ -78,7 +90,8 @@ impl WidgetCore { event_receiver: Arc::new(Mutex::new(Some(receiver))), status_bar_content: status_bar_content, term_size: (xsize, ysize), - dirty: DirtyBit::new() }; + dirty: DirtyBit::new(), + config: Arc::new(RwLock::new(config)) }; let minibuffer = MiniBuffer::new(&core); *core.minibuffer.lock().unwrap() = Some(minibuffer); @@ -130,6 +143,7 @@ pub trait Widget { fn refresh(&mut self) -> HResult<()>; fn get_drawlist(&self) -> HResult<String>; fn after_draw(&self) -> HResult<()> { Ok(()) } + fn config_loaded(&mut self) -> HResult<()> { Ok(()) } @@ -277,6 +291,9 @@ pub trait Widget { _ => {} } } + Events::ConfigLoaded => { + self.get_core_mut()?.config.write()?.take_async().log(); + } _ => {} } self.refresh().log(); @@ -291,7 +308,19 @@ pub trait Widget { self.write_to_screen(&clearlist) } + fn config(&self) -> Config { + self.get_core() + .unwrap() + .config.read().unwrap().get() + .map(|config| config.clone()) + .unwrap_or(Config::new()) + } + fn animate_slide_up(&mut self, animator: Option<Stale>) -> HResult<()> { + if !self.config().animate() { return Ok(()); } + + self.config(); + let coords = self.get_coordinates()?.clone(); let xpos = coords.position().x(); let ypos = coords.position().y(); @@ -361,6 +390,10 @@ pub trait Widget { Events::TerminalResized => { self.screen()?.clear().log(); } + Events::ConfigLoaded => { + self.get_core_mut()?.config.write()?.take_async().log(); + self.config_loaded(); + } _ => {} } self.resize().log(); |