summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-02-12 22:55:16 +0100
committerrabite <rabite@posteo.de>2019-02-12 22:55:16 +0100
commit56d9c3521599baef6ff1472c0c95fa07f17a5a67 (patch)
tree48f16edb6cc49a71bd9d438072f7c2d4848c3ac7 /src
parent1c500d91cf7389850e9f32b14d8ae210a7e62888 (diff)
async widget
Diffstat (limited to 'src')
-rw-r--r--src/coordinates.rs12
-rw-r--r--src/file_browser.rs20
-rw-r--r--src/files.rs2
-rw-r--r--src/hbox.rs16
-rw-r--r--src/listview.rs28
-rw-r--r--src/main.rs8
-rw-r--r--src/miller_columns.rs26
-rw-r--r--src/preview.rs159
-rw-r--r--src/tabview.rs22
-rw-r--r--src/textview.rs14
-rw-r--r--src/widget.rs32
11 files changed, 213 insertions, 126 deletions
diff --git a/src/coordinates.rs b/src/coordinates.rs
index d4dc914..5861f72 100644
--- a/src/coordinates.rs
+++ b/src/coordinates.rs
@@ -40,6 +40,18 @@ impl Coordinates {
&self.position
}
+ pub fn u16position(&self) -> (u16, u16) {
+ self.position.position()
+ }
+
+ pub fn size(&self) -> &Size {
+ &self.size
+ }
+
+ pub fn u16size(&self) -> (u16, u16) {
+ self.size.size()
+ }
+
pub fn top(&self) -> Position {
self.position().clone()
}
diff --git a/src/file_browser.rs b/src/file_browser.rs
index 667e708..a499c5b 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -16,7 +16,7 @@ pub struct FileBrowser {
}
impl Tabbable<FileBrowser> for FileBrowser {
- fn new_tab(&self) -> Self {
+ fn new_tab(&self) -> FileBrowser {
FileBrowser::new().unwrap()
}
@@ -115,8 +115,12 @@ impl FileBrowser {
pub fn update_preview(&mut self) {
if self.columns.get_main_widget().content.len() == 0 { return }
let file = self.columns.get_main_widget().selected_file().clone();
- let preview = &mut self.columns.preview;
+ //let preview = &mut self.columns.preview;
+ let coords = self.columns.preview.get_coordinates();
+ let mut preview = crate::preview::AsyncPreviewer::new();
+ preview.set_coordinates(&coords);
preview.set_file(&file);
+ self.columns.preview = preview;
}
pub fn fix_selection(&mut self) {
@@ -188,18 +192,6 @@ impl FileBrowser {
}
impl Widget for FileBrowser {
- fn get_size(&self) -> &Size {
- &self.columns.get_size()
- }
- fn get_position(&self) -> &Position {
- &self.columns.get_position()
- }
- fn set_size(&mut self, size: Size) {
- self.columns.set_size(size);
- }
- fn set_position(&mut self, position: Position) {
- self.columns.set_position(position);
- }
fn get_coordinates(&self) -> &Coordinates {
&self.columns.coordinates
}
diff --git a/src/files.rs b/src/files.rs
index 4bd0f45..03f0dc6 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -26,7 +26,7 @@ pub struct Files {
impl Index<usize> for Files {
type Output = File;
- fn index(&self, pos: usize) -> &Self::Output {
+ fn index(&self, pos: usize) -> &File {
&self.files[pos]
}
}
diff --git a/src/hbox.rs b/src/hbox.rs
index cdd7023..23c580b 100644
--- a/src/hbox.rs
+++ b/src/hbox.rs
@@ -11,7 +11,7 @@ pub struct HBox<T: Widget> {
}
-impl<T> HBox<T> where T: Widget {
+impl<T> HBox<T> where T: Widget + PartialEq {
pub fn new() -> HBox<T> {
HBox { coordinates: Coordinates::new(),
widgets: vec![],
@@ -78,7 +78,7 @@ impl<T> HBox<T> where T: Widget {
-impl<T> Widget for HBox<T> where T: Widget {
+impl<T> Widget for HBox<T> where T: Widget + PartialEq {
fn render_header(&self) -> String {
self.active_widget().render_header()
}
@@ -96,18 +96,6 @@ impl<T> Widget for HBox<T> where T: Widget {
}).collect()
}
- fn get_size(&self) -> &Size {
- &self.coordinates.size
- }
- fn get_position(&self) -> &Position {
- &self.coordinates.position
- }
- fn set_size(&mut self, size: Size) {
- self.coordinates.size = size;
- }
- fn set_position(&mut self, position: Position) {
- self.coordinates.position = position;
- }
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
diff --git a/src/listview.rs b/src/listview.rs
index 92e5111..cec6630 100644
--- a/src/listview.rs
+++ b/src/listview.rs
@@ -4,11 +4,12 @@ use unicode_width::UnicodeWidthStr;
use std::path::{Path, PathBuf};
use std::io::Write;
+//use std::sync::mpsc::{channel, Sender, Receiver};
use crate::coordinates::{Coordinates, Position, Size};
use crate::files::{File, Files};
use crate::term;
-use crate::widget::Widget;
+use crate::widget::{Widget};
// Maybe also buffer drawlist for efficiency when it doesn't change every draw
@@ -30,7 +31,7 @@ where
ListView<T>: Widget,
T: Send,
{
- pub fn new(content: T) -> Self {
+ pub fn new(content: T) -> ListView<T> {
let view = ListView::<T> {
content: content,
selection: 0,
@@ -81,7 +82,8 @@ where
let ysize = self.coordinates.ysize() as usize;
let mut offset = 0;
- while position + 2 >= ysize + offset {
+ while position + 2
+ >= ysize + offset {
offset += 1
}
@@ -99,7 +101,7 @@ where
} else { (name.clone(), "".to_string()) };
- let xsize = self.get_size().xsize();
+ let xsize = self.get_coordinates().xsize();
let sized_string = term::sized_string(&name, xsize);
let size_pos = xsize - (size.to_string().len() as u16
+ unit.to_string().len() as u16);
@@ -321,8 +323,8 @@ where
.arg("-c")
.arg(&cmd)
.status();
-
- write!(std::io::stdout(), "{}{}",
+ let mut bufout = std::io::BufWriter::new(std::io::stdout());
+ write!(bufout, "{}{}",
termion::style::Reset,
termion::clear::All).unwrap();
@@ -347,18 +349,6 @@ where
}
impl Widget for ListView<Files> {
- fn get_size(&self) -> &Size {
- &self.coordinates.size
- }
- fn get_position(&self) -> &Position {
- &self.coordinates.position
- }
- fn set_size(&mut self, size: Size) {
- self.coordinates.size = size;
- }
- fn set_position(&mut self, position: Position) {
- self.coordinates.position = position;
- }
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
@@ -376,7 +366,7 @@ impl Widget for ListView<Files> {
fn get_drawlist(&self) -> String {
let mut output = term::reset();
- let (_, ysize) = self.get_size().size();
+ let ysize = self.get_coordinates().ysize();
let (xpos, ypos) = self.coordinates.position().position();
output += &self
diff --git a/src/main.rs b/src/main.rs
index 2798311..602fb11 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
#![feature(vec_remove_item)]
+#![feature(trivial_bounds)]
extern crate termion;
extern crate unicode_width;
@@ -18,6 +19,7 @@ use termion::raw::IntoRawMode;
use termion::screen::AlternateScreen;
use std::io::{stdout, Write};
+use std::marker::Send;
mod coordinates;
mod file_browser;
@@ -32,12 +34,16 @@ mod win_main;
mod window;
mod hbox;
mod tabview;
+mod async_widget;
use window::Window;
+use async_widget::AsyncPlug;
+use widget::Widget;
fn main() {
+ let mut bufout = std::io::BufWriter::new(std::io::stdout());
// Need to do this here to actually turn terminal into raw mode...
- let mut _screen = AlternateScreen::from(Box::new(stdout()));
+ let mut _screen = AlternateScreen::from(Box::new(bufout));
let mut _stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
diff --git a/src/miller_columns.rs b/src/miller_columns.rs
index 4114326..66113c6 100644
--- a/src/miller_columns.rs
+++ b/src/miller_columns.rs
@@ -1,7 +1,7 @@
use termion::event::Key;
use crate::coordinates::{Coordinates, Position, Size};
-use crate::preview::Previewer;
+use crate::preview::AsyncPreviewer;
use crate::widget::Widget;
use crate::hbox::HBox;
@@ -10,21 +10,21 @@ pub struct MillerColumns<T> where T: Widget {
pub widgets: HBox<T>,
// pub left: Option<T>,
// pub main: Option<T>,
- pub preview: Previewer,
+ pub preview: AsyncPreviewer,
pub ratio: (u16, u16, u16),
pub coordinates: Coordinates,
}
impl<T> MillerColumns<T>
where
- T: Widget,
+ T: Widget + PartialEq,
{
- pub fn new() -> Self {
- Self {
+ pub fn new() -> MillerColumns<T> {
+ MillerColumns {
widgets: HBox::new(),
coordinates: Coordinates::new(),
ratio: (20, 30, 50),
- preview: Previewer::new(),
+ preview: AsyncPreviewer::new(),
}
}
@@ -91,7 +91,6 @@ where
if len < 2 {
return None;
}
- self.widgets.widgets.get(len - 2)?.get_position();
self.widgets.widgets.get_mut(len - 2)
}
pub fn get_main_widget(&self) -> &T {
@@ -105,19 +104,8 @@ where
impl<T> Widget for MillerColumns<T>
where
T: Widget,
+ T: PartialEq
{
- fn get_size(&self) -> &Size {
- &self.coordinates.size
- }
- fn get_position(&self) -> &Position {
- &self.coordinates.position
- }
- fn set_size(&mut self, size: Size) {
- self.coordinates.size = size;
- }
- fn set_position(&mut self, position: Position) {
- self.coordinates.position = position;
- }
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
diff --git a/src/preview.rs b/src/preview.rs
index d6bf31d..f6bad98 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -7,6 +7,7 @@ use crate::files::{File, Files, Kind};
use crate::listview::ListView;
use crate::textview::TextView;
use crate::widget::Widget;
+use crate::async_widget::AsyncPlug;
lazy_static! {
@@ -23,10 +24,130 @@ fn kill_procs() {
}
fn is_current(file: &File) -> bool {
- CURFILE.lock().unwrap().as_ref().unwrap() == file
+ true
+ //CURFILE.lock().unwrap().as_ref().unwrap() == file
}
+#[derive(PartialEq)]
+pub struct AsyncPreviewer {
+ pub file: Option<File>,
+ pub buffer: String,
+ pub coordinates: Coordinates,
+ pub async_plug: AsyncPlug
+}
+
+impl AsyncPreviewer {
+ pub fn new() -> AsyncPreviewer {
+ let textview = crate::textview::TextView {
+ lines: vec![],
+ buffer: "".to_string(),
+ coordinates: Coordinates::new(),
+ };
+ let textview = Box::new(textview);
+
+ AsyncPreviewer {
+ file: None,
+ buffer: String::new(),
+ coordinates: Coordinates::new(),
+ async_plug: AsyncPlug::new(textview)
+ }
+ }
+ pub fn set_file(&mut self, file: &File) {
+ let coordinates = self.coordinates.clone();
+ let file = file.clone();
+ let redraw = crate::term::reset() + &self.get_redraw_empty_list(0);
+
+ self.async_plug.replace_widget(Box::new(move || {
+ kill_procs();
+ let mut bufout = std::io::BufWriter::new(std::io::stdout());
+ match &file.kind {
+ Kind::Directory => match Files::new_from_path(&file.path) {
+ Ok(files) => {
+ //if !is_current(&file) { return }
+ let len = files.len();
+ //if len == 0 { return };
+ let mut file_list = ListView::new(files);
+ file_list.set_coordinates(&coordinates);
+ file_list.refresh();
+ //if !is_current(&file) { return }
+ file_list.animate_slide_up();
+ return Box::new(file_list) as Box<dyn Widget + Send>;
+
+ }
+ Err(err) => {
+ write!(bufout, "{}", redraw).unwrap();
+ let textview = crate::textview::TextView {
+ lines: vec![],
+ buffer: "".to_string(),
+ coordinates: Coordinates::new(),
+ };
+ return Box::new(textview) as Box<dyn Widget + Send>;
+ },
+ }
+ _ => {
+ if file.get_mime() == Some("text".to_string()) {
+ let mut textview = TextView::new_from_file(&file);
+ //if !is_current(&file) { return }
+ textview.set_coordinates(&coordinates);
+ textview.refresh();
+ //if !is_current(&file) { return }
+ textview.animate_slide_up();
+ return Box::new(textview);
+ } else {
+ 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().unwrap();
+
+ // let pid = process.id();
+ // PIDS.lock().unwrap().push(pid);
+ //if !is_current(&file) { return }
+
+ let output = process.wait_with_output();
+ //if output.is_err() { return }
+ let output = output.unwrap();
+
+ let status = output.status.code();
+ //if status.is_none() { return }
+ let status = status.unwrap();
+
+ 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 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);
+ }
+ }
+ }));
+ }
+}
#[derive(PartialEq)]
pub struct Previewer {
@@ -129,18 +250,32 @@ impl Previewer {
}
impl Widget for Previewer {
- fn get_size(&self) -> &Size {
- &self.coordinates.size
+ fn get_coordinates(&self) -> &Coordinates {
+ &self.coordinates
}
- fn set_size(&mut self, size: Size) {
- self.coordinates.size = size;
+ fn set_coordinates(&mut self, coordinates: &Coordinates) {
+ if self.coordinates == *coordinates {
+ return;
+ }
+ self.coordinates = coordinates.clone();
+ self.refresh();
}
- fn get_position(&self) -> &Position {
- &self.coordinates.position
+ fn render_header(&self) -> String {
+ "".to_string()
}
- fn set_position(&mut self, pos: Position) {
- self.coordinates.position = pos;
+ fn refresh(&mut self) {
+ let file = self.file.clone();
+ if let Some(file) = file {
+ self.set_file(&file);
+ }
+ }
+ fn get_drawlist(&self) -> String {
+ self.buffer.clone()
}
+}
+
+
+impl Widget for AsyncPreviewer {
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
@@ -149,7 +284,8 @@ impl Widget for Previewer {
return;
}
self.coordinates = coordinates.clone();
- self.refresh();
+ self.async_plug.set_coordinates(&coordinates.clone());
+ self.async_plug.refresh();
}
fn render_header(&self) -> String {
"".to_string()
@@ -161,6 +297,7 @@ impl Widget for Previewer {
}
}
fn get_drawlist(&self) -> String {
- self.buffer.clone()
+ self.async_plug.get_drawlist();
+ "".to_string()
}
}
diff --git a/src/tabview.rs b/src/tabview.rs
index 59e5872..39286a0 100644
--- a/src/tabview.rs
+++ b/src/tabview.rs
@@ -10,15 +10,15 @@ pub trait Tabbable<T: Widget> {
#[derive(PartialEq)]
-pub struct TabView<T> where T: Widget {
+pub struct TabView<T> where T: Widget, T: Tabbable<T> {
widgets: Vec<T>,
active: usize,
coordinates: Coordinates
}
-impl<T> TabView<T> where T: Widget + Tabbable<T> {
- pub fn new() -> Self {
- Self {
+impl<T> TabView<T> where T: Widget, T: Tabbable<T> {
+ pub fn new() -> TabView<T> {
+ TabView {
widgets: vec![],
active: 0,
coordinates: Coordinates::new()
@@ -67,7 +67,7 @@ impl<T> TabView<T> where T: Widget + Tabbable<T> {
}
}
-impl<T> Widget for TabView<T> where T: Widget + Tabbable<T> + PartialEq {
+impl<T> Widget for TabView<T> where T: Widget + Tabbable<T> {
fn render_header(&self) -> String {
let xsize = self.get_coordinates().xsize();
let header = self.active_widget().render_header();
@@ -106,18 +106,6 @@ impl<T> Widget for TabView<T> where T: Widget + Tabbable<T> + PartialEq {
self.active_widget().get_drawlist()
}
- fn get_size(&self) -> &Size {
- &self.coordinates.size
- }
- fn get_position(&self) -> &Position {
- &self.coordinates.position
- }
- fn set_size(&mut self, size: Size) {
- self.coordinates.size = size;
- }
- fn set_position(&mut self, position: Position) {
- self.coordinates.position = position;
- }
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
diff --git a/src/textview.rs b/src/textview.rs
index ad76ca8..04e0fbf 100644
--- a/src/textview.rs
+++ b/src/textview.rs
@@ -31,18 +31,6 @@ impl TextView {
}
impl Widget for TextView {
- fn get_size(&self) -> &Size {
- &self.coordinates.size
- }
- fn set_size(&mut self, size: Size) {
- self.coordinates.size = size;
- }
- fn get_position(&self) -> &Position {
- &self.coordinates.position
- }
- fn set_position(&mut self, pos: Position) {
- self.coordinates.position = pos;
- }
fn get_coordinates(&self) -> &Coordinates {
&self.coordinates
}
@@ -54,7 +42,7 @@ impl Widget for TextView {
"".to_string()
}
fn refresh(&mut self) {
- let (xsize, ysize) = self.get_size().size();
+ let (xsize, ysize) = self.get_coordinates().size().size();
let (xpos, ypos) = self.get_coordinates().position().position();
self.buffer = self.get_clearlist() +
diff --git a/src/widget.rs b/src/widget.rs
index 465d625..5cbcec6 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -2,18 +2,17 @@ use termion::event::{Event, Key, MouseEvent};
use crate::coordinates::{Coordinates, Position, Size};
-use std::io::Write;
-
-pub trait Widget: PartialEq {
- //fn render(&self) -> Vec<String>;
- fn get_size(&self) -> &Size;
- fn get_position(&self) -> &Position;
- fn set_size(&mut self, size: Size);
- fn set_position(&mut self, position: Position);
+use std::io::{BufWriter, Write};
+
+
+pub trait Widget {
fn get_coordinates(&self) -> &Coordinates;
fn set_coordinates(&mut self, coordinates: &Coordinates);
fn render_header(&self) -> String;
fn render_footer(&self) -> String { "".into() }
+ fn refresh(&mut self);
+ fn get_drawlist(&self) -> String;
+
fn on_event(&mut self, event: Event) {
match event {
@@ -62,7 +61,7 @@ pub trait Widget: PartialEq {
" ",
crate::term::goto_xy(1, 1),
self.render_header(),
- xsize = self.get_size().xsize() as usize
+ xsize = self.get_coordinates().xsize() as usize
)
}
@@ -80,8 +79,8 @@ pub trait Widget: PartialEq {
}
fn get_clearlist(&self) -> String {
- let (xpos, ypos) = self.get_position().position();
- let (xsize, ysize) = self.get_size().size();
+ let (xpos, ypos) = self.get_coordinates().u16position();
+ let (xsize, ysize) = self.get_coordinates().u16size();
(ypos..ysize + 2)
.map(|line| {
@@ -97,8 +96,8 @@ pub trait Widget: PartialEq {
}
fn get_redraw_empty_list(&self, lines: usize) -> String {
- let (xpos, ypos) = self.get_position().position();
- let (xsize, ysize) = self.get_size().size();
+ let (xpos, ypos) = self.get_coordinates().u16position();
+ let (xsize, ysize) = self.get_coordinates().u16size();
let start_y = lines + ypos as usize;
(start_y..(ysize + 2) as usize)
@@ -121,6 +120,7 @@ pub trait Widget: PartialEq {
let ysize = coords.ysize();
let clear = self.get_clearlist();
let pause = std::time::Duration::from_millis(5);
+ let mut bufout = std::io::BufWriter::new(std::io::stdout());
for i in (0..10).rev() {
let coords = Coordinates { size: Size((xsize,ysize-i)),
@@ -130,13 +130,11 @@ pub trait Widget: PartialEq {
};
self.set_coordinates(&coords);
let buffer = self.get_drawlist();
- write!(std::io::stdout(), "{}{}",
+ write!(bufout, "{}{}",
clear, buffer).unwrap();
+
std::thread::sleep(pause);
}
}
-
- fn refresh(&mut self);
- fn get_drawlist(&self) -> String;
}