summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-04-03 15:35:29 +0200
committerrabite <rabite@posteo.de>2019-04-03 15:35:29 +0200
commit10d9a5462cd3c64ce8a1e3e6f724fb1528cc99ce (patch)
treef6acef7291ffcdacc88b2086bb590964041d18eb
parent8bfc707a596c45ce134a427d8c800620042ba78c (diff)
configurable hidden files/animation
-rw-r--r--src/config.rs58
-rw-r--r--src/fail.rs6
-rw-r--r--src/file_browser.rs15
-rw-r--r--src/files.rs19
-rw-r--r--src/listview.rs26
-rw-r--r--src/main.rs3
-rw-r--r--src/preview.rs10
-rw-r--r--src/tabview.rs7
-rw-r--r--src/widget.rs41
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();