summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-04-04 00:31:01 +0200
committerrabite <rabite@posteo.de>2019-04-04 00:31:01 +0200
commitd5ccfb0d7403bea77e027a9ca930c81bed5a2314 (patch)
tree897dce30b7909b4267cfe79bc256c3d16545f47a
parent343dd6dedabb1fc5158677fced8588e5b9a00c05 (diff)
show fs space usage and too much other stuff
-rw-r--r--Cargo.toml2
-rw-r--r--src/file_browser.rs88
-rw-r--r--src/files.rs19
-rw-r--r--src/fscache.rs38
-rw-r--r--src/listview.rs25
-rw-r--r--src/main.rs3
-rw-r--r--src/preview.rs4
-rw-r--r--src/stats.rs84
-rw-r--r--src/term.rs44
-rw-r--r--src/widget.rs2
10 files changed, 251 insertions, 58 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0c02c56..278f2ea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,6 +23,8 @@ failure_derive = "0.1.1"
notify = "4.0.9"
parse-ansi = "0.1.6"
signal-notify = "0.1.3"
+systemstat = "0.1.4"
+
#[profile.release]
#debug = true
diff --git a/src/file_browser.rs b/src/file_browser.rs
index a7f4b19..cb5e40f 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -1,7 +1,7 @@
use termion::event::Key;
use std::io::Write;
-use std::sync::{Arc, Mutex};
+use std::sync::{Arc, Mutex, RwLock};
use std::path::PathBuf;
use std::ffi::OsString;
use std::collections::HashSet;
@@ -23,6 +23,7 @@ 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 {
@@ -78,6 +79,7 @@ pub struct FileBrowser {
bookmarks: Arc<Mutex<BMPopup>>,
log_view: Arc<Mutex<LogView>>,
fs_cache: FsCache,
+ fs_stat: Arc<RwLock<FsStat>>
}
impl Tabbable for TabView<FileBrowser> {
@@ -95,6 +97,7 @@ impl Tabbable for TabView<FileBrowser> {
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 = self.widgets.len() - 1;
@@ -187,10 +190,14 @@ impl Tabbable for TabView<FileBrowser> {
});
self.active_tab_mut_().fs_cache.watch_only(open_dirs).log();
+ self.active_tab_mut_().fs_stat.write()?.refresh().log();
Ok(())
}
fn on_config_loaded(&mut self) -> HResult<()> {
+ // hack: wait a bit for widget readyness...
+ std::thread::sleep_ms(100);
+
let show_hidden = self.config().show_hidden();
for tab in self.widgets.iter_mut() {
tab.left_widget_mut().map(|w| {
@@ -198,7 +205,14 @@ impl Tabbable for TabView<FileBrowser> {
w.content.dirty_meta.set_dirty();
w.refresh().log();
}).ok();
- tab.main_widget_mut().map(|w| w.content.show_hidden = show_hidden).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(())
@@ -256,6 +270,8 @@ impl FileBrowser {
list.select_file(&file);
}
+ list.content.meta_all();
+ list.content.dirty_meta.set_dirty();
list.refresh().log();
if startup {
@@ -320,6 +336,7 @@ impl FileBrowser {
let proc_view = ProcView::new(&core);
let bookmarks = BMPopup::new(&core);
let log_view = LogView::new(&core, vec![]);
+ let fs_stat = FsStat::new().unwrap();
@@ -331,6 +348,7 @@ impl FileBrowser {
bookmarks: Arc::new(Mutex::new(bookmarks)),
log_view: Arc::new(Mutex::new(log_view)),
fs_cache: fs_cache,
+ fs_stat: Arc::new(RwLock::new(fs_stat))
})
}
@@ -636,31 +654,6 @@ impl FileBrowser {
HError::no_files()
}
- // pub fn take_preview_files(&mut self) -> HResult<Files> {
- // let widget = self.columns.remove_widget(2);
- // if let Filxx
- // }
-
- // pub fn take_files_from_widget(&self,
- // widget: FileBrowserWidgets) -> HResult<Files> {
- // match widget {
- // FileBrowserWidgets::FileList(file_list) => {
- // match file_list.take_widget() {
- // Ok(widget) => {
- // let files = widget.content;
- // Ok(files)
- // }
- // _ => HError::no_files()
- // }
- // }
- // FileBrowserWidgets::Previewer(previewer) => {
- // let files = previewer.take_files()?;
- // Ok(files)
- // }
- // _ => HError::no_files()
- // }
- // }
-
pub fn get_files(&self) -> HResult<&Files> {
Ok(&self.main_widget()?.content)
}
@@ -676,12 +669,12 @@ impl FileBrowser {
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;
- }
+ // 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(())
}
@@ -929,6 +922,18 @@ impl FileBrowser {
let count_xpos = xsize - file_count.len() as u16;
let count_ypos = ypos + self.get_coordinates()?.ysize();
+ let fs = self.fs_stat.read()?.find_fs(&file.path)?.clone();
+
+ let dev = fs.get_dev();
+ let free_space = fs.get_free();
+ let total_space = fs.get_total();
+ let space = format!("{}: {} / {}",
+ dev,
+ free_space,
+ total_space);
+
+ let space_xpos = count_xpos - space.len() as u16 - 5; // - 3;
+
let status = format!("{} {}:{} {}{} {}{}",
permissions,
user,
@@ -940,10 +945,13 @@ impl FileBrowser {
);
let status = crate::term::sized_string_u(&status, (xsize-1) as usize);
- let status = format!("{}{}{}{}",
+ let status = format!("{}{}{}{}{}{} | {}",
status,
crate::term::header_color(),
- crate::term::goto_xy(count_xpos, count_ypos),
+ crate::term::goto_xy(space_xpos, count_ypos),
+ crate::term::color_orange(),
+ space,
+ crate::term::header_color(),
file_count);
Ok(status)
@@ -972,9 +980,13 @@ impl Widget for FileBrowser {
let file = self.selected_file()?;
let name = &file.name;
- let color = if file.is_dir() || file.color.is_none() {
- crate::term::highlight_color() } else {
- crate::term::from_lscolor(file.color.as_ref().unwrap()) };
+ let color = if file.is_dir() {
+ crate::term::highlight_color() }
+ else if file.color.is_none() {
+ crate::term::normal_color()
+ } else {
+ crate::term::from_lscolor(file.color.as_ref().unwrap())
+ };
let path = self.cwd.short_string();
diff --git a/src/files.rs b/src/files.rs
index b3c13e4..637b99a 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -329,8 +329,21 @@ impl Files {
pub fn replace_file(&mut self,
old: Option<&File>,
new: Option<File>) -> HResult<()> {
+ let (tag, selected) = if let Some(old) = old {
+ if let Some(old) = self.find_file_with_path(&old.path) {
+ (old.tag, old.selected)
+ } else {
+ (None, false)
+ }
+ } else {
+ (None, false)
+ };
old.map(|old| self.files.remove_item(old));
- new.map(|new| self.files.push(new));
+ new.map(|mut new| {
+ new.tag = tag;
+ new.selected = selected;
+ self.files.push(new);
+ });
self.sort();
Ok(())
}
@@ -913,7 +926,7 @@ impl File {
if file_user.name() == cur_user {
crate::term::color_green()
} else {
- crate::term::color_yellow() };
+ crate::term::color_red() };
Some(format!("{}{}", color, file_user.name().to_string_lossy()))
}
@@ -926,7 +939,7 @@ impl File {
if file_group.name() == cur_group {
crate::term::color_green()
} else {
- crate::term::color_yellow() };
+ crate::term::color_red() };
Some(format!("{}{}", color, file_group.name().to_string_lossy()))
}
diff --git a/src/fscache.rs b/src/fscache.rs
index ba0212f..7add081 100644
--- a/src/fscache.rs
+++ b/src/fscache.rs
@@ -115,8 +115,10 @@ impl FsCache {
self.add_watch(&dir).log();
let dir = dir.clone();
let selection = self.get_selection(&dir).ok();
+ let cache = self.clone();
let files = Async::new(Box::new(move |_| {
- let files = Files::new_from_path_cancellable(&dir.path, stale)?;
+ let mut files = Files::new_from_path_cancellable(&dir.path, stale)?;
+ FsCache::apply_settingss(&cache, &mut files).ok();
Ok(files)
}));
Ok((selection, files))
@@ -126,7 +128,9 @@ impl FsCache {
pub fn get_files_sync(&self, dir: &File) -> HResult<Files> {
self.add_watch(&dir).log();
let files = self.get_files(&dir, Stale::new())?.1;
- files.wait()
+ let mut files = files.wait()?;
+ FsCache::apply_settingss(&self, &mut files).ok();
+ Ok(files)
}
pub fn get_selection(&self, dir: &File) -> HResult<File> {
@@ -232,6 +236,36 @@ impl FsCache {
Ok((selection, files))
}
+
+ pub fn apply_settingss(cache: &FsCache,
+ files: &mut Files)
+ -> HResult<()> {
+ let dir = &files.directory;
+ let tab_settings = cache.tab_settings.read()?.get(&dir).cloned();
+ if tab_settings.is_none() { return Ok(()) }
+ let tab_settings = tab_settings?;
+
+ files.sort = tab_settings.dir_settings.sort;
+ files.dirs_first = tab_settings.dir_settings.dirs_first;
+ files.reverse = tab_settings.dir_settings.reverse;
+ files.show_hidden = tab_settings.dir_settings.show_hidden;
+ files.filter = tab_settings.dir_settings.filter.clone();
+
+ if tab_settings.multi_selections.len() > 0 {
+ for file in &mut files.files {
+ for selected_files in &tab_settings.multi_selections {
+ if file.path == selected_files.path {
+ file.selected = true;
+ }
+ }
+ }
+ }
+
+ files.sort();
+ Ok(())
+ }
+
+
fn extract_tab_settings(files: &Files, selection: Option<File>) -> TabSettings {
TabSettings {
selection: selection,
diff --git a/src/listview.rs b/src/listview.rs
index ddf8c90..92fac5f 100644
--- a/src/listview.rs
+++ b/src/listview.rs
@@ -65,6 +65,8 @@ impl Listable for ListView<Files> {
self.move_down();
self.refresh()?;
},
+ Key::Char('<') => self.move_top(),
+ Key::Char('>') => self.move_bottom(),
Key::Char('S') => { self.search_file().log(); }
Key::Alt('s') => { self.search_next().log(); }
Key::Alt('S') => { self.search_prev().log(); }
@@ -72,6 +74,7 @@ impl Listable for ListView<Files> {
Key::Left => self.goto_grand_parent()?,
Key::Right => self.goto_selected()?,
Key::Char(' ') => self.multi_select_file(),
+ Key::Char('v') => self.invert_selection(),
Key::Char('t') => self.toggle_tag()?,
Key::Char('h') => self.toggle_hidden(),
Key::Char('r') => self.reverse_sort(),
@@ -146,6 +149,15 @@ where
self.seeking = false;
}
+ pub fn move_top(&mut self) {
+ self.set_selection(0);
+ }
+
+ pub fn move_bottom(&mut self) {
+ let lines = self.lines;
+ self.set_selection(lines - 1);
+ }
+
pub fn get_selection(&self) -> usize {
self.selection
}
@@ -154,8 +166,7 @@ where
let ysize = self.get_coordinates().unwrap().ysize() as usize;
let mut offset = 0;
- while position + 2
- >= ysize + offset {
+ while position >= ysize + offset {
offset += 1
}
@@ -175,7 +186,7 @@ impl ListView<Files>
pub fn selected_file_mut(&mut self) -> &mut File {
let selection = self.selection;
- let mut file = self.content.get_file_mut(selection);
+ let file = self.content.get_file_mut(selection);
file.unwrap()
}
@@ -325,6 +336,14 @@ impl ListView<Files>
self.move_down();
}
+ pub fn invert_selection(&mut self) {
+ for file in self.content.get_files_mut() {
+ file.toggle_selection();
+ }
+ self.content.set_dirty();
+ self.refresh().log();
+ }
+
fn toggle_tag(&mut self) -> HResult<()> {
self.selected_file_mut().toggle_tag()?;
diff --git a/src/main.rs b/src/main.rs
index 4d77667..1d2451c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -21,6 +21,7 @@ extern crate notify;
extern crate parse_ansi;
extern crate signal_notify;
extern crate tree_magic;
+extern crate systemstat;
use failure::Fail;
@@ -50,7 +51,7 @@ mod foldview;
mod dirty;
mod fscache;
mod config;
-
+mod stats;
diff --git a/src/preview.rs b/src/preview.rs
index a6a99a7..9aecdbc 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -644,7 +644,7 @@ impl Previewer {
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
- let output = dbg!(process.wait_with_output())?;
+ let output = process.wait_with_output()?;
if is_stale(&stale)? { return Previewer::preview_failed(&file) }
{
@@ -652,7 +652,7 @@ impl Previewer {
*pid_ = None;
}
- let status = output.status.code()?;
+ //let status = output.status.code()?;
if !is_stale(&stale)? {
let output = std::str::from_utf8(&output.stdout)
diff --git a/src/stats.rs b/src/stats.rs
new file mode 100644
index 0000000..10c83b0
--- /dev/null
+++ b/src/stats.rs
@@ -0,0 +1,84 @@
+use systemstat::{System, Platform};
+use systemstat::data::Filesystem;
+
+use std::path::{Path, PathBuf, Component};
+use std::collections::HashMap;
+
+use crate::fail::{HResult, ErrorLog};
+
+#[derive(Debug,Clone)]
+pub struct FsStat {
+ pub stats: HashMap<PathBuf, Filesystem>
+}
+
+impl FsStat {
+ pub fn new() -> HResult<FsStat> {
+ let mut stats = FsStat { stats: HashMap::new() };
+ stats.refresh().log();
+
+ Ok(stats)
+ }
+
+ pub fn refresh(&mut self) -> HResult<()> {
+ let sys = System::new();
+ let mounts = sys.mounts()?;
+
+ let stats = mounts.into_iter()
+ .fold(HashMap::new(), |mut stats, mount: Filesystem| {
+ let path = PathBuf::from(&mount.fs_mounted_on);
+ stats.insert(path, mount);
+ stats
+ });
+
+ self.stats = stats;
+
+ Ok(())
+ }
+
+ pub fn find_fs(&self, path: &Path) -> HResult<&Filesystem> {
+ let candidates = self
+ .stats
+ .keys()
+ .filter(|mount_point| path.starts_with(&mount_point))
+ .collect::<Vec<&PathBuf>>();
+
+ let deepest_match = candidates.iter()
+ .fold(PathBuf::new(), |mut deepest, path| {
+ let curren_path_len = deepest.components().count();
+ let candidate_path_len = path.components().count();
+
+ if candidate_path_len > curren_path_len {
+ deepest = path.to_path_buf();
+ }
+ deepest
+ });
+ let fs = self.stats.get(&deepest_match)?;
+ Ok(fs)
+ }
+}
+
+pub trait FsExt {
+ fn get_dev(&self) -> String;
+ fn get_total(&self) -> String;
+ fn get_free(&self) -> String;
+}
+
+impl FsExt for Filesystem {
+ fn get_dev(&self) -> String {
+ let path = PathBuf::from(&self.fs_mounted_from);
+ let dev = path.components().last().unwrap();
+ let dev = match dev {
+ Component::Normal(dev) => dev.to_string_lossy().to_string(),
+ _ => "wtf".to_string()
+ };
+ dev
+ }
+
+ fn get_total(&self) -> String {
+ self.total.to_string(false)
+ }
+
+ fn get_free(&self) -> String {
+ self.free.to_string(false)
+ }
+}
diff --git a/src/term.rs b/src/term.rs
index bc99c36..f9a3347 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -249,16 +249,44 @@ pub fn color_green() -> String {
format!("{}", termion::color::Fg(termion::color::Green))
}
+pub fn color_light_green() -> String {
+ format!("{}", termion::color::Fg(termion::color::LightGreen))
+}
+
+pub fn color_cyan() -> String {
+ format!("{}", termion::color::Fg(termion::color::Cyan))
+}
+
+pub fn color_light_yellow() -> String {
+ format!("{}", termion::color::Fg(termion::color::LightYellow))
+}
+
+pub fn color_orange() -> String {
+ let color = termion::color::Fg(termion::color::AnsiValue::rgb(5 as u8 ,
+ 4 as u8,
+ 0 as u8));
+ format!("{}", color)
+}
+
+
pub fn from_lscolor(color: &lscolors::Color) -> String {
match color {
- lscolors::Color::Black => format!("{}", termion::color::Fg(termion::color::Black)),
- lscolors::Color::Red => format!("{}", termion::color::Fg(termion::color::Red)),
- lscolors::Color::Green => format!("{}", termion::color::Fg(termion::color::Green)),
- lscolors::Color::Yellow => format!("{}", termion::color::Fg(termion::color::Yellow)),
- lscolors::Color::Blue => format!("{}", termion::color::Fg(termion::color::Blue)),
- lscolors::Color::Magenta => format!("{}", termion::color::Fg(termion::color::Magenta)),
- lscolors::Color::Cyan => format!("{}", termion::color::Fg(termion::color::Cyan)),
- lscolors::Color::White => format!("{}", termion::color::Fg(termion::color::White)),
+ lscolors::Color::Black
+ => format!("{}", termion::color::Fg(termion::color::Black)),
+ lscolors::Color::Red
+ => format!("{}", termion::color::Fg(termion::color::Red)),
+ lscolors::Color::Green
+ => format!("{}", termion::color::Fg(termion::color::Green)),
+ lscolors::Color::Yellow
+ => format!("{}", termion::color::Fg(termion::color::Yellow)),
+ lscolors::Color::Blue
+ => format!("{}", termion::color::Fg(termion::color::Blue)),
+ lscolors::Color::Magenta
+ => format!("{}", termion::color::Fg(termion::color::Magenta)),
+ lscolors::Color::Cyan
+ => format!("{}", termion::color::Fg(termion::color::Cyan)),
+ lscolors::Color::White
+ => format!("{}", termion::color::Fg(termion::color::White)),
_ => format!("{}", normal_color()),
}
}
diff --git a/src/widget.rs b/src/widget.rs
index 0d9b72a..8525677 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -392,7 +392,7 @@ pub trait Widget {
}
Events::ConfigLoaded => {
self.get_core_mut()?.config.write()?.take_async().log();
- self.config_loaded();
+ self.config_loaded().log();
}
_ => {}
}