1
0
mirror of https://github.com/bobwen-dev/hunter synced 2025-04-12 00:55:41 +02:00

async v3-beta

This commit is contained in:
rabite 2019-02-16 15:01:46 +01:00
parent f77178938c
commit 6802a76479
7 changed files with 262 additions and 213 deletions

View File

@ -17,6 +17,8 @@ dirs-2 = "1.1.0"
users = "0.8" users = "0.8"
chrono = "0.4" chrono = "0.4"
libc = "*" libc = "*"
failure = "0.1.5"
failure_derive = "0.1.1"
#[profile.release] #[profile.release]
#debug = true #debug = true

View File

@ -69,9 +69,6 @@ impl FileBrowser {
self.columns.push_widget(view); self.columns.push_widget(view);
self.update_preview(); self.update_preview();
}, },
Err(ref err) if err.description() == "placeholder".to_string() =>
self.show_status("No! Can't open this!"),
_ => { _ => {
let status = std::process::Command::new("rifle") let status = std::process::Command::new("rifle")
.args(file.path.file_name()) .args(file.path.file_name())

View File

@ -1,5 +1,4 @@
use std::cmp::{Ord, Ordering}; use std::cmp::{Ord, Ordering};
use std::error::Error;
use std::ops::Index; use std::ops::Index;
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -8,6 +7,9 @@ use lscolors::LsColors;
use mime_detective; use mime_detective;
use users; use users;
use chrono::TimeZone; use chrono::TimeZone;
use failure::Error;
use crate::fail::HError;
lazy_static! { lazy_static! {
@ -53,7 +55,7 @@ fn get_color(path: &Path, meta: &std::fs::Metadata) -> Option<lscolors::Color> {
} }
impl Files { impl Files {
pub fn new_from_path(path: &Path) -> Result<Files, Box<dyn Error>> { pub fn new_from_path(path: &Path) -> Result<Files, Error> {
let direntries: Result<Vec<_>, _> = std::fs::read_dir(&path)?.collect(); let direntries: Result<Vec<_>, _> = std::fs::read_dir(&path)?.collect();
let files: Vec<_> = direntries? let files: Vec<_> = direntries?
@ -244,7 +246,7 @@ impl File {
} }
} }
pub fn new_from_path(path: &Path) -> Result<File, Box<Error>> { pub fn new_from_path(path: &Path) -> Result<File, Error> {
let pathbuf = path.to_path_buf(); let pathbuf = path.to_path_buf();
let name = path let name = path
.file_name() .file_name()
@ -265,7 +267,7 @@ impl File {
) )
} }
pub fn new_placeholder(path: &Path) -> Result<File, Box<Error>> { pub fn new_placeholder(path: &Path) -> Result<File, Error> {
let mut file = File::new_from_path(path)?; let mut file = File::new_from_path(path)?;
file.name = "<empty>".to_string(); file.name = "<empty>".to_string();
file.kind = Kind::Placeholder; file.kind = Kind::Placeholder;
@ -314,16 +316,8 @@ impl File {
self.kind == Kind::Directory self.kind == Kind::Directory
} }
pub fn read_dir(&self) -> Result<Files, Box<Error>> { pub fn read_dir(&self) -> Result<Files, Error> {
match self.kind { Files::new_from_path(&self.path)
Kind::Placeholder => {
let e: Box<Error>
= From::from("placeholder".to_string());
Err(e)
},
_ => Files::new_from_path(&self.path)
}
} }

View File

@ -5,6 +5,10 @@ extern crate termion;
extern crate unicode_width; extern crate unicode_width;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate alphanumeric_sort; extern crate alphanumeric_sort;
extern crate dirs_2; extern crate dirs_2;
extern crate lscolors; extern crate lscolors;
@ -35,6 +39,7 @@ mod window;
mod hbox; mod hbox;
mod tabview; mod tabview;
mod async_widget; mod async_widget;
mod fail;
use window::Window; use window::Window;
///use async_widget::AsyncPlug; ///use async_widget::AsyncPlug;

View File

@ -1,7 +1,7 @@
use termion::event::Key; use termion::event::Key;
use crate::coordinates::{Coordinates, Position, Size}; use crate::coordinates::{Coordinates, Position, Size};
use crate::preview::AsyncPreviewer; use crate::preview::Previewer;
use crate::widget::Widget; use crate::widget::Widget;
use crate::hbox::HBox; use crate::hbox::HBox;
@ -11,7 +11,7 @@ pub struct MillerColumns<T> where T: Widget {
// pub left: Option<T>, // pub left: Option<T>,
// pub main: Option<T>, // pub main: Option<T>,
//pub preview: AsyncPreviewer, //pub preview: AsyncPreviewer,
pub preview: crate::preview::LOLPreviewer, pub preview: Previewer,
pub ratio: (u16, u16, u16), pub ratio: (u16, u16, u16),
pub coordinates: Coordinates, pub coordinates: Coordinates,
} }
@ -25,7 +25,7 @@ where
widgets: HBox::new(), widgets: HBox::new(),
coordinates: Coordinates::new(), coordinates: Coordinates::new(),
ratio: (20, 30, 50), ratio: (20, 30, 50),
preview: crate::preview::LOLPreviewer::new() preview: Previewer::new()
} }
} }

View File

@ -1,3 +1,6 @@
use failure::Error;
use failure::Fail;
use std::io::Write; use std::io::Write;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::Arc; use std::sync::Arc;
@ -7,8 +10,10 @@ use crate::files::{File, Files, Kind};
use crate::listview::ListView; use crate::listview::ListView;
use crate::textview::TextView; use crate::textview::TextView;
use crate::widget::Widget; use crate::widget::Widget;
//use crate::async_widget::AsyncPlug; use crate::fail::HError;
use crate::async_widget::AsyncPlug2;
lazy_static! { lazy_static! {
static ref PIDS: Arc<Mutex<Vec<u32>>> = { Arc::new(Mutex::new(vec![])) }; static ref PIDS: Arc<Mutex<Vec<u32>>> = { Arc::new(Mutex::new(vec![])) };
@ -57,11 +62,11 @@ impl<T: Send + 'static> WillBe<T> where {
fn run(&mut self, closure: Box<Fn() -> T + Send>, tx: std::sync::mpsc::Sender<T>) { fn run(&mut self, closure: Box<Fn() -> T + Send>, tx: std::sync::mpsc::Sender<T>) {
std::thread::spawn(move|| { std::thread::spawn(move|| {
let thing = closure(); let thing = closure();
tx.send(thing).unwrap(); tx.send(thing).ok();
}); });
} }
pub fn check(&mut self) -> Result<(), Box<std::error::Error>> { pub fn check(&mut self) -> Result<(), Error> {
match self.state { match self.state {
State::Is(_) => Ok(()), State::Is(_) => Ok(()),
_ => { _ => {
@ -99,6 +104,15 @@ struct WillBeWidget<T: Widget + Send> {
coordinates: Coordinates coordinates: Coordinates
} }
impl<T: Widget + Send + 'static> WillBeWidget<T> {
fn new(closure: Box<Fn() -> T + Send>) -> WillBeWidget<T> {
WillBeWidget {
willbe: WillBe::new_become(Box::new(move || closure())),
coordinates: Coordinates::new()
}
}
}
// impl<T: Widget + Send> WillBeWidget<T> { // impl<T: Widget + Send> WillBeWidget<T> {
// fn is_widget(&self) -> bool { // fn is_widget(&self) -> bool {
// self.willbe.check().is_ok() // self.willbe.check().is_ok()
@ -148,49 +162,64 @@ impl<T: Widget + Send> Widget for WillBeWidget<T> {
} }
} }
type WidgetO = Box<dyn Widget + Send>;
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct LOLPreviewer { pub struct Previewer {
widget: WillBeWidget<Box<dyn Widget + Send>>, widget: WillBeWidget<Box<dyn Widget + Send>>,
} }
impl LOLPreviewer { impl Previewer {
pub fn new() -> LOLPreviewer { pub fn new() -> Previewer {
let willbe = WillBeWidget::<Box<dyn Widget + Send>> { let willbe = WillBeWidget::new(Box::new(move || {
coordinates: Coordinates::new(),
willbe: WillBe::new_become(Box::new(move || {
Box::new(crate::textview::TextView { Box::new(crate::textview::TextView {
lines: vec![], lines: vec![],
buffer: String::new(), buffer: String::new(),
coordinates: Coordinates::new() coordinates: Coordinates::new()
}) as Box<dyn Widget + Send> }) as Box<dyn Widget + Send>
})) }));
}; Previewer { widget: willbe }
LOLPreviewer { widget: willbe }
} }
fn become_preview(&mut self, widget: WillBeWidget<Box<dyn Widget + Send>>) { fn become_preview(&mut self, widget: WillBeWidget<Box<dyn Widget + Send>>) {
let coordinates = self.get_coordinates().clone();
self.widget = widget; self.widget = widget;
self.set_coordinates(&coordinates);
} }
pub fn set_file(&mut self, file: &File) { pub fn set_file(&mut self, file: &File) {
let coordinates = self.get_coordinates().clone(); let coordinates = self.get_coordinates().clone();
let redraw = crate::term::reset() + &self.get_redraw_empty_list(0);
//let pids = PIDS.clone(); //let pids = PIDS.clone();
//kill_procs(); //kill_procs();
let file = file.clone(); let file = file.clone();
self.become_preview(WillBeWidget::<Box<dyn Widget + Send>> { self.become_preview(WillBeWidget::new(Box::new(move || {
coordinates: coordinates.clone(),
willbe: WillBe::new_become(Box::new(move || {
//kill_procs(); //kill_procs();
let file = file.clone(); let file = file.clone();
let mut bufout = std::io::BufWriter::new(std::io::stdout());
match &file.kind { if file.kind == Kind::Directory {
Kind::Directory => match Files::new_from_path(&file.path) { let preview = Previewer::preview_dir(&file, &coordinates);
Ok(files) => { let mut preview = preview.unwrap();
preview.set_coordinates(&coordinates);
return preview
}
if file.get_mime() == Some("text".to_string()) {
return Previewer::preview_text(&file, &coordinates)
} else {
}
let mut textview = crate::textview::TextView::new_blank();
textview.set_coordinates(&coordinates);
return Box::new(textview) as Box<dyn Widget + Send>
})));
}
fn preview_dir(file: &File, coordinates: &Coordinates)
-> Result<WidgetO, Error> {
let files = Files::new_from_path(&file.path)?;
//if !is_current(&file) { return } //if !is_current(&file) { return }
let len = files.len(); let len = files.len();
//if len == 0 { return }; //if len == 0 { return };
@ -199,28 +228,68 @@ impl LOLPreviewer {
file_list.refresh(); file_list.refresh();
//if !is_current(&file) { return } //if !is_current(&file) { return }
file_list.animate_slide_up(); file_list.animate_slide_up();
return Box::new(file_list) as Box<dyn Widget + Send> Ok(Box::new(file_list) as Box<dyn Widget + Send>)
}
fn preview_text(file: &File, coordinates: &Coordinates) -> Box<dyn Widget + Send> {
let lines = coordinates.ysize() as usize;
let mut textview
= TextView::new_from_file_limit_lines(&file,
lines);
//if !is_current(&file) { return }
textview.set_coordinates(&coordinates);
textview.refresh();
//if !is_current(&file) { return }
textview.animate_slide_up();
Box::new(textview)
} }
Err(err) => {},
fn preview_external(file: &File, coordinates: &Coordinates)
-> Result<Box<dyn Widget + Send>, HError> {
let process =
std::process::Command::new("scope.sh")
.arg(&file.name)
.arg("10".to_string())
.arg("10".to_string())
.arg("".to_string())
.arg("false".to_string())
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::null())
.spawn()?;
let pid = process.id();
let mut pids = PIDS.lock()?;
pids.push(pid);
//if !is_current(&file) { return }
let output = process.wait_with_output()?;
let status = output.status.code()
.ok_or(HError::PreviewFailed{file: file.name.clone()})?;
if status == 0 || status == 5 && is_current(&file) {
let output = std::str::from_utf8(&output.stdout)
.unwrap()
.to_string();
let mut textview = TextView {
lines: output.lines().map(|s| s.to_string()).collect(),
buffer: String::new(),
coordinates: Coordinates::new() };
textview.set_coordinates(&coordinates);
textview.refresh();
textview.animate_slide_up();
return Ok(Box::new(textview))
} }
_ => {} Err(HError::PreviewFailed{file: file.name.clone()})
};
let textview = crate::textview::TextView {
lines: vec![],
buffer: "".to_string(),
coordinates: Coordinates::new(),
};
return Box::new(textview) as Box<dyn Widget + Send>
}))
});
} }
} }
impl Widget for Previewer {
impl Widget for LOLPreviewer {
fn get_coordinates(&self) -> &Coordinates { fn get_coordinates(&self) -> &Coordinates {
&self.widget.coordinates &self.widget.coordinates
} }
@ -264,161 +333,136 @@ impl Widget for LOLPreviewer {
#[derive(PartialEq)] // #[derive(PartialEq)]
pub struct AsyncPreviewer { // pub struct AsyncPreviewer {
pub file: Option<File>, // pub file: Option<File>,
pub buffer: String, // pub buffer: String,
pub coordinates: Coordinates, // pub coordinates: Coordinates,
pub async_plug: AsyncPlug2<Box<dyn Widget + Send + 'static>> // pub async_plug: AsyncPlug2<Box<dyn Widget + Send + 'static>>
} // }
impl AsyncPreviewer { // impl AsyncPreviewer {
pub fn new() -> AsyncPreviewer { // pub fn new() -> AsyncPreviewer {
let closure = Box::new(|| { // let closure = Box::new(|| {
Box::new(crate::textview::TextView { // Box::new(crate::textview::TextView {
lines: vec![], // lines: vec![],
buffer: "".to_string(), // buffer: "".to_string(),
coordinates: Coordinates::new() // coordinates: Coordinates::new()
}) as Box<dyn Widget + Send + 'static> // }) as Box<dyn Widget + Send + 'static>
}); // });
AsyncPreviewer { // AsyncPreviewer {
file: None, // file: None,
buffer: String::new(), // buffer: String::new(),
coordinates: Coordinates::new(), // coordinates: Coordinates::new(),
async_plug: AsyncPlug2::new_from_closure(closure), // async_plug: AsyncPlug2::new_from_closure(closure),
} // }
} // }
pub fn set_file(&mut self, file: &File) { // pub fn set_file(&mut self, file: &File) {
let coordinates = self.coordinates.clone(); // let coordinates = self.coordinates.clone();
let file = file.clone(); // let file = file.clone();
let redraw = crate::term::reset() + &self.get_redraw_empty_list(0); // let redraw = crate::term::reset() + &self.get_redraw_empty_list(0);
//let pids = PIDS.clone(); // //let pids = PIDS.clone();
//kill_procs(); // //kill_procs();
self.async_plug.replace_widget(Box::new(move || { // self.async_plug.replace_widget(Box::new(move || {
kill_procs(); // kill_procs();
let mut bufout = std::io::BufWriter::new(std::io::stdout()); // let mut bufout = std::io::BufWriter::new(std::io::stdout());
match &file.kind { // match &file.kind {
Kind::Directory => match Files::new_from_path(&file.path) { // Kind::Directory => match Files::new_from_path(&file.path) {
Ok(files) => { // Ok(files) => {
//if !is_current(&file) { return } // //if !is_current(&file) { return }
let len = files.len(); // let len = files.len();
//if len == 0 { return }; // //if len == 0 { return };
let mut file_list = ListView::new(files); // let mut file_list = ListView::new(files);
file_list.set_coordinates(&coordinates); // file_list.set_coordinates(&coordinates);
file_list.refresh(); // file_list.refresh();
//if !is_current(&file) { return } // //if !is_current(&file) { return }
file_list.animate_slide_up(); // file_list.animate_slide_up();
return Box::new(file_list) // return Box::new(file_list)
} // }
Err(err) => { // Err(err) => {
write!(bufout, "{}", redraw).unwrap(); // write!(bufout, "{}", redraw).unwrap();
let textview = crate::textview::TextView { // let textview = crate::textview::TextView {
lines: vec![], // lines: vec![],
buffer: "".to_string(), // buffer: "".to_string(),
coordinates: Coordinates::new(), // coordinates: Coordinates::new(),
}; // };
return Box::new(textview) // return Box::new(textview)
}, // },
} // }
_ => { // _ => {
if file.get_mime() == Some("text".to_string()) { // if file.get_mime() == Some("text".to_string()) {
let lines = coordinates.ysize() as usize; // let lines = coordinates.ysize() as usize;
let mut textview // let mut textview
= TextView::new_from_file_limit_lines(&file, // = TextView::new_from_file_limit_lines(&file,
lines); // lines);
//if !is_current(&file) { return } // //if !is_current(&file) { return }
textview.set_coordinates(&coordinates); // textview.set_coordinates(&coordinates);
textview.refresh(); // textview.refresh();
//if !is_current(&file) { return } // //if !is_current(&file) { return }
textview.animate_slide_up(); // textview.animate_slide_up();
return Box::new(textview) // return Box::new(textview)
} else { // } else {
let process = // let process =
std::process::Command::new("scope.sh") // std::process::Command::new("scope.sh")
.arg(&file.name) // .arg(&file.name)
.arg("10".to_string()) // .arg("10".to_string())
.arg("10".to_string()) // .arg("10".to_string())
.arg("".to_string()) // .arg("".to_string())
.arg("false".to_string()) // .arg("false".to_string())
.stdin(std::process::Stdio::null()) // .stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped()) // .stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::null()) // .stderr(std::process::Stdio::null())
.spawn().unwrap(); // .spawn().unwrap();
let pid = process.id(); // let pid = process.id();
PIDS.lock().unwrap().push(pid); // PIDS.lock().unwrap().push(pid);
//if !is_current(&file) { return } // //if !is_current(&file) { return }
let output = process.wait_with_output(); // let output = process.wait_with_output();
match output { // match output {
Ok(output) => { // Ok(output) => {
let status = output.status.code(); // let status = output.status.code();
match status { // match status {
Some(status) => { // Some(status) => {
if status == 0 || status == 5 && is_current(&file) { // if status == 0 || status == 5 && is_current(&file) {
let output = std::str::from_utf8(&output.stdout) // let output = std::str::from_utf8(&output.stdout)
.unwrap() // .unwrap()
.to_string(); // .to_string();
let mut textview = TextView { // let mut textview = TextView {
lines: output.lines().map(|s| s.to_string()).collect(), // lines: output.lines().map(|s| s.to_string()).collect(),
buffer: String::new(), // buffer: String::new(),
coordinates: Coordinates::new() }; // coordinates: Coordinates::new() };
textview.set_coordinates(&coordinates); // textview.set_coordinates(&coordinates);
textview.refresh(); // textview.refresh();
textview.animate_slide_up(); // textview.animate_slide_up();
return Box::new(textview) // return Box::new(textview)
} // }
}, None => {} // }, None => {}
} // }
}, Err(_) => {} // }, Err(_) => {}
} // }
// write!(bufout, "{}", redraw).unwrap();
// //std::io::stdout().flush().unwrap();
// let textview = crate::textview::TextView {
// lines: vec![],
// buffer: "".to_string(),
// coordinates: Coordinates::new(),
// };
// return Box::new(textview)
// }
// }
// }}))
// }
// }
write!(bufout, "{}", redraw).unwrap();
//std::io::stdout().flush().unwrap();
let textview = crate::textview::TextView {
lines: vec![],
buffer: "".to_string(),
coordinates: Coordinates::new(),
};
return Box::new(textview)
}
}
}}))
}
}
impl Widget for AsyncPreviewer {
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
fn set_coordinates(&mut self, coordinates: &Coordinates) {
if self.coordinates == *coordinates {
return;
}
self.coordinates = coordinates.clone();
self.async_plug.set_coordinates(&coordinates.clone());
self.async_plug.refresh();
}
fn render_header(&self) -> String {
"".to_string()
}
fn refresh(&mut self) {
let file = self.file.clone();
if let Some(file) = file {
self.set_file(&file);
}
}
fn get_drawlist(&self) -> String {
self.async_plug.get_drawlist();
"".to_string()
}
}
impl<T> Widget for Box<T> where T: Widget + ?Sized { impl<T> Widget for Box<T> where T: Widget + ?Sized {
fn get_coordinates(&self) -> &Coordinates { fn get_coordinates(&self) -> &Coordinates {

View File

@ -15,6 +15,13 @@ pub struct TextView {
} }
impl TextView { impl TextView {
pub fn new_blank() -> TextView {
TextView {
lines: vec![],
buffer: String::new(),
coordinates: Coordinates::new()
}
}
pub fn new_from_file(file: &File) -> TextView { pub fn new_from_file(file: &File) -> TextView {
let file = std::fs::File::open(&file.path).unwrap(); let file = std::fs::File::open(&file.path).unwrap();
let file = std::io::BufReader::new(file); let file = std::io::BufReader::new(file);