summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fail.rs43
-rw-r--r--src/file_browser.rs6
-rw-r--r--src/files.rs208
-rw-r--r--src/listview.rs12
-rw-r--r--src/main.rs8
-rw-r--r--src/preview.rs103
-rw-r--r--src/tabview.rs2
-rw-r--r--src/textview.rs4
-rw-r--r--src/widget.rs8
9 files changed, 234 insertions, 160 deletions
diff --git a/src/fail.rs b/src/fail.rs
new file mode 100644
index 0000000..791435b
--- /dev/null
+++ b/src/fail.rs
@@ -0,0 +1,43 @@
+use failure;
+
+pub type HResult<T> = Result<T, HError>;
+
+#[derive(Fail, Debug)]
+pub enum HError {
+ #[fail(display = "IO error: {}", error)]
+ IoError{#[cause] error: std::io::Error},
+ #[fail(display = "Mutex failed")]
+ MutexError,
+ #[fail(display = "Channel failed: {}", error)]
+ ChannelTryRecvError{#[cause] error: std::sync::mpsc::TryRecvError},
+ #[fail(display = "Previewer failed on file: {}", file)]
+ PreviewFailed{file: String},
+ #[fail(display = "StalePreviewer for file: {}", file)]
+ StalePreviewError{file: String},
+ #[fail(display = "Failed: {}", error)]
+ Error{#[cause] error: failure::Error }
+}
+
+impl From<std::io::Error> for HError {
+ fn from(error: std::io::Error) -> Self {
+ HError::IoError { error: error }
+ }
+}
+
+impl From<failure::Error> for HError {
+ fn from(error: failure::Error) -> Self {
+ HError::Error { error: error }
+ }
+}
+
+impl From<std::sync::mpsc::TryRecvError> for HError {
+ fn from(error: std::sync::mpsc::TryRecvError) -> Self {
+ HError::ChannelTryRecvError { error: error }
+ }
+}
+
+impl<T> From<std::sync::PoisonError<T>> for HError {
+ fn from(_: std::sync::PoisonError<T>) -> Self {
+ HError::MutexError
+ }
+}
diff --git a/src/file_browser.rs b/src/file_browser.rs
index 01eb316..f5809a5 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -3,7 +3,7 @@ use termion::event::Key;
use std::error::Error;
use std::io::Write;
-use crate::coordinates::{Coordinates, Position, Size};
+use crate::coordinates::{Coordinates};
use crate::files::{File, Files};
use crate::listview::ListView;
use crate::miller_columns::MillerColumns;
@@ -212,10 +212,10 @@ impl Widget for FileBrowser {
let ypos = self.get_coordinates().position().y();
let file = self.selected_file();
- let permissions = file.pretty_print_permissions();
+ let permissions = file.pretty_print_permissions().unwrap_or("NOPERMS".into());
let user = file.pretty_user().unwrap_or("NOUSER".into());
let group = file.pretty_group().unwrap_or("NOGROUP".into());
- let mtime = file.pretty_mtime();
+ let mtime = file.pretty_mtime().unwrap_or("NOMTIME".into());
let selection = self.main_column().get_selection();
diff --git a/src/files.rs b/src/files.rs
index 7d7b3e4..322f99c 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -9,7 +9,9 @@ use users;
use chrono::TimeZone;
use failure::Error;
-use crate::fail::HError;
+use crate::fail::HResult;
+
+use std::sync::{Arc, Mutex};
lazy_static! {
@@ -33,26 +35,9 @@ impl Index<usize> for Files {
}
}
-fn get_kind(file: &std::fs::DirEntry) -> Kind {
- let file = file.file_type().unwrap();
- if file.is_file() {
- return Kind::File;
- }
- if file.is_dir() {
- return Kind::Directory;
- }
- if file.is_symlink() {
- return Kind::Link;
- }
- Kind::Pipe
-}
-fn get_color(path: &Path, meta: &std::fs::Metadata) -> Option<lscolors::Color> {
- match COLORS.style_for_path_with_metadata(path, Some(&meta)) {
- Some(style) => style.clone().foreground,
- None => None,
- }
-}
+
+
impl Files {
pub fn new_from_path(path: &Path) -> Result<Files, Error> {
@@ -61,23 +46,56 @@ impl Files {
let files: Vec<_> = direntries?
.iter()
.map(|file| {
- //let file = file?;
let name = file.file_name();
let name = name.to_string_lossy();
- let kind = get_kind(&file);
let path = file.path();
- let meta = file.metadata().unwrap();
- let mode = meta.mode();
- let size = meta.len();
- let mtime = meta.mtime();
- let user = meta.uid();
- let group = meta.gid();
- let color = get_color(&path, &meta);
- File::new(&name, path, kind, size as usize, mtime, color, mode,
- user, group)
+ File::new(&name, path)
+ })
+ .collect();
+
+ let mut files = Files {
+ directory: File::new_from_path(&path)?,
+ files: files,
+ sort: SortBy::Name,
+ dirs_first: true,
+ reverse: false,
+ show_hidden: true
+ };
+
+ files.sort();
+
+ if files.files.len() == 0 {
+ files.files = vec![File::new_placeholder(&path)?];
+ }
+
+ Ok(files)
+ }
+
+ pub fn new_from_path_cancellable(path: &Path, stale: Arc<Mutex<bool>>) -> Result<Files, Error> {
+ let direntries: Result<Vec<_>, _> = std::fs::read_dir(&path)?.collect();
+
+ let files: Vec<_> = direntries?
+ .iter()
+ .map(|file| {
+ if crate::preview::is_stale(&stale).unwrap() {
+ None
+ } else {
+ let name = file.file_name();
+ let name = name.to_string_lossy();
+ let path = file.path();
+ Some(File::new(&name, path))
+ }
})
+ .fuse()
+ .flatten()
.collect();
+ if crate::preview::is_stale(&stale).unwrap() {
+ return Err(crate::fail::HError::StalePreviewError {
+ file: path.to_string_lossy().to_string()
+ })?;
+ }
+
let mut files = Files {
directory: File::new_from_path(&path)?,
files: files,
@@ -102,19 +120,21 @@ impl Files {
.files
.sort_by(|a, b| alphanumeric_sort::compare_str(&a.name, &b.name)),
SortBy::Size => {
+ self.meta_all();
self.files.sort_by(|a, b| {
- if a.size == b.size {
+ if a.meta().unwrap().size() == b.meta().unwrap().size() {
return alphanumeric_sort::compare_str(&b.name, &a.name);
}
- a.size.cmp(&b.size).reverse()
+ a.meta().unwrap().size().cmp(&b.meta().unwrap().size()).reverse()
});
}
SortBy::MTime => {
+ self.meta_all();
self.files.sort_by(|a, b| {
- if a.mtime == b.mtime {
+ if a.meta().unwrap().mtime() == b.meta().unwrap().mtime() {
return alphanumeric_sort::compare_str(&a.name, &b.name);
}
- a.mtime.cmp(&b.mtime)
+ a.meta().unwrap().mtime().cmp(&b.meta().unwrap().mtime())
});
}
};
@@ -169,6 +189,17 @@ impl Files {
self.files = files;
}
+ pub fn meta_all(&mut self) {
+ let len = self.files.len();
+ self.meta_upto(len);
+ }
+
+ pub fn meta_upto(&mut self, to: usize) {
+ for file in self.files.iter_mut().take(to) {
+ file.get_meta().ok();
+ }
+ }
+
pub fn len(&self) -> usize {
self.files.len()
}
@@ -182,8 +213,6 @@ impl Files {
pub enum Kind {
Directory,
File,
- Link,
- Pipe,
Placeholder
}
@@ -205,17 +234,24 @@ pub enum SortBy {
MTime,
}
-#[derive(Debug, PartialEq, Clone)]
+
+impl PartialEq for File {
+ fn eq(&self, other: &File) -> bool {
+ if self.path == other.path {
+ true
+ } else {
+ false
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
pub struct File {
pub name: String,
pub path: PathBuf,
- pub size: Option<usize>,
pub kind: Kind,
- pub mtime: i64,
pub color: Option<lscolors::Color>,
- pub mode: u32,
- pub user: u32,
- pub group: u32,
+ pub meta: Option<std::fs::Metadata>,
pub selected: bool
// flags: Option<String>,
}
@@ -224,24 +260,13 @@ impl File {
pub fn new(
name: &str,
path: PathBuf,
- kind: Kind,
- size: usize,
- mtime: i64,
- color: Option<lscolors::Color>,
- mode: u32,
- user: u32,
- group: u32
) -> File {
File {
name: name.to_string(),
+ kind: if path.is_dir() { Kind::Directory } else { Kind::File },
path: path,
- size: Some(size),
- kind: kind,
- mtime: mtime,
- color: color,
- mode: mode,
- user: user,
- group: group,
+ meta: None,
+ color: None,
selected: false
}
}
@@ -253,18 +278,7 @@ impl File {
.map(|name| name.to_string_lossy().to_string())
.unwrap_or("/".to_string());
- let kind = Kind::Directory; //get_kind(&path);
- let meta = &path.metadata()?;
- let size = meta.len();
- let user = meta.uid();
- let group = meta.gid();
- let color = get_color(&path, meta);
- let mode = meta.mode();
- let mtime = meta.mtime();
- Ok(
- File::new(&name, pathbuf, kind, size as usize, mtime, color, mode, user
- , group)
- )
+ Ok(File::new(&name, pathbuf))
}
pub fn new_placeholder(path: &Path) -> Result<File, Error> {
@@ -274,17 +288,44 @@ impl File {
Ok(file)
}
- pub fn calculate_size(&self) -> (usize, String) {
+ pub fn meta(&self) -> HResult<std::fs::Metadata> {
+ match &self.meta {
+ Some(meta) => Ok(meta.clone()),
+ None => { Ok(std::fs::metadata(&self.path)?) }
+ }
+ }
+
+ pub fn get_meta(&mut self) -> HResult<()> {
+ if let Some(_) = self.meta { return Ok(()) }
+
+ let meta = std::fs::metadata(&self.path)?;
+ let color = self.get_color(&meta);
+
+ self.meta = Some(meta);
+ self.color = color;
+ Ok(())
+ }
+
+ fn get_color(&self, meta: &std::fs::Metadata) -> Option<lscolors::Color> {
+ match COLORS.style_for_path_with_metadata(&self.path, Some(&meta)) {
+ Some(style) => style.clone().foreground,
+ None => None,
+ }
+ }
+
+ pub fn calculate_size(&self) -> HResult<(u64, String)> {
if self.is_dir() {
let dir_iterator = std::fs::read_dir(&self.path);
match dir_iterator {
- Ok(dir_iterator) => return (dir_iterator.count(), "".to_string()),
- Err(_) => return (0, "".to_string())
+ Ok(dir_iterator) => return Ok((dir_iterator.count() as u64,
+ "".to_string())),
+ Err(_) => return Ok((0, "".to_string()))
}
}
+
let mut unit = 0;
- let mut size = self.size.unwrap();
+ let mut size = self.meta()?.size();
while size > 1024 {
size /= 1024;
unit += 1;
@@ -299,7 +340,7 @@ impl File {
_ => "",
}
.to_string();
- (size, unit)
+ Ok((size, unit))
}
pub fn get_mime(&self) -> Option<String> {
@@ -333,8 +374,8 @@ impl File {
self.selected
}
- pub fn pretty_print_permissions(&self) -> String {
- let perms: usize = format!("{:o}", self.mode).parse().unwrap();
+ pub fn pretty_print_permissions(&self) -> HResult<String> {
+ let perms: usize = format!("{:o}", self.meta()?.mode()).parse().unwrap();
let perms: usize = perms % 800;
let perms = format!("{}", perms);
@@ -354,11 +395,12 @@ impl File {
_ => format!("---")
}).collect();
- perms
+ Ok(perms)
}
pub fn pretty_user(&self) -> Option<String> {
- let uid = self.user;
+ if self.meta().is_err() { return None }
+ let uid = self.meta().unwrap().uid();
let file_user = users::get_user_by_uid(uid)?;
let cur_user = users::get_current_username()?;
let color =
@@ -370,7 +412,8 @@ impl File {
}
pub fn pretty_group(&self) -> Option<String> {
- let gid = self.group;
+ if self.meta().is_err() { return None }
+ let gid = self.meta().unwrap().gid();
let file_group = users::get_group_by_gid(gid)?;
let cur_group = users::get_current_groupname()?;
let color =
@@ -381,10 +424,11 @@ impl File {
Some(format!("{}{}", color, file_group.name().to_string_lossy()))
}
- pub fn pretty_mtime(&self) -> String {
+ pub fn pretty_mtime(&self) -> Option<String> {
+ if self.meta().is_err() { return None }
//let time = chrono::DateTime::from_timestamp(self.mtime, 0);
let time: chrono::DateTime<chrono::Local>
- = chrono::Local.timestamp(self.mtime, 0);
- time.format("%F %R").to_string()
+ = chrono::Local.timestamp(self.meta().unwrap().mtime(), 0);
+ Some(time.format("%F %R").to_string())
}
}
diff --git a/src/listview.rs b/src/listview.rs
index 99adaaf..c1e1d30 100644
--- a/src/listview.rs
+++ b/src/listview.rs
@@ -1,18 +1,14 @@
-use rayon::prelude::*;
use termion::event::{Event, Key};
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};
-// Maybe also buffer drawlist for efficiency when it doesn't change every draw
-
#[derive(PartialEq)]
pub struct ListView<T>
where
@@ -95,7 +91,7 @@ where
fn render_line(&self, file: &File) -> String {
let name = &file.name;
- let (size, unit) = file.calculate_size();
+ let (size, unit) = file.calculate_size().unwrap();
let selection_gap = " ".to_string();
let (name, selection_color) = if file.is_selected() {
@@ -137,10 +133,6 @@ where
}
impl ListView<Files>
-where
- ListView<Files>: Widget,
- Files: std::ops::Index<usize, Output = File>,
- Files: std::marker::Sized,
{
pub fn selected_file(&self) -> &File {
let selection = self.selection;
@@ -366,6 +358,8 @@ impl Widget for ListView<Files> {
self.refresh();
}
fn refresh(&mut self) {
+ let visible_file_num = self.selection + self.get_coordinates().ysize() as usize;
+ self.content.meta_upto(visible_file_num);
self.lines = self.content.len();
self.buffer = self.render();
}
diff --git a/src/main.rs b/src/main.rs
index 7de9a46..0add6c9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,7 +5,6 @@ extern crate termion;
extern crate unicode_width;
#[macro_use]
extern crate lazy_static;
-#[macro_use]
extern crate failure;
#[macro_use]
extern crate failure_derive;
@@ -23,7 +22,6 @@ use termion::raw::IntoRawMode;
use termion::screen::AlternateScreen;
use std::io::{stdout, Write};
-use std::marker::Send;
mod coordinates;
mod file_browser;
@@ -42,16 +40,14 @@ mod async_widget;
mod fail;
use window::Window;
-///use async_widget::AsyncPlug;
-use widget::Widget;
+
fn main() {
- let mut bufout = std::io::BufWriter::new(std::io::stdout());
+ let 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(bufout));
let mut _stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
-
let filebrowser = crate::file_browser::FileBrowser::new().unwrap();
let mut tabview = crate::tabview::TabView::new();
diff --git a/src/preview.rs b/src/preview.rs
index 2d3f82c..dd78c78 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -1,7 +1,5 @@
use failure::Error;
-use failure::Fail;
-use std::io::Write;
use std::sync::Mutex;
use std::sync::Arc;
@@ -14,14 +12,11 @@ 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 HClosure<T> = Box<Fn(Arc<Mutex<bool>>) -> Result<T, HError> + Send>;
type WidgetO = Box<dyn Widget + Send>;
-type WidgetFn = Box<Fn() -> Box<dyn Widget + Send>>;
lazy_static! {
static ref SUBPROC: Arc<Mutex<Option<u32>>> = { Arc::new(Mutex::new(None)) };
- static ref CURFILE: Arc<Mutex<Option<File>>> = { Arc::new(Mutex::new(None)) };
}
fn kill_proc() -> HResult<()> {
@@ -33,17 +28,8 @@ fn kill_proc() -> HResult<()> {
Ok(())
}
-fn is_current(file: &File) -> bool {
- match CURFILE.lock().unwrap().as_ref() {
- Some(curfile) => curfile == file,
- None => true
- }
-}
-
-fn set_current(file: &File) -> HResult<()> {
- let mut curfile = CURFILE.lock()?;
- *curfile = Some(file.clone());
- Ok(())
+pub fn is_stale(stale: &Arc<Mutex<bool>>) -> HResult<bool> {
+ Ok(*(stale.lock()?))
}
enum State<T: Send> {
@@ -56,7 +42,7 @@ enum State<T: Send> {
struct WillBe<T: Send> {
pub state: State<T>,
rx: std::sync::mpsc::Receiver<T>,
- cancel: bool
+ stale: Arc<Mutex<bool>>
}
impl<T: Send + 'static> WillBe<T> where {
@@ -65,14 +51,15 @@ impl<T: Send + 'static> WillBe<T> where {
let (tx,rx) = std::sync::mpsc::channel();
let mut willbe = WillBe { state: State::Becoming,
rx: rx,
- cancel: false };
+ stale: Arc::new(Mutex::new(false)) };
willbe.run(closure, tx);
willbe
}
fn run(&mut self, closure: HClosure<T>, tx: std::sync::mpsc::Sender<T>) {
+ let stale = self.stale.clone();
std::thread::spawn(move|| {
- let thing = closure();
+ let thing = closure(stale);
match thing {
Ok(thing) => { tx.send(thing).ok(); },
Err(err) => { dbg!(err); }
@@ -80,6 +67,11 @@ impl<T: Send + 'static> WillBe<T> where {
});
}
+ pub fn set_stale(&mut self) -> HResult<()> {
+ *self.stale.lock()? = true;
+ Ok(())
+ }
+
pub fn check(&mut self) -> Result<(), Error> {
match self.state {
State::Is(_) => Ok(()),
@@ -91,16 +83,9 @@ impl<T: Send + 'static> WillBe<T> where {
}
}
- pub fn wait(mut self) -> Result<T, std::sync::mpsc::RecvError> {
+ pub fn wait(self) -> Result<T, std::sync::mpsc::RecvError> {
self.rx.recv()
}
-
- pub fn take(mut self) -> Option<T> {
- match self.state {
- State::Is(thing) => Some(thing),
- _ => None
- }
- }
}
impl<W: Widget + Send> PartialEq for WillBeWidget<W> {
@@ -121,10 +106,13 @@ struct WillBeWidget<T: Widget + Send> {
impl<T: Widget + Send + 'static> WillBeWidget<T> {
fn new(closure: HClosure<T>) -> WillBeWidget<T> {
WillBeWidget {
- willbe: WillBe::new_become(Box::new(move || closure())),
+ willbe: WillBe::new_become(Box::new(move |stale| closure(stale))),
coordinates: Coordinates::new()
}
}
+ pub fn set_stale(&mut self) -> HResult<()> {
+ self.willbe.set_stale()
+ }
}
// impl<T: Widget + Send> WillBeWidget<T> {
@@ -177,8 +165,16 @@ impl<T: Widget + Send> Widget for WillBeWidget<T> {
}
+impl PartialEq for Previewer {
+ fn eq(&self, other: &Previewer) -> bool {
+ if self.widget.coordinates == other.widget.coordinates {
+ true
+ } else {
+ false
+ }
+ }
+}
-#[derive(PartialEq)]
pub struct Previewer {
widget: WillBeWidget<Box<dyn Widget + Send>>,
}
@@ -186,12 +182,9 @@ pub struct Previewer {
impl Previewer {
pub fn new() -> Previewer {
- let willbe = WillBeWidget::new(Box::new(move || {
- Ok(Box::new(crate::textview::TextView {
- lines: vec![],
- buffer: String::new(),
- coordinates: Coordinates::new()
- }) as Box<dyn Widget + Send>)
+ let willbe = WillBeWidget::new(Box::new(move |_| {
+ Ok(Box::new(crate::textview::TextView::new_blank())
+ as Box<dyn Widget + Send>)
}));
Previewer { widget: willbe }
}
@@ -206,22 +199,26 @@ impl Previewer {
pub fn set_file(&mut self, file: &File) {
let coordinates = self.get_coordinates().clone();
let file = file.clone();
- set_current(&file).unwrap();
- self.become_preview(Ok(WillBeWidget::new(Box::new(move || {
+ self.widget.set_stale().ok();
+
+ self.become_preview(Ok(WillBeWidget::new(Box::new(move |stale| {
kill_proc().unwrap();
+
let file = file.clone();
if file.kind == Kind::Directory {
- let preview = Previewer::preview_dir(&file, &coordinates);
+ let preview = Previewer::preview_dir(&file, &coordinates, stale.clone());
return preview;
}
if file.get_mime() == Some("text".to_string()) {
- return Previewer::preview_text(&file, &coordinates)
+ return Previewer::preview_text(&file, &coordinates, stale.clone())
}
- let preview = Previewer::preview_external(&file, &coordinates);
+ let preview = Previewer::preview_external(&file,
+ &coordinates,
+ stale.clone());
if preview.is_ok() { return preview; }
else {
let mut blank = Box::new(TextView::new_blank());
@@ -237,39 +234,40 @@ impl Previewer {
Err(HError::PreviewFailed { file: file.name.clone() })
}
- fn preview_dir(file: &File, coordinates: &Coordinates)
+ fn preview_dir(file: &File, coordinates: &Coordinates, stale: Arc<Mutex<bool>>)
-> Result<WidgetO, HError> {
- let files = Files::new_from_path(&file.path)?;
+ let files = Files::new_from_path_cancellable(&file.path,
+ stale.clone())?;
let len = files.len();
- if len == 0 || !is_current(&file) { return Previewer::preview_failed(&file) }
+ if len == 0 || is_stale(&stale)? { return Previewer::preview_failed(&file) }
let mut file_list = ListView::new(files);
file_list.set_coordinates(&coordinates);
file_list.refresh();
- if !is_current(&file) { return Previewer::preview_failed(&file) }
+ if is_stale(&stale)? { return Previewer::preview_failed(&file) }
file_list.animate_slide_up();
Ok(Box::new(file_list) as Box<dyn Widget + Send>)
}
- fn preview_text(file: &File, coordinates: &Coordinates)
+ fn preview_text(file: &File, coordinates: &Coordinates, stale: Arc<Mutex<bool>>)
-> HResult<WidgetO> {
let lines = coordinates.ysize() as usize;
let mut textview
= TextView::new_from_file_limit_lines(&file,
lines);
- if !is_current(&file) { return Previewer::preview_failed(&file) }
+ if is_stale(&stale)? { return Previewer::preview_failed(&file) }
textview.set_coordinates(&coordinates);
textview.refresh();
- if !is_current(&file) { return Previewer::preview_failed(&file) }
+ if is_stale(&stale)? { return Previewer::preview_failed(&file) }
textview.animate_slide_up();
Ok(Box::new(textview))
}
- fn preview_external(file: &File, coordinates: &Coordinates)
+ fn preview_external(file: &File, coordinates: &Coordinates, stale: Arc<Mutex<bool>>)
-> Result<Box<dyn Widget + Send>, HError> {
let process =
std::process::Command::new("scope.sh")
@@ -289,12 +287,11 @@ impl Previewer {
*pid_ = Some(pid);
}
- if !is_current(&file) { return Previewer::preview_failed(&file) }
+ if is_stale(&stale)? { return Previewer::preview_failed(&file) }
let output = process.wait_with_output()?;
- if !is_current(&file) { return Previewer::preview_failed(&file) }
-
+ if is_stale(&stale)? { return Previewer::preview_failed(&file) }
{
let mut pid_ = SUBPROC.lock()?;
*pid_ = None;
@@ -303,7 +300,7 @@ impl Previewer {
let status = output.status.code()
.ok_or(HError::PreviewFailed{file: file.name.clone()})?;
- if status == 0 || status == 5 && is_current(&file) {
+ if status == 0 || status == 5 && !is_stale(&stale)? { //is_current(&file) {
let output = std::str::from_utf8(&output.stdout)
.unwrap()
.to_string();
diff --git a/src/tabview.rs b/src/tabview.rs
index 39286a0..65cfaef 100644
--- a/src/tabview.rs
+++ b/src/tabview.rs
@@ -1,6 +1,6 @@
use termion::event::Key;
-use crate::coordinates::{Coordinates, Position, Size};
+use crate::coordinates::{Coordinates};
use crate::widget::Widget;
pub trait Tabbable<T: Widget> {
diff --git a/src/textview.rs b/src/textview.rs
index 304d664..a7a28c6 100644
--- a/src/textview.rs
+++ b/src/textview.rs
@@ -1,8 +1,6 @@
-use ::rayon::prelude::*;
-
use std::io::BufRead;
-use crate::coordinates::{Coordinates, Position, Size};
+use crate::coordinates::{Coordinates};
use crate::files::File;
use crate::term::sized_string;
use crate::widget::Widget;
diff --git a/src/widget.rs b/src/widget.rs
index dec2fa7..ccf8f72 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -6,6 +6,9 @@ use std::io::{BufWriter, Write};
pub trait Widget {
+ fn get_widget(&self) -> Box<dyn Widget> {
+ Box::new(crate::textview::TextView::new_blank())
+ }
fn get_coordinates(&self) -> &Coordinates;
fn set_coordinates(&mut self, coordinates: &Coordinates);
fn render_header(&self) -> String;
@@ -120,7 +123,7 @@ pub trait Widget {
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());
+ let mut bufout = BufWriter::new(std::io::stdout());
for i in (0..10).rev() {
let coords = Coordinates { size: Size((xsize,ysize-i)),
@@ -132,8 +135,7 @@ pub trait Widget {
let buffer = self.get_drawlist();
write!(bufout, "{}{}",
clear, buffer).unwrap();
- bufout.flush();
-
+ bufout.flush().ok();
std::thread::sleep(pause);
}