diff --git a/src/files.rs b/src/files.rs index 2d83bd9..dd86304 100644 --- a/src/files.rs +++ b/src/files.rs @@ -1,4 +1,7 @@ use std::ops::Index; +use std::error::Error; +use std::path::PathBuf; +use std::ffi::OsStr; pub struct Files(Vec); @@ -10,6 +13,22 @@ impl Index for Files { } impl Files { + pub fn new_from_path + Sized>(path: S) + -> Result> + where S: std::convert::AsRef { + let mut files = Vec::new(); + for file in std::fs::read_dir(path)? { + let file = file?; + let name = file.file_name(); + let name = name.to_string_lossy(); + let path = file.path(); + let size = file.metadata()?.len() / 1024; + files.push(File::new(&name, path, size as usize)); + } + Ok(Files(files)) + } + + pub fn iter(&self) -> std::slice::Iter { self.0.iter() } @@ -22,7 +41,7 @@ impl Files { #[derive(Debug)] pub struct File { pub name: String, - pub path: String, + pub path: PathBuf, pub size: Option, // owner: Option, // group: Option, @@ -33,10 +52,10 @@ pub struct File { impl File { - pub fn new(name: &str, path: &str, size: usize) -> File { + pub fn new(name: &str, path: PathBuf, size: usize) -> File { File { name: name.to_string(), - path: path.to_string(), + path: path, size: Some(size), // owner: None, // group: None, @@ -62,18 +81,13 @@ impl File { }.to_string(); (size, unit) } -} -pub fn get_files(dir: &str) -> Result { - let mut files = Vec::new(); - for file in std::fs::read_dir(dir)? { - let name = file.as_ref().unwrap().file_name().into_string().unwrap(); - file.as_ref().unwrap().path().pop(); - let path = file.as_ref().unwrap().path().into_os_string().into_string().unwrap(); - let size = file.unwrap().metadata()?.len() / 1024; - files.push(File::new(&name, &path, size as usize)); + pub fn grand_parent(&self) -> Option { + Some(self.path.parent()?.parent()?.to_path_buf()) + } + + pub fn path(&self) -> PathBuf { + self.path.clone() } - Ok(Files(files)) } - diff --git a/src/hbox.rs b/src/hbox.rs index 4719544..3cd8f53 100644 --- a/src/hbox.rs +++ b/src/hbox.rs @@ -9,7 +9,6 @@ use crate::widget::Widget; // active: bool // } - pub struct HBox { dimensions: (u16, u16), position: (u16, u16), @@ -39,27 +38,20 @@ impl HBox { let hbox_position = dbg!(self.position); let cell_size = dbg!(hbox_size.0 / self.children.len() as u16); let mut current_pos = dbg!(hbox_position.1); - let mut current_edge = dbg!(cell_size); - - for mut widget in &mut self.children { + + for widget in &mut self.children { widget.set_dimensions(dbg!((cell_size, hbox_size.1))); widget.set_position(dbg!((current_pos, hbox_position.1))); widget.refresh(); dbg!(current_pos += cell_size); - dbg!(current_edge += cell_size); } } - pub fn resize_child(&mut self, index: usize, size: (u16, u16)) { - self.children[index].set_dimensions(size); - } + // pub fn widget(&self, index: usize) -> &Box { + // &self.children[index] + // } - - pub fn widget(&self, index: usize) -> &Box { - &self.children[index] - } - - pub fn active_widget(&self, index: usize) -> &Box { + pub fn active_widget(&self) -> &Box { &self.children[self.active] } @@ -75,7 +67,7 @@ impl Widget for HBox { } fn render_header(&self) -> String { - self.children[self.active].render_header() + self.active_widget().render_header() } fn refresh(&mut self) { diff --git a/src/listview.rs b/src/listview.rs index 8098564..1ec0dfb 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -1,8 +1,10 @@ use unicode_width::{UnicodeWidthStr}; use termion::event::{Key,Event}; +use std::path::{Path, PathBuf}; + use crate::term; -use crate::files::Files; +use crate::files::{File, Files}; use crate::widget::Widget; // Maybe also buffer drawlist for efficiency when it doesn't change every draw @@ -79,8 +81,54 @@ impl ListView where ListView: Widget { } + } +impl ListView where + ListView: Widget, + Files: std::ops::Index, + Files: std::marker::Sized +{ + fn selected_file(&self) -> &File { + let selection = self.selection; + let file = &self.content[selection]; + file + } + + fn grand_parent(&self) -> Option { + self.selected_file().grand_parent() + } + + fn goto_grand_parent(&mut self) { + match self.grand_parent() { + Some(grand_parent) => self.goto_path(&grand_parent), + None => self.show_status("Can't go further!") + } + } + + fn goto_selected(&mut self) { + let path = self.selected_file().path(); + + self.goto_path(&path); + } + + fn goto_path(&mut self, path: &Path) { + match crate::files::Files::new_from_path(path){ + Ok(files) => { + self.content = files; + self.selection = 0; + self.offset = 0; + self.refresh(); + }, + Err(err) => { + self.show_status(&format!("Can't open this path: {}", err)); + return; + } + } + } +} + + impl Widget for ListView { fn get_dimensions(&self) -> (u16, u16) { self.dimensions @@ -147,9 +195,14 @@ impl Widget for ListView { fn on_key(&mut self, key: Key) { match key { - Key::Up => { self.move_up(); self.refresh() }, - Key::Down => { self.move_down(); self.refresh() }, - //Key::Right => self.go(), + Key::Up => { self.move_up(); self.refresh(); }, + Key::Down => { self.move_down(); self.refresh(); }, + Key::Left => { + self.goto_grand_parent() + }, + Key::Right => { + self.goto_selected() + }, _ => { self.bad(Event::Key(key)); } } } diff --git a/src/widget.rs b/src/widget.rs index c9012c9..da98f60 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,5 +1,6 @@ use termion::event::{Key, MouseEvent, Event}; + pub trait Widget { fn render(&self) -> Vec; fn get_dimensions(&self) -> (u16, u16);