mirror of https://github.com/bobwen-dev/hunter
preview v3 rc1
This commit is contained in:
parent
6802a76479
commit
ad44f6f2fc
120
src/preview.rs
120
src/preview.rs
|
@ -13,19 +13,24 @@ use crate::widget::Widget;
|
||||||
use crate::fail::HError;
|
use crate::fail::HError;
|
||||||
|
|
||||||
|
|
||||||
|
type HResult<T> = Result<T, HError>;
|
||||||
|
type HClosure<T> = Box<Fn() -> Result<T, HError> + Send>;
|
||||||
|
type WClosure = HClosure<Box<dyn Widget>>;
|
||||||
|
type WidgetO = Box<dyn Widget + Send>;
|
||||||
|
type WidgetFn = Box<Fn() -> Box<dyn Widget + Send>>;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PIDS: Arc<Mutex<Vec<u32>>> = { Arc::new(Mutex::new(vec![])) };
|
static ref SUBPROC: Arc<Mutex<Option<u32>>> = { Arc::new(Mutex::new(None)) };
|
||||||
static ref CURFILE: Arc<Mutex<Option<File>>> = { Arc::new(Mutex::new(None)) };
|
static ref CURFILE: Arc<Mutex<Option<File>>> = { Arc::new(Mutex::new(None)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill_procs() {
|
fn kill_proc() -> HResult<()> {
|
||||||
let mut pids = PIDS.lock().unwrap();
|
let mut pid = SUBPROC.lock()?;
|
||||||
for pid in &*pids {
|
pid.map(|pid|
|
||||||
unsafe { libc::kill(*pid as i32, 9); }
|
unsafe { libc::kill(pid as i32, 15); }
|
||||||
}
|
);
|
||||||
pids.clear();
|
*pid = None;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_current(file: &File) -> bool {
|
fn is_current(file: &File) -> bool {
|
||||||
|
@ -35,6 +40,12 @@ fn is_current(file: &File) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_current(file: &File) -> HResult<()> {
|
||||||
|
let mut curfile = CURFILE.lock()?;
|
||||||
|
*curfile = Some(file.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
enum State<T: Send> {
|
enum State<T: Send> {
|
||||||
Is(T),
|
Is(T),
|
||||||
Becoming,
|
Becoming,
|
||||||
|
@ -49,7 +60,7 @@ struct WillBe<T: Send> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send + 'static> WillBe<T> where {
|
impl<T: Send + 'static> WillBe<T> where {
|
||||||
pub fn new_become(closure: Box<Fn() -> T + Send>)
|
pub fn new_become(closure: HClosure<T>)
|
||||||
-> WillBe<T> {
|
-> WillBe<T> {
|
||||||
let (tx,rx) = std::sync::mpsc::channel();
|
let (tx,rx) = std::sync::mpsc::channel();
|
||||||
let mut willbe = WillBe { state: State::Becoming,
|
let mut willbe = WillBe { state: State::Becoming,
|
||||||
|
@ -59,10 +70,13 @@ impl<T: Send + 'static> WillBe<T> where {
|
||||||
willbe
|
willbe
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&mut self, closure: Box<Fn() -> T + Send>, tx: std::sync::mpsc::Sender<T>) {
|
fn run(&mut self, closure: HClosure<T>, tx: std::sync::mpsc::Sender<T>) {
|
||||||
std::thread::spawn(move|| {
|
std::thread::spawn(move|| {
|
||||||
let thing = closure();
|
let thing = closure();
|
||||||
tx.send(thing).ok();
|
match thing {
|
||||||
|
Ok(thing) => { tx.send(thing).ok(); },
|
||||||
|
Err(err) => { dbg!(err); }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +119,7 @@ struct WillBeWidget<T: Widget + Send> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Widget + Send + 'static> WillBeWidget<T> {
|
impl<T: Widget + Send + 'static> WillBeWidget<T> {
|
||||||
fn new(closure: Box<Fn() -> T + Send>) -> WillBeWidget<T> {
|
fn new(closure: HClosure<T>) -> WillBeWidget<T> {
|
||||||
WillBeWidget {
|
WillBeWidget {
|
||||||
willbe: WillBe::new_become(Box::new(move || closure())),
|
willbe: WillBe::new_become(Box::new(move || closure())),
|
||||||
coordinates: Coordinates::new()
|
coordinates: Coordinates::new()
|
||||||
|
@ -162,7 +176,7 @@ impl<T: Widget + Send> Widget for WillBeWidget<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type WidgetO = Box<dyn Widget + Send>;
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct Previewer {
|
pub struct Previewer {
|
||||||
|
@ -173,75 +187,86 @@ pub struct Previewer {
|
||||||
impl Previewer {
|
impl Previewer {
|
||||||
pub fn new() -> Previewer {
|
pub fn new() -> Previewer {
|
||||||
let willbe = WillBeWidget::new(Box::new(move || {
|
let willbe = WillBeWidget::new(Box::new(move || {
|
||||||
Box::new(crate::textview::TextView {
|
Ok(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 }
|
Previewer { widget: willbe }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn become_preview(&mut self, widget: WillBeWidget<Box<dyn Widget + Send>>) {
|
fn become_preview(&mut self,
|
||||||
|
widget: HResult<WillBeWidget<WidgetO>>) {
|
||||||
let coordinates = self.get_coordinates().clone();
|
let coordinates = self.get_coordinates().clone();
|
||||||
self.widget = widget;
|
self.widget = widget.unwrap();
|
||||||
self.set_coordinates(&coordinates);
|
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 pids = PIDS.clone();
|
|
||||||
//kill_procs();
|
|
||||||
let file = file.clone();
|
let file = file.clone();
|
||||||
|
set_current(&file).unwrap();
|
||||||
|
|
||||||
self.become_preview(WillBeWidget::new(Box::new(move || {
|
self.become_preview(Ok(WillBeWidget::new(Box::new(move || {
|
||||||
//kill_procs();
|
kill_proc().unwrap();
|
||||||
let file = file.clone();
|
let file = file.clone();
|
||||||
|
|
||||||
if file.kind == Kind::Directory {
|
if file.kind == Kind::Directory {
|
||||||
let preview = Previewer::preview_dir(&file, &coordinates);
|
let preview = Previewer::preview_dir(&file, &coordinates);
|
||||||
let mut preview = preview.unwrap();
|
return preview;
|
||||||
preview.set_coordinates(&coordinates);
|
|
||||||
return preview
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.get_mime() == Some("text".to_string()) {
|
if file.get_mime() == Some("text".to_string()) {
|
||||||
return Previewer::preview_text(&file, &coordinates)
|
return Previewer::preview_text(&file, &coordinates)
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut textview = crate::textview::TextView::new_blank();
|
let preview = Previewer::preview_external(&file, &coordinates);
|
||||||
textview.set_coordinates(&coordinates);
|
if preview.is_ok() { return preview; }
|
||||||
return Box::new(textview) as Box<dyn Widget + Send>
|
else {
|
||||||
})));
|
let mut blank = Box::new(TextView::new_blank());
|
||||||
|
blank.set_coordinates(&coordinates);
|
||||||
|
blank.refresh();
|
||||||
|
blank.animate_slide_up();
|
||||||
|
return Ok(blank)
|
||||||
|
}
|
||||||
|
}))));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preview_failed(file: &File) -> HResult<WidgetO> {
|
||||||
|
Err(HError::PreviewFailed { file: file.name.clone() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preview_dir(file: &File, coordinates: &Coordinates)
|
fn preview_dir(file: &File, coordinates: &Coordinates)
|
||||||
-> Result<WidgetO, Error> {
|
-> Result<WidgetO, HError> {
|
||||||
let files = Files::new_from_path(&file.path)?;
|
let files = Files::new_from_path(&file.path)?;
|
||||||
//if !is_current(&file) { return }
|
|
||||||
let len = files.len();
|
let len = files.len();
|
||||||
//if len == 0 { return };
|
|
||||||
|
if len == 0 || !is_current(&file) { return Previewer::preview_failed(&file) }
|
||||||
|
|
||||||
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 Previewer::preview_failed(&file) }
|
||||||
file_list.animate_slide_up();
|
file_list.animate_slide_up();
|
||||||
Ok(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> {
|
fn preview_text(file: &File, coordinates: &Coordinates)
|
||||||
|
-> HResult<WidgetO> {
|
||||||
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 Previewer::preview_failed(&file) }
|
||||||
|
|
||||||
textview.set_coordinates(&coordinates);
|
textview.set_coordinates(&coordinates);
|
||||||
textview.refresh();
|
textview.refresh();
|
||||||
//if !is_current(&file) { return }
|
|
||||||
|
if !is_current(&file) { return Previewer::preview_failed(&file) }
|
||||||
|
|
||||||
textview.animate_slide_up();
|
textview.animate_slide_up();
|
||||||
Box::new(textview)
|
Ok(Box::new(textview))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preview_external(file: &File, coordinates: &Coordinates)
|
fn preview_external(file: &File, coordinates: &Coordinates)
|
||||||
|
@ -259,13 +284,22 @@ impl Previewer {
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
||||||
let pid = process.id();
|
let pid = process.id();
|
||||||
let mut pids = PIDS.lock()?;
|
{
|
||||||
pids.push(pid);
|
let mut pid_ = SUBPROC.lock()?;
|
||||||
|
*pid_ = Some(pid);
|
||||||
|
}
|
||||||
|
|
||||||
//if !is_current(&file) { return }
|
if !is_current(&file) { return Previewer::preview_failed(&file) }
|
||||||
|
|
||||||
let output = process.wait_with_output()?;
|
let output = process.wait_with_output()?;
|
||||||
|
|
||||||
|
if !is_current(&file) { return Previewer::preview_failed(&file) }
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut pid_ = SUBPROC.lock()?;
|
||||||
|
*pid_ = None;
|
||||||
|
}
|
||||||
|
|
||||||
let status = output.status.code()
|
let status = output.status.code()
|
||||||
.ok_or(HError::PreviewFailed{file: file.name.clone()})?;
|
.ok_or(HError::PreviewFailed{file: file.name.clone()})?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue