The ProgressBar and Spinner structs have been refactored to use the same patterns as the input module. This should make the API more cohesive and able to support a wider variety of contexts.
DGHQ46S3S2RQ27CXF4OES5GDXUI63VTSYYQFLXHG7PRKSVWB3SZAC use std::sync::Arc;use std::time::Duration;use super::{ProgressBarTrait, SpinnerTrait};use indicatif::{MultiProgress, ProgressBar, ProgressStyle};use lazy_static::lazy_static;lazy_static! {static ref MULTI_PROGRESS: MultiProgress = MultiProgress::new();}pub fn new_progress(len: u64, message: String) -> Arc<ProgressBar> {let style =ProgressStyle::with_template("{msg:<20} [{bar:50}] {pos}/{len} [{elapsed_precise}]").unwrap().progress_chars("=> ");let progress_bar = ProgressBar::new(len).with_style(style).with_message(message);MULTI_PROGRESS.add(progress_bar.clone());progress_bar.enable_steady_tick(Duration::from_millis(15));Arc::new(progress_bar)}impl ProgressBarTrait for Arc<ProgressBar> {fn inc(&self, delta: u64) {self.as_ref().inc(delta);}fn finish(&self) {// Only finish the progress bar if it's the last referenceif Arc::strong_count(self) == 1 {self.as_ref().finish();}}fn boxed_clone(&self) -> Box<(dyn ProgressBarTrait)> {Box::new(self.clone())}}pub fn new_spinner(message: String) -> Arc<ProgressBar> {let style = ProgressStyle::with_template("{msg}{spinner}").unwrap().tick_strings(&[". ", ".. ", "...", " "]);let spinner = ProgressBar::new_spinner().with_style(style).with_message(message);spinner.enable_steady_tick(Duration::from_millis(200));MULTI_PROGRESS.add(spinner.clone());Arc::new(spinner)}impl SpinnerTrait for Arc<ProgressBar> {fn finish(&self) {// Only display finish message if it's the last referenceif Arc::strong_count(self) == 1 {self.set_style(ProgressStyle::with_template("{msg}").unwrap());self.finish_with_message(format!("{}... done!", self.message()));}}fn boxed_clone(&self) -> Box<dyn SpinnerTrait> {Box::new(self.clone())}}
mod terminal;use super::{ProgressBar, Spinner};use crate::{InteractionError, InteractiveContext};pub trait ProgressBarTrait: Send {fn inc(&self, delta: u64);fn finish(&self);fn boxed_clone(&self) -> Box<dyn ProgressBarTrait>;}impl ProgressBar {pub fn new<S: ToString>(len: u64, message: S) -> Result<ProgressBar, InteractionError> {Ok(Self(match crate::get_context()? {InteractiveContext::Terminal | InteractiveContext::NotInteractive => {Box::new(terminal::new_progress(len, message.to_string()))}}))}pub fn inc(&self, delta: u64) {self.0.inc(delta);}fn finish(&self) {self.0.finish()}}impl Drop for ProgressBar {fn drop(&mut self) {self.finish();}}impl Clone for ProgressBar {fn clone(&self) -> Self {Self(self.0.boxed_clone())}}pub trait SpinnerTrait: Send {fn finish(&self);fn boxed_clone(&self) -> Box<dyn SpinnerTrait>;}impl Spinner {pub fn new<S: ToString>(message: S) -> Result<Spinner, InteractionError> {Ok(Self(match crate::get_context()? {InteractiveContext::Terminal | InteractiveContext::NotInteractive => {Box::new(terminal::new_spinner(message.to_string()))}}))}fn finish(&self) {self.0.finish();}}impl Drop for Spinner {fn drop(&mut self) {self.finish();}}impl Clone for Spinner {fn clone(&self) -> Self {Self(self.0.boxed_clone())}}
// TODO: these should be replaced with a more sophisticated localization systempub const DOWNLOAD_MESSAGE: &str = "Downloading changes";pub const APPLY_MESSAGE: &str = "Applying changes";pub const UPLOAD_MESSAGE: &str = "Uploading changes";pub const COMPLETE_MESSAGE: &str = "Completing changes";pub const OUTPUT_MESSAGE: &str = "Outputting repository";
/// A progress bar that is controlled by codepub struct ProgressBar(Box<dyn ProgressBarTrait>);/// An animated progress bar to indicate activitypub struct Spinner(Box<dyn SpinnerTrait>);