From 428879e184b4a2160e3a12dbf2f95f10d8cb5b0a Mon Sep 17 00:00:00 2001 From: rabite Date: Sun, 26 Jan 2020 01:31:29 +0100 Subject: add builder for ListView --- Cargo.lock | 6 +-- Cargo.toml | 2 +- src/fscache.rs | 7 +++ src/listview.rs | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 168 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0cb3a72..bbee8dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,7 +63,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "async_value" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -580,7 +580,7 @@ name = "hunter" version = "1.3.5" dependencies = [ "alphanumeric-sort 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "async_value 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "async_value 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1556,7 +1556,7 @@ dependencies = [ "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" -"checksum async_value 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70c539659e43174b12194af36cda1859266a5dcad90d87bafe80e25f49666140" +"checksum async_value 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "35a62a04436ffd962e78a3301658eac900480d425ea36ec42553aadc572742be" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" diff --git a/Cargo.toml b/Cargo.toml index d6c9472..48080c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ parse-ansi = "0.1.6" signal-notify = "0.1.3" systemstat = "0.1.5" mime_guess = "2.0" -async_value = "0.2.5" +async_value = "0.2.6" osstrtools = "0.2" pathbuftools = "0.1" clap = "2.33" diff --git a/src/fscache.rs b/src/fscache.rs index bf5ab2f..613bd3e 100644 --- a/src/fscache.rs +++ b/src/fscache.rs @@ -183,6 +183,13 @@ impl FsCache { } } + pub fn get_files_sync_stale(&self, dir: &File, stale: Stale) -> HResult { + let files = self.get_files(&dir, stale)?.1; + let files = files.run_sync()?; + let files = FsCache::ensure_not_empty(files)?; + Ok(files) + } + pub fn get_files_sync(&self, dir: &File) -> HResult { let files = self.get_files(&dir, Stale::new())?.1; let files = files.run_sync()?; diff --git a/src/listview.rs b/src/listview.rs index 8a14d54..134f9b0 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -1,14 +1,18 @@ use std::fmt::Debug; +use std::path::{Path, PathBuf}; + use termion::event::Key; use unicode_width::UnicodeWidthStr; -use std::path::{Path, PathBuf}; +use async_value::{Stale, StopIter}; use crate::files::{File, Files}; use crate::fail::{HResult, HError, ErrorLog}; use crate::term; use crate::widget::{Widget, WidgetCore}; use crate::dirty::Dirtyable; +use crate::fscache::FsCache; + pub trait Listable { type Item: Debug + PartialEq + Default; @@ -253,8 +257,125 @@ where } +pub enum FileSource { + Path(File), + Files(Files) +} + + +pub struct FileListBuilder { + core: WidgetCore, + source: FileSource, + cache: Option, + selected_file: Option, + stale: Option, + meta_upto: usize, + meta_all: bool, + prerender: bool +} + +impl FileListBuilder { + pub fn new(core: WidgetCore, source: FileSource) -> Self { + FileListBuilder { + core: core, + source: source, + cache: None, + selected_file: None, + stale: None, + meta_upto: 0, + meta_all: false, + prerender: false + } + } + + pub fn select(mut self, file: impl Into>) -> Self { + self.selected_file = file.into(); + self + } + + pub fn with_cache(mut self, cache: impl Into>) -> Self { + self.cache = cache.into(); + self + } + + pub fn with_stale(mut self, stale: impl Into>) -> Self { + self.stale = stale.into(); + self + } + + pub fn meta_upto(mut self, upto: impl Into>) -> Self { + self.meta_upto = upto.into().unwrap_or(0); + self + } + + pub fn meta_all(mut self) -> Self { + self.meta_all = true; + self + } + + pub fn prerender(mut self) -> Self { + self.prerender = true; + self + } + + pub fn build(self) -> HResult> { + let c = &self.cache; + let s = self.stale.clone(); + let mut files = match self.source { + FileSource::Files(f) => Ok(f), + FileSource::Path(f) => { + c.as_ref() + .map_or_else(| | Files::new_from_path(&f.path), + |c| s.map_or_else(| | c.get_files_sync(&f), + |s| c.get_files_sync_stale(&f, s))) + } + }?; + + if self.meta_all { + files.meta_all(); + } else if self.meta_upto > 0 { + files.meta_upto(self.meta_upto, Some(self.core.get_sender())); + } + + let selected_file = match self.selected_file { + Some(f) => Some(f), + None => { + c.as_ref() + .map(|c| c.get_selection(&files.directory).ok()) + .flatten() + } + }; + + let mut view = ListView::new(&self.core, files); + + selected_file.map(|mut f| { + f.meta_sync().log(); + view.select_file(&f); + }); + + if self.prerender { + view.refresh().log(); + + + match self.stale { + Some(s) => view.render_buffer_stale(s)?, + None => view.render_buffer()? + } + + if view.buffer.len() > 0 { + view.lines = view.buffer.len() - 1; + } + }; + + Ok(view) + } +} + impl ListView { + pub fn builder(core: WidgetCore, source: FileSource) -> FileListBuilder { + FileListBuilder::new(core, source) + } pub fn update_selected_file(&mut self) { let pos = self.selection; @@ -327,12 +448,13 @@ impl ListView } pub fn select_file(&mut self, file: &File) { - self.current_item = Some(file.clone()); + let file = file.clone(); + self.current_item = Some(file); let pos = self .content .iter_files() - .position(|item| item == file) + .position(|item| item == self.selected_file()) .unwrap_or(0); self.set_selection(pos); } @@ -719,6 +841,38 @@ impl ListView .collect() } + fn render_buffer(&mut self) -> HResult<()> { + let render_fn = self.render_line_fn(); + self.buffer = self.content + .iter_files() + .enumerate() + .map(|(_, file)| { + render_fn(file) + }) + .collect(); + Ok(()) + } + + fn render_buffer_stale(&mut self, stale: Stale) -> HResult<()> { + let render_fn = self.render_line_fn(); + let buffer = self.content + .iter_files() + .stop_stale(stale.clone()) + .enumerate() + .map(|(_, file)| { + render_fn(file) + }) + .collect(); + + if stale.is_stale() + .unwrap_or(true) { + return HError::stale(); + } else { + self.buffer = buffer; + return Ok(()) + } + } + fn refresh_files(&mut self) -> HResult<()> { if let Ok(Some(mut refresh)) = self.content.get_refresh() { let file = self.clone_selected_file(); -- cgit v1.2.3