configurable hidden files/animation

This commit is contained in:
rabite 2019-04-03 15:35:29 +02:00
parent 8bfc707a59
commit 10d9a5462c
9 changed files with 168 additions and 17 deletions

58
src/config.rs Normal file
View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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(())
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -49,8 +49,7 @@ mod paths;
mod foldview;
mod dirty;
mod fscache;
mod config;

View File

@ -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)

View File

@ -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 {

View File

@ -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();