mirror of https://github.com/bobwen-dev/hunter
some bugfixes and stuff
This commit is contained in:
parent
153bf24238
commit
90e626d169
|
@ -13,6 +13,7 @@ use crate::files::{File, Files, PathBufExt};
|
|||
use crate::listview::ListView;
|
||||
use crate::hbox::HBox;
|
||||
use crate::widget::Widget;
|
||||
use crate::dirty::Dirtyable;
|
||||
use crate::tabview::{TabView, Tabbable};
|
||||
use crate::preview::{Previewer, AsyncWidget};
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
|
@ -248,6 +249,18 @@ impl FileBrowser {
|
|||
let file = self.selected_file()?;
|
||||
|
||||
if file.is_dir() {
|
||||
match file.is_readable() {
|
||||
Ok(true) => {},
|
||||
Ok(false) => {
|
||||
let status =
|
||||
format!("{}Stop right there, cowboy! Check your permisions!",
|
||||
term::color_red());
|
||||
self.show_status(&status).log();
|
||||
return Ok(());
|
||||
}
|
||||
err @ Err(_) => err.log()
|
||||
}
|
||||
|
||||
self.main_widget_goto(&file).log();
|
||||
} else {
|
||||
self.core.get_sender().send(Events::InputEnabled(false))?;
|
||||
|
@ -293,22 +306,13 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
|
||||
match dir.is_readable() {
|
||||
Ok(true) => {},
|
||||
Ok(false) => {
|
||||
let status =
|
||||
format!("{}Stop right there, cowboy! Check your permisions!",
|
||||
term::color_red());
|
||||
self.show_status(&status).log();
|
||||
return Ok(());
|
||||
}
|
||||
err @ Err(_) => err.log()
|
||||
}
|
||||
|
||||
|
||||
let dir = dir.clone();
|
||||
let selected_file = self.get_selection(&dir).ok().cloned();
|
||||
|
||||
self.get_files().and_then(|files| self.cache_files(files)).log();
|
||||
self.get_left_files().and_then(|files| self.cache_files(files)).log();
|
||||
let cached_files = self.get_cached_files(&dir).ok();
|
||||
|
||||
self.prev_cwd = Some(self.cwd.clone());
|
||||
|
@ -320,11 +324,12 @@ impl FileBrowser {
|
|||
let cached_files = cached_files.clone();
|
||||
|
||||
let files = cached_files.or_else(|| {
|
||||
Files::new_from_path_cancellable(&path, stale).ok()
|
||||
Files::new_from_path_cancellable(&path, stale.clone()).ok()
|
||||
})?;
|
||||
|
||||
let mut list = ListView::new(&core, files);
|
||||
list.content.meta_all();
|
||||
|
||||
list.content.meta_set_fresh().log();
|
||||
|
||||
if let Some(file) = &selected_file {
|
||||
list.select_file(file);
|
||||
|
@ -335,6 +340,8 @@ impl FileBrowser {
|
|||
if let Ok(grand_parent) = self.cwd()?.parent_as_file() {
|
||||
self.left_widget_goto(&grand_parent).log();
|
||||
} else {
|
||||
self.left_async_widget_mut()?.clear().log();
|
||||
self.screen()?.flush();
|
||||
self.left_async_widget_mut()?.set_stale().log();
|
||||
}
|
||||
|
||||
|
@ -342,7 +349,6 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn left_widget_goto(&mut self, dir: &File) -> HResult<()> {
|
||||
self.get_left_files().and_then(|files| self.cache_files(files)).log();
|
||||
let cached_files = self.get_cached_files(&dir).ok();
|
||||
let dir = dir.clone();
|
||||
|
||||
|
|
102
src/files.rs
102
src/files.rs
|
@ -3,7 +3,7 @@ use std::ops::Index;
|
|||
use std::fs::Metadata;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::os::unix::ffi::{OsStringExt, OsStrExt};
|
||||
|
@ -23,13 +23,13 @@ use rayon::{ThreadPool, ThreadPoolBuilder};
|
|||
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
use crate::dirty::{AsyncDirtyBit, DirtyBit, Dirtyable};
|
||||
use crate::preview::Async;
|
||||
use crate::preview::{Async, Stale};
|
||||
use crate::widget::Events;
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref COLORS: LsColors = LsColors::from_env().unwrap();
|
||||
static ref TAGS: Mutex<(bool, Vec<PathBuf>)> = Mutex::new((false, vec![]));
|
||||
static ref TAGS: RwLock<(bool, Vec<PathBuf>)> = RwLock::new((false, vec![]));
|
||||
}
|
||||
|
||||
fn make_pool(sender: Option<Sender<Events>>) -> ThreadPool {
|
||||
|
@ -54,7 +54,7 @@ pub fn load_tags() -> HResult<()> {
|
|||
let tag_path = crate::paths::tagfile_path()?;
|
||||
let tags = std::fs::read_to_string(tag_path)?;
|
||||
let mut tags = tags.lines().map(|f| PathBuf::from(f)).collect::<Vec<PathBuf>>();
|
||||
let mut tag_lock = TAGS.lock()?;
|
||||
let mut tag_lock = TAGS.write()?;
|
||||
tag_lock.0 = true;
|
||||
tag_lock.1.append(&mut tags);
|
||||
Ok(())
|
||||
|
@ -64,12 +64,12 @@ pub fn load_tags() -> HResult<()> {
|
|||
|
||||
pub fn check_tag(path: &PathBuf) -> HResult<bool> {
|
||||
tags_loaded()?;
|
||||
let tagged = TAGS.lock()?.1.contains(path);
|
||||
let tagged = TAGS.read()?.1.contains(path);
|
||||
Ok(tagged)
|
||||
}
|
||||
|
||||
pub fn tags_loaded() -> HResult<()> {
|
||||
let loaded = TAGS.lock()?.0;
|
||||
let loaded = TAGS.read()?.0;
|
||||
if loaded { Ok(()) }
|
||||
else { HError::tags_not_loaded() }
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ impl Files {
|
|||
}
|
||||
|
||||
pub fn new_from_path_cancellable(path: &Path,
|
||||
stale: Arc<Mutex<bool>>)
|
||||
stale: Stale)
|
||||
-> Result<Files, Error> {
|
||||
let direntries: Result<Vec<_>, _> = std::fs::read_dir(&path)?.collect();
|
||||
let dirty = DirtyBit::new();
|
||||
|
@ -170,9 +170,10 @@ impl Files {
|
|||
let name = file.file_name();
|
||||
let name = name.to_string_lossy();
|
||||
let path = file.path();
|
||||
Some(File::new(&name,
|
||||
path,
|
||||
Some(dirty_meta.clone())))
|
||||
Some(File::new_with_stale(&name,
|
||||
path,
|
||||
Some(dirty_meta.clone()),
|
||||
stale.clone()))
|
||||
}
|
||||
})
|
||||
.fuse()
|
||||
|
@ -392,6 +393,11 @@ impl Files {
|
|||
self.meta_upto = Some(meta_files);
|
||||
}
|
||||
|
||||
pub fn meta_set_fresh(&self) -> HResult<()> {
|
||||
self.files.get(0)?.meta.set_fresh()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn set_filter(&mut self, filter: Option<String>) {
|
||||
self.filter = filter;
|
||||
|
@ -480,9 +486,38 @@ impl File {
|
|||
path: PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>) -> File {
|
||||
let tag = check_tag(&path).ok();
|
||||
let meta = File::make_async_meta(&path, dirty_meta.clone());
|
||||
let meta = File::make_async_meta(&path, dirty_meta.clone(), None);
|
||||
let dirsize = if path.is_dir() {
|
||||
Some(File::make_async_dirsize(&path, dirty_meta.clone()))
|
||||
Some(File::make_async_dirsize(&path, dirty_meta.clone(), None))
|
||||
} else { None };
|
||||
|
||||
File {
|
||||
name: name.to_string(),
|
||||
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
||||
path: path,
|
||||
dirsize: dirsize,
|
||||
target: None,
|
||||
meta: meta,
|
||||
meta_processed: false,
|
||||
dirty_meta: dirty_meta,
|
||||
color: None,
|
||||
selected: false,
|
||||
tag: tag,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_stale(name: &str,
|
||||
path: PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale: Stale) -> File {
|
||||
let tag = check_tag(&path).ok();
|
||||
let meta = File::make_async_meta(&path,
|
||||
dirty_meta.clone(),
|
||||
Some(stale.clone()));
|
||||
let dirsize = if path.is_dir() {
|
||||
Some(File::make_async_dirsize(&path,
|
||||
dirty_meta.clone(),
|
||||
Some(stale)))
|
||||
} else { None };
|
||||
|
||||
File {
|
||||
|
@ -519,13 +554,19 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn make_async_meta(path: &PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>) -> Async<Metadata> {
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale_preview: Option<Stale>) -> Async<Metadata> {
|
||||
let path = path.clone();
|
||||
|
||||
let mut meta = Async::new(Box::new(move |stale| {
|
||||
if *stale.lock()? { HError::stale()? }
|
||||
Ok(std::fs::symlink_metadata(&path).unwrap())
|
||||
}));
|
||||
let meta_closure = Box::new(move |stale: Stale| {
|
||||
if stale.is_stale()? { HError::stale()? }
|
||||
Ok(std::fs::symlink_metadata(&path)?)
|
||||
});
|
||||
|
||||
let mut meta = match stale_preview {
|
||||
Some(stale) => Async::new_with_stale(meta_closure, stale),
|
||||
None => Async::new(meta_closure)
|
||||
};
|
||||
if let Some(dirty_meta) = dirty_meta {
|
||||
meta.on_ready(Box::new(move |_| {
|
||||
let mut dirty_meta = dirty_meta.clone();
|
||||
|
@ -538,13 +579,20 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn make_async_dirsize(path: &PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>) -> Async<usize> {
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale_preview: Option<Stale>) -> Async<usize> {
|
||||
let path = path.clone();
|
||||
|
||||
let mut dirsize = Async::new(Box::new(move |stale| {
|
||||
if *stale.lock()? { HError::stale()? }
|
||||
let dirsize_closure = Box::new(move |stale: Stale| {
|
||||
if stale.is_stale()? { HError::stale()? }
|
||||
Ok(std::fs::read_dir(&path)?.count())
|
||||
}));
|
||||
});
|
||||
|
||||
let mut dirsize = match stale_preview {
|
||||
Some(stale) => Async::new_with_stale(dirsize_closure, stale),
|
||||
None => Async::new(dirsize_closure)
|
||||
};
|
||||
|
||||
if let Some(dirty_meta) = dirty_meta {
|
||||
dirsize.on_ready(Box::new(move |_| {
|
||||
let mut dirty_meta = dirty_meta.clone();
|
||||
|
@ -604,10 +652,12 @@ impl File {
|
|||
pub fn reload_meta(&mut self) -> HResult<()> {
|
||||
self.dirty_meta.as_mut()?.set_dirty();
|
||||
self.meta_processed = false;
|
||||
self.meta = File::make_async_meta(&self.path, self.dirty_meta.clone());
|
||||
self.meta = File::make_async_meta(&self.path,
|
||||
self.dirty_meta.clone(),
|
||||
None);
|
||||
if self.dirsize.is_some() {
|
||||
self.dirsize
|
||||
= Some(File::make_async_dirsize(&self.path, self.dirty_meta.clone()));
|
||||
= Some(File::make_async_dirsize(&self.path, self.dirty_meta.clone(), None));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -720,8 +770,8 @@ impl File {
|
|||
self.tag = Some(new_state);
|
||||
|
||||
match new_state {
|
||||
true => TAGS.lock()?.1.push(self.path.clone()),
|
||||
false => { TAGS.lock()?.1.remove_item(&self.path); },
|
||||
true => TAGS.write()?.1.push(self.path.clone()),
|
||||
false => { TAGS.write()?.1.remove_item(&self.path); },
|
||||
}
|
||||
self.save_tags()?;
|
||||
Ok(())
|
||||
|
@ -730,7 +780,7 @@ impl File {
|
|||
pub fn save_tags(&self) -> HResult<()> {
|
||||
std::thread::spawn(|| -> HResult<()> {
|
||||
let tagfile_path = crate::paths::tagfile_path()?;
|
||||
let tags = TAGS.lock()?.clone();
|
||||
let tags = TAGS.read()?.clone();
|
||||
let tags_str = tags.1.iter().map(|p| {
|
||||
let path = p.to_string_lossy().to_string();
|
||||
format!("{}\n", path)
|
||||
|
|
161
src/preview.rs
161
src/preview.rs
|
@ -1,4 +1,4 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
use rayon::ThreadPool;
|
||||
|
||||
|
@ -10,8 +10,6 @@ use crate::coordinates::Coordinates;
|
|||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
|
||||
|
||||
pub type Stale = Arc<Mutex<bool>>;
|
||||
|
||||
pub type AsyncValueFn<T> = Box<Fn(Stale) -> HResult<T> + Send>;
|
||||
pub type AsyncValue<T> = Arc<Mutex<Option<HResult<T>>>>;
|
||||
pub type AsyncReadyFn<T> = Box<Fn(&mut T) -> HResult<()> + Send>;
|
||||
|
@ -33,8 +31,30 @@ fn kill_proc() -> HResult<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_stale(stale: &Arc<Mutex<bool>>) -> HResult<bool> {
|
||||
let stale = *(stale.lock().unwrap());
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Stale(Arc<RwLock<bool>>);
|
||||
|
||||
impl Stale {
|
||||
pub fn new() -> Stale {
|
||||
Stale(Arc::new(RwLock::new(false)))
|
||||
}
|
||||
pub fn is_stale(&self) -> HResult<bool> {
|
||||
Ok(*self.0.read()?)
|
||||
}
|
||||
pub fn set_stale(&self) -> HResult<()> {
|
||||
*self.0.write()? = true;
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_fresh(&self) -> HResult<()> {
|
||||
*self.0.write()? = false;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn is_stale(stale: &Stale) -> HResult<bool> {
|
||||
let stale = stale.is_stale()?;
|
||||
Ok(stale)
|
||||
}
|
||||
|
||||
|
@ -68,7 +88,20 @@ impl<T: Send + 'static> Async<T> {
|
|||
async_value: Arc::new(Mutex::new(None)),
|
||||
async_closure: Arc::new(Mutex::new(Some(closure))),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
stale: Arc::new(Mutex::new(false)) };
|
||||
stale: Stale::new() };
|
||||
|
||||
async_value
|
||||
}
|
||||
|
||||
pub fn new_with_stale(closure: AsyncValueFn<T>,
|
||||
stale: Stale)
|
||||
-> Async<T> {
|
||||
let async_value = Async {
|
||||
value: HError::async_not_ready(),
|
||||
async_value: Arc::new(Mutex::new(None)),
|
||||
async_closure: Arc::new(Mutex::new(Some(closure))),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
stale: stale };
|
||||
|
||||
async_value
|
||||
}
|
||||
|
@ -79,53 +112,104 @@ impl<T: Send + 'static> Async<T> {
|
|||
async_value: Arc::new(Mutex::new(None)),
|
||||
async_closure: Arc::new(Mutex::new(None)),
|
||||
on_ready: Arc::new(Mutex::new(None)),
|
||||
stale: Arc::new(Mutex::new(false))
|
||||
stale: Stale::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> HResult<()> {
|
||||
let closure = self.async_closure.lock()?.take()?;
|
||||
let closure = self.async_closure.clone();
|
||||
let async_value = self.async_value.clone();
|
||||
let stale = self.stale.clone();
|
||||
let on_ready_fn = self.on_ready.lock()?.take();
|
||||
let on_ready_fn = self.on_ready.clone();
|
||||
|
||||
std::thread::spawn(move|| -> HResult<()> {
|
||||
let mut value = closure(stale);
|
||||
let value = closure.lock().map(|closure|
|
||||
closure.as_ref().map(|closure|
|
||||
closure(stale)));
|
||||
|
||||
if let Ok(ref mut value) = value {
|
||||
if let Some(on_ready_fn) = on_ready_fn {
|
||||
on_ready_fn(value);
|
||||
if let Ok(value) = value {
|
||||
if let Some(value) = value {
|
||||
match value {
|
||||
Ok(mut value) => {
|
||||
if let Ok(mut on_ready_fn) = on_ready_fn.lock() {
|
||||
if let Some(on_ready_fn) = on_ready_fn.as_ref() {
|
||||
on_ready_fn(&mut value).log();
|
||||
}
|
||||
on_ready_fn.take();
|
||||
}
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value|
|
||||
async_value.replace(Ok(value))).ok();
|
||||
closure.lock().map(|mut closure|
|
||||
closure.take()).ok();
|
||||
},
|
||||
Err(err) => {
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value|
|
||||
async_value.replace(Err(err))).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value|
|
||||
async_value.replace(Err(HError::MutexError))).ok();
|
||||
}
|
||||
|
||||
async_value.lock()?.replace(value);
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_pooled(&mut self, pool: &ThreadPool) -> HResult<()> {
|
||||
let closure = self.async_closure.lock()?.take()?;
|
||||
let closure = self.async_closure.clone();
|
||||
let async_value = self.async_value.clone();
|
||||
let stale = self.stale.clone();
|
||||
let on_ready_fn = self.on_ready.lock()?.take();
|
||||
let on_ready_fn = self.on_ready.clone();
|
||||
|
||||
pool.spawn(move || {
|
||||
let mut value = closure(stale);
|
||||
let value = closure.lock().map(|closure|
|
||||
closure.as_ref().map(|closure|
|
||||
closure(stale)));
|
||||
|
||||
if let Ok(ref mut value) = value {
|
||||
if let Some(on_ready_fn) = on_ready_fn {
|
||||
on_ready_fn(value);
|
||||
if let Ok(value) = value {
|
||||
if let Some(value) = value {
|
||||
match value {
|
||||
Ok(mut value) => {
|
||||
if let Ok(mut on_ready_fn) = on_ready_fn.lock() {
|
||||
if let Some(on_ready_fn) = on_ready_fn.as_ref() {
|
||||
on_ready_fn(&mut value).log();
|
||||
}
|
||||
on_ready_fn.take();
|
||||
}
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value|
|
||||
async_value.replace(Ok(value))).ok();
|
||||
closure.lock().map(|mut closure|
|
||||
closure.take()).ok();
|
||||
},
|
||||
Err(err) => {
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value|
|
||||
async_value.replace(Err(err))).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value|
|
||||
async_value.replace(Err(HError::MutexError))).ok();
|
||||
}
|
||||
|
||||
async_value
|
||||
.lock()
|
||||
.map(|mut async_value| async_value.replace(value));
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn wait(&mut self) -> HResult<()> {
|
||||
let closure = self.async_closure.lock()?.take()?;
|
||||
let mut value = closure(self.stale.clone());
|
||||
|
@ -141,12 +225,21 @@ impl<T: Send + 'static> Async<T> {
|
|||
}
|
||||
|
||||
pub fn set_stale(&mut self) -> HResult<()> {
|
||||
*self.stale.lock()? = true;
|
||||
self.stale.set_stale()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_fresh(&self) -> HResult<()> {
|
||||
self.stale.set_fresh()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_stale(&self) -> HResult<bool> {
|
||||
is_stale(&self.stale)
|
||||
self.stale.is_stale()
|
||||
}
|
||||
|
||||
pub fn get_stale(&self) -> Stale {
|
||||
self.stale.clone()
|
||||
}
|
||||
|
||||
pub fn take_async(&mut self) -> HResult<()> {
|
||||
|
@ -251,6 +344,10 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
|||
self.widget.is_stale()
|
||||
}
|
||||
|
||||
pub fn get_stale(&self) -> Stale {
|
||||
self.widget.get_stale()
|
||||
}
|
||||
|
||||
pub fn widget(&self) -> HResult<&W> {
|
||||
self.widget.get()
|
||||
}
|
||||
|
@ -292,7 +389,7 @@ impl<T: Widget + Send + 'static> Widget for AsyncWidget<T> {
|
|||
}
|
||||
|
||||
fn refresh(&mut self) -> HResult<()> {
|
||||
self.widget.take_async().log();
|
||||
self.widget.take_async().ok();
|
||||
|
||||
let coords = self.get_coordinates()?.clone();
|
||||
if let Ok(widget) = self.widget_mut() {
|
||||
|
@ -342,7 +439,7 @@ pub struct Previewer {
|
|||
core: WidgetCore,
|
||||
file: Option<File>,
|
||||
selection: Option<File>,
|
||||
cached_files: Option<Files>
|
||||
cached_files: Option<Files>,
|
||||
}
|
||||
|
||||
|
||||
|
@ -435,7 +532,7 @@ impl Previewer {
|
|||
selection: Option<File>,
|
||||
cached_files: Option<Files>,
|
||||
core: &WidgetCore,
|
||||
stale: Arc<Mutex<bool>>)
|
||||
stale: Stale)
|
||||
-> Result<WidgetO, HError> {
|
||||
let files = cached_files.or_else(|| {
|
||||
Files::new_from_path_cancellable(&file.path,
|
||||
|
@ -456,7 +553,7 @@ impl Previewer {
|
|||
Ok(Box::new(file_list) as Box<dyn Widget + Send>)
|
||||
}
|
||||
|
||||
fn preview_text(file: &File, core: &WidgetCore, stale: Arc<Mutex<bool>>)
|
||||
fn preview_text(file: &File, core: &WidgetCore, stale: Stale)
|
||||
-> HResult<WidgetO> {
|
||||
let lines = core.coordinates.ysize() as usize;
|
||||
let mut textview
|
||||
|
@ -476,7 +573,7 @@ impl Previewer {
|
|||
|
||||
fn preview_external(file: &File,
|
||||
core: &WidgetCore,
|
||||
stale: Arc<Mutex<bool>>)
|
||||
stale: Stale)
|
||||
-> Result<Box<dyn Widget + Send>, HError> {
|
||||
let process =
|
||||
std::process::Command::new("scope.sh")
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::minibuffer::MiniBuffer;
|
|||
use crate::term;
|
||||
use crate::term::{Screen, ScreenExt};
|
||||
use crate::dirty::{Dirtyable, DirtyBit};
|
||||
use crate::preview::Stale;
|
||||
use crate::signal_notify::{notify, Signal};
|
||||
|
||||
use std::io::stdin;
|
||||
|
|
Loading…
Reference in New Issue