From 34ff9847cb252581565aca257ba6c540dd8a4fb5 Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 5 Nov 2020 20:55:57 +0000 Subject: [PATCH] progress bar host API works --- TODO | 3 +-- src/delete.rs | 2 +- src/main.rs | 53 +++++++++++++++++++++++++++++++++------------ src/progress/mod.rs | 43 +++++++++++++++++++++++++++++++----- src/state.rs | 6 +++-- 5 files changed, 83 insertions(+), 24 deletions(-) diff --git a/TODO b/TODO index b1ea52a..dc74ff1 100644 --- a/TODO +++ b/TODO @@ -1,2 +1 @@ -Add lolistealer-like async progress bar handler to State (check state.rs) - +Rework logging macro calls to use new progress API diff --git a/src/delete.rs b/src/delete.rs index 24ac094..efce546 100644 --- a/src/delete.rs +++ b/src/delete.rs @@ -28,7 +28,7 @@ use futures::{ async fn process_single(state: Arc, path: impl AsRef) -> eyre::Result<()> { let path = path.as_ref(); - debug_assert!(!path.is_file(), "process_single() expected a file, but {:?} is not one.", path); + debug_assert!(path.is_file(), "process_single() expected a file, but {:?} is not one.", path); let _g = state.lock().await; debug!("{:?} Processing", path); diff --git a/src/main.rs b/src/main.rs index 5135038..b334ee4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,22 +102,47 @@ async fn validate_config(config: config::Config) -> eyre::Result async fn begin() -> eyre::Result { + use futures::prelude::*; install()?; - let state = Arc::new(state::State::new(validate_config(config::Config::default()).await - .wrap_err(eyre!("Failed to validate config"))?)); - info!("Validated config OK"); - if args::process(|file| { - let state = Arc::clone(&state); - use futures::future::TryFutureExt; - process(state, file).inspect_err(|err| eprintln!("{:?}", err)) - }).await - .wrap_err(eyre!("One or more child workers failed to complete successfully"))? - .len() == 0 { - args::usage(); - } - - Ok(0) + let (progress, progress_join) = { + let bar = termprogress::progress::Bar::new(50); + let (p, join) = progress::host(bar); + (p, join.map(|bar| match bar { + Ok(bar) => { + bar.complete(); + Ok(()) + }, + Err(panic) => { + println!(); + Err(panic) + }, + })) + }; + + let state = Arc::new(state::State::new(validate_config(config::Config::default()).await + .wrap_err(eyre!("Failed to validate config"))?, + progress)); + info!("Validated config OK"); + if args::process(|file| { + let state = Arc::clone(&state); + use futures::future::TryFutureExt; + process(state, file).inspect_err(|err| eprintln!("{:?}", err)) + }).await + .wrap_err(eyre!("One or more child workers failed to complete successfully"))? + .len() == 0 + { + args::usage(); + } + + //Cleanup deferred in new `async` block to drop `state` before this block is ran. + async move { + progress_join.await?; + + Ok::<_, eyre::Report>(0) + }.map(|res| res.wrap_err(eyre!("Cleanup failed"))) + }.await + } #[tokio::main] diff --git a/src/progress/mod.rs b/src/progress/mod.rs index 754e115..16956eb 100644 --- a/src/progress/mod.rs +++ b/src/progress/mod.rs @@ -41,7 +41,10 @@ pub enum CommandKind Bump(isize), BumpHigh(isize), - + Set{low: Option, high: Option}, + + Refresh, + /// Add a task to the tasklist /// /// # Response @@ -58,6 +61,7 @@ pub enum CommandKind Many(Vec), } +/// The type sent in response to a `Command`. pub type Response = Option>; #[derive(Debug)] @@ -131,7 +135,7 @@ impl State } /// A handle to a running async progress bar -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Handle where B: ProgressBar, { @@ -145,6 +149,19 @@ where B: ProgressBar, dead: watch::Receiver, } +impl Clone for Handle +{ + fn clone(&self)->Self + { + Self { + chan: self.chan.clone(), + bar: self.bar.clone(), + state: self.state.clone(), + dead: self.dead.clone(), + } + } +} + impl Handle { /// Is the worker alive? @@ -235,7 +252,7 @@ impl fmt::Display for WorkerCommError } } -/// Host a progress bar detached +/// Host a progress bar and detach it pub fn host(bar: B) -> (Handle, JoinHandle) { let state = Arc::new(RwLock::new(Default::default())); @@ -255,6 +272,13 @@ pub fn host(bar: B) -> (Handle, JoinH ({ let mut tasks = tasklist::TaskList::new(); macro_rules! update_bar { + (refresh $($tt:tt)*) => { + { + let bar = bar.read().await; + bar.refresh(); + update_bar!($($tt)*); + } + }; (to $state:ident $($tt:tt)*) => { { let mut bar = bar.write().await; @@ -301,6 +325,8 @@ pub fn host(bar: B) -> (Handle, JoinH }; () => {}; } + + update_bar!(refresh); while let Some(Command(command, response)) = rx.recv().await { let response = Arc::new(std::sync::Mutex::new(Some(response))); @@ -362,6 +388,14 @@ pub fn host(bar: B) -> (Handle, JoinH update_bar!(to state); }, + CommandKind::Set{low: None, high: None} => (), + CommandKind::Set{low, high} => { + let mut state = state.write().await; + state.cur = low.unwrap_or(state.cur); + state.max = high.unwrap_or(state.max); + + update_bar!(to state); + }, CommandKind::Line(line) => update_bar!(write line), CommandKind::LineErr(line) => update_bar!(write error line), @@ -371,8 +405,7 @@ pub fn host(bar: B) -> (Handle, JoinH CommandKind::RemoveTask(id) => { send_response!(update_bar!(-task id title)); }, - - //TODO: Title + CommandKind::Refresh => update_bar!(refresh), CommandKind::Many(_) => unimplemented!(), } } diff --git a/src/state.rs b/src/state.rs index 62623f6..5e58105 100644 --- a/src/state.rs +++ b/src/state.rs @@ -14,13 +14,14 @@ use futures::{ }; /// Contains state for a set of operations -//TODO: Add progress bar handler in here, when we get around to adding it. #[derive(Debug)] pub struct State { cfg: config::Config, mtx: Option, stop: RwLock<()>, + + progress: progress::Handle, } /// Guard for operations inside state @@ -30,12 +31,13 @@ pub struct Permit<'a>(RwLockReadGuard<'a, ()>, Option>); impl State { /// Create a new state - pub fn new(cfg: config::Config) -> Self + pub fn new(cfg: config::Config, progress: progress::Handle) -> Self { Self { mtx: cfg.limit.map(|x| Semaphore::new(x.into())), cfg, stop: RwLock::new(()), + progress, } }