diff options
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | src/file_browser.rs | 11 | ||||
-rw-r--r-- | src/files.rs | 101 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/term.rs | 18 | ||||
-rw-r--r-- | src/widget.rs | 14 | ||||
-rw-r--r-- | src/window.rs | 24 |
7 files changed, 144 insertions, 30 deletions
@@ -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"
\ No newline at end of file +dirs-2 = "1.1.0" +users = "0.8" +chrono = "0.4"
\ No newline at end of file diff --git a/src/file_browser.rs b/src/file_browser.rs index aa23b22..1de948d 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -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(); } diff --git a/src/files.rs b/src/files.rs index 0c836ab..0f0f373 100644 --- a/src/files.rs +++ b/src/files.rs @@ -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() + } } diff --git a/src/main.rs b/src/main.rs index 24550d2..c4a0cb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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; diff --git a/src/term.rs b/src/term.rs index bbd8806..950a410 100644 --- a/src/term.rs +++ b/src/term.rs @@ -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)) diff --git a/src/widget.rs b/src/widget.rs index 02103fc..465d625 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -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(); diff --git a/src/window.rs b/src/window.rs index a06c276..6033c71 100644 --- a/src/window.rs +++ b/src/window.rs @@ -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(); |