mirror of
https://github.com/bobwen-dev/hunter
synced 2025-04-12 00:55:41 +02:00
basic browsing working
This commit is contained in:
parent
00c2eb8e46
commit
ab9baf17f1
42
src/files.rs
42
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<File>);
|
||||
|
||||
@ -10,6 +13,22 @@ impl Index<usize> for Files {
|
||||
}
|
||||
|
||||
impl Files {
|
||||
pub fn new_from_path<S: AsRef<OsStr> + Sized>(path: S)
|
||||
-> Result<Files, Box<dyn Error>>
|
||||
where S: std::convert::AsRef<std::path::Path> {
|
||||
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<File> {
|
||||
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<usize>,
|
||||
// owner: Option<String>,
|
||||
// group: Option<String>,
|
||||
@ -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<Files, std::io::Error> {
|
||||
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<PathBuf> {
|
||||
Some(self.path.parent()?.parent()?.to_path_buf())
|
||||
}
|
||||
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.path.clone()
|
||||
}
|
||||
Ok(Files(files))
|
||||
}
|
||||
|
||||
|
||||
|
22
src/hbox.rs
22
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<Widget> {
|
||||
// &self.children[index]
|
||||
// }
|
||||
|
||||
|
||||
pub fn widget(&self, index: usize) -> &Box<Widget> {
|
||||
&self.children[index]
|
||||
}
|
||||
|
||||
pub fn active_widget(&self, index: usize) -> &Box<Widget> {
|
||||
pub fn active_widget(&self) -> &Box<Widget> {
|
||||
&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) {
|
||||
|
@ -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<T: 'static> ListView<T> where ListView<T>: Widget {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl ListView<Files> where
|
||||
ListView<Files>: Widget,
|
||||
Files: std::ops::Index<usize, Output=File>,
|
||||
Files: std::marker::Sized
|
||||
{
|
||||
fn selected_file(&self) -> &File {
|
||||
let selection = self.selection;
|
||||
let file = &self.content[selection];
|
||||
file
|
||||
}
|
||||
|
||||
fn grand_parent(&self) -> Option<PathBuf> {
|
||||
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<Files> {
|
||||
fn get_dimensions(&self) -> (u16, u16) {
|
||||
self.dimensions
|
||||
@ -147,9 +195,14 @@ impl Widget for ListView<Files> {
|
||||
|
||||
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)); }
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use termion::event::{Key, MouseEvent, Event};
|
||||
|
||||
|
||||
pub trait Widget {
|
||||
fn render(&self) -> Vec<String>;
|
||||
fn get_dimensions(&self) -> (u16, u16);
|
||||
|
Loading…
x
Reference in New Issue
Block a user