show file stats at bottom

This commit is contained in:
rabite 2019-02-06 00:55:10 +01:00
parent 09b50562ec
commit 8c2c1c0bab
7 changed files with 144 additions and 30 deletions

View File

@ -13,4 +13,6 @@ alphanumeric-sort = "1.0.6"
lscolors = { version = "0.5.0", features = [ "ansi_term" ] }
mime-detective = "*"
rayon = "1.0.3"
dirs-2 = "1.1.0"
dirs-2 = "1.1.0"
users = "0.8"
chrono = "0.4"

View File

@ -181,6 +181,17 @@ impl Widget for FileBrowser {
let sized_path = crate::term::sized_string(&pretty_path, xsize);
sized_path
}
fn render_footer(&self) -> String {
let file = self.selected_file();
let permissions = file.pretty_print_permissions();
let user = file.pretty_user().unwrap_or("NOUSER".into());
let group = file.pretty_group().unwrap_or("NOGROUP".into());
let mtime = file.pretty_mtime();
format!("{} {}:{} {}", permissions, user, group, mtime)
}
fn refresh(&mut self) {
self.columns.refresh();
}

View File

@ -1,11 +1,13 @@
use std::cmp::{Ord, Ordering};
use std::error::Error;
use std::ops::Index;
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
use lscolors::LsColors;
use mime_detective;
use users;
use chrono::TimeZone;
lazy_static! {
@ -55,17 +57,20 @@ impl Files {
let files: Vec<_> = direntries?
.iter()
.map(|file| {
//let file = file?;
//let file = file?;
let name = file.file_name();
let name = name.to_string_lossy();
let kind = get_kind(&file);
let path = file.path();
let meta = file.metadata().unwrap();
let mode = meta.mode();
let size = meta.len();
let mtime = meta.modified().unwrap();
let color = get_color(&path, &meta);
File::new(&name, path, kind, size as usize, mtime, color)
let mtime = meta.mtime();
let user = meta.uid();
let group = meta.gid();
let color = get_color(&path, &meta);
File::new(&name, path, kind, size as usize, mtime, color, mode,
user, group)
})
.collect();
@ -165,10 +170,11 @@ pub struct File {
pub path: PathBuf,
pub size: Option<usize>,
pub kind: Kind,
pub mtime: SystemTime,
pub mtime: i64,
pub color: Option<lscolors::Color>,
// owner: Option<String>,
// group: Option<String>,
pub mode: u32,
pub user: u32,
pub group: u32,
// flags: Option<String>,
}
@ -178,8 +184,11 @@ impl File {
path: PathBuf,
kind: Kind,
size: usize,
mtime: SystemTime,
mtime: i64,
color: Option<lscolors::Color>,
mode: u32,
user: u32,
group: u32
) -> File {
File {
name: name.to_string(),
@ -187,7 +196,10 @@ impl File {
size: Some(size),
kind: kind,
mtime: mtime,
color: color
color: color,
mode: mode,
user: user,
group: group
// owner: None,
// group: None,
// flags: None,
@ -202,11 +214,17 @@ impl File {
.unwrap_or("/".to_string());
let kind = Kind::Directory; //get_kind(&path);
let meta = &path.metadata().unwrap();
let meta = &path.metadata()?;
let size = meta.len();
let mtime = meta.modified().unwrap();
let user = meta.uid();
let group = meta.gid();
let color = get_color(&path, meta);
Ok(File::new(&name, pathbuf, kind, size as usize, mtime, color))
let mode = meta.mode();
let mtime = meta.mtime();
Ok(
File::new(&name, pathbuf, kind, size as usize, mtime, color, mode, user
, group)
)
}
pub fn new_placeholder(path: &Path) -> Result<File, Box<Error>> {
@ -266,4 +284,59 @@ impl File {
pub fn path(&self) -> PathBuf {
self.path.clone()
}
pub fn pretty_print_permissions(&self) -> String {
let perms: usize = format!("{:o}", self.mode).parse().unwrap();
let perms: usize = perms % 800;
let perms = format!("{}", perms);
let r = format!("{}r", crate::term::color_green());
let w = format!("{}w", crate::term::color_yellow());
let x = format!("{}x", crate::term::color_red());
let n = format!("{}-", crate::term::highlight_color());
let perms = perms.chars().map(|c| match c.to_string().parse().unwrap() {
1 => format!("{}{}{}", n,n,x),
2 => format!("{}{}{}", n,w,n),
3 => format!("{}{}{}", n,w,x),
4 => format!("{}{}{}", r,n,n),
5 => format!("{}{}{}", r,n,x),
6 => format!("{}{}{}", r,w,n),
7 => format!("{}{}{}", r,w,x),
_ => format!("---")
}).collect();
perms
}
pub fn pretty_user(&self) -> Option<String> {
let uid = self.user;
let file_user = users::get_user_by_uid(uid)?;
let cur_user = users::get_current_username()?;
let color =
if file_user.name() == cur_user {
crate::term::color_green()
} else {
crate::term::color_yellow() };
Some(format!("{}{}", color, file_user.name().to_string_lossy()))
}
pub fn pretty_group(&self) -> Option<String> {
let gid = self.group;
let file_group = users::get_group_by_gid(gid)?;
let cur_group = users::get_current_groupname()?;
let color =
if file_group.name() == cur_group {
crate::term::color_green()
} else {
crate::term::color_yellow() };
Some(format!("{}{}", color, file_group.name().to_string_lossy()))
}
pub fn pretty_mtime(&self) -> String {
//let time = chrono::DateTime::from_timestamp(self.mtime, 0);
let time: chrono::DateTime<chrono::Local>
= chrono::Local.timestamp(self.mtime, 0);
time.format("%F %R").to_string()
}
}

View File

@ -5,6 +5,8 @@ extern crate lazy_static;
extern crate alphanumeric_sort;
extern crate dirs_2;
extern crate lscolors;
extern crate users;
extern crate chrono;
extern crate mime_detective;
extern crate rayon;

View File

@ -55,6 +55,18 @@ pub fn normal_color() -> String {
)
}
pub fn color_red() -> String {
format!("{}", termion::color::Fg(termion::color::Red))
}
pub fn color_yellow() -> String {
format!("{}", termion::color::Fg(termion::color::Yellow))
}
pub fn color_green() -> String {
format!("{}", termion::color::Fg(termion::color::Green))
}
pub fn from_lscolor(color: &lscolors::Color) -> String {
match color {
lscolors::Color::Black => format!("{}", termion::color::Fg(termion::color::Black)),
@ -69,9 +81,9 @@ pub fn from_lscolor(color: &lscolors::Color) -> String {
}
}
pub fn cursor_left(n: u16) -> String {
format!("{}", termion::cursor::Left(n))
}
// pub fn cursor_left(n: u16) -> String {
// format!("{}", termion::cursor::Left(n))
// }
pub fn gotoy(y: u16) -> String {
format!("{}", termion::cursor::Goto(1, y))

View File

@ -13,6 +13,7 @@ pub trait Widget: PartialEq {
fn get_coordinates(&self) -> &Coordinates;
fn set_coordinates(&mut self, coordinates: &Coordinates);
fn render_header(&self) -> String;
fn render_footer(&self) -> String { "".into() }
fn on_event(&mut self, event: Event) {
match event {
@ -65,6 +66,19 @@ pub trait Widget: PartialEq {
)
}
fn get_footer_drawlist(&mut self) -> String {
let xsize = self.get_coordinates().xsize();
let ypos = crate::term::ysize();
format!(
"{}{}{:xsize$}{}{}",
crate::term::goto_xy(1, ypos),
crate::term::header_color(),
" ",
crate::term::goto_xy(1, ypos),
self.render_footer(),
xsize = xsize as usize)
}
fn get_clearlist(&self) -> String {
let (xpos, ypos) = self.get_position().position();
let (xsize, ysize) = self.get_size().size();

View File

@ -50,28 +50,28 @@ where
}
pub fn draw(&mut self) {
let output = self.widget.get_drawlist() + &self.widget.get_header_drawlist();
let output = self.widget.get_drawlist() + &self.widget.get_header_drawlist()
+ &self.widget.get_footer_drawlist();
self.screen.write(output.as_ref()).unwrap();
self.screen.flush().unwrap();
Self::draw_status();
}
pub fn show_status(status: &str) {
show_status(status);
}
// pub fn show_status(status: &str) {
// show_status(status);
// }
pub fn draw_status() {
draw_status();
}
// pub fn draw_status() {
// draw_status();
// }
pub fn clear_status() {
Self::show_status("");
}
// pub fn clear_status() {
// Self::show_status("");
// }
pub fn handle_input(&mut self) {
for event in stdin().events() {
Self::clear_status();
//Self::clear_status();
let event = event.unwrap();
self.widget.on_event(event);
self.draw();