cargo-mate 1.7.6

Rust development companion that enhances cargo with intelligent workflows, state management, performance optimization, and comprehensive project monitoring.
Documentation
use indicatif::{ProgressBar, ProgressStyle as IndicatifStyle, MultiProgress};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;
use std::time::Duration;
use colored::*;
use anyhow::Result;
use crate::progress::tracker::{BuildTracker, BuildTrend};
pub enum ProgressStyle {
    Nautical,
    Classic,
    Minimal,
    Verbose,
}
pub struct BuildProgressBar {
    multi: MultiProgress,
    main_bar: ProgressBar,
    status_bar: Option<ProgressBar>,
    warning_counter: Arc<AtomicUsize>,
    error_counter: Arc<AtomicUsize>,
    tracker: Arc<Mutex<BuildTracker>>,
    style: ProgressStyle,
}
impl BuildProgressBar {
    pub fn new() -> Result<Self> {
        Self::with_style(ProgressStyle::Nautical)
    }
    pub fn with_style(style: ProgressStyle) -> Result<Self> {
        let multi = MultiProgress::new();
        let main_bar = multi.add(ProgressBar::new(100));
        main_bar.set_style(Self::get_indicatif_style(&style));
        let status_bar = if matches!(style, ProgressStyle::Verbose) {
            Some(multi.add(ProgressBar::new_spinner()))
        } else {
            None
        };
        Ok(Self {
            multi,
            main_bar,
            status_bar,
            warning_counter: Arc::new(AtomicUsize::new(0)),
            error_counter: Arc::new(AtomicUsize::new(0)),
            tracker: Arc::new(Mutex::new(BuildTracker::new()?)),
            style,
        })
    }
    fn get_indicatif_style(style: &ProgressStyle) -> IndicatifStyle {
        match style {
            ProgressStyle::Nautical => {
                IndicatifStyle::default_bar()
                    .template("{spinner:.cyan} [{bar:40.cyan/blue}] {pos}/{len} {msg}")
                    .unwrap()
                    .progress_chars("⚓▬▬")
                    .tick_strings(
                        &[
                            "",
                            "🌊 ",
                            "",
                            "🚢 ",
                            "🏴‍☠️ ",
                            "🧭 ",
                            "",
                            "🦜 ",
                            "🐙 ",
                            "🦈 ",
                            "🐚 ",
                            "🌊 ",
                            "",
                        ],
                    )
            }
            ProgressStyle::Classic => {
                IndicatifStyle::default_bar()
                    .template(
                        "{spinner:.green} [{bar:40.green/white}] {pos}/{len} {msg}",
                    )
                    .unwrap()
                    .progress_chars("=>-")
            }
            ProgressStyle::Minimal => {
                IndicatifStyle::default_bar()
                    .template("{bar:50} {msg}")
                    .unwrap()
                    .progress_chars("█▓░")
            }
            ProgressStyle::Verbose => {
                IndicatifStyle::default_bar()
                    .template(
                        "{spinner:.cyan} {msg}\n[{bar:50.cyan/blue}] {pos}/{len} ({percent}%) ETA: {eta}",
                    )
                    .unwrap()
                    .progress_chars("=>-")
            }
        }
    }
    pub fn start_build(&self, command: &str) {
        let stats = self.tracker.lock().unwrap().get_stats();
        let message = match stats.trend {
            BuildTrend::Improving => {
                format!(
                    "📈 Building... | Success Rate: {:.1}% (improving!) | Last: {} ⚠️  {}",
                    stats.success_rate * 100.0, stats.avg_warnings as usize, stats
                    .avg_errors as usize
                )
            }
            BuildTrend::Degrading => {
                format!(
                    "📉 Building... | Success Rate: {:.1}% (needs attention) | Last: {} ⚠️  {}",
                    stats.success_rate * 100.0, stats.avg_warnings as usize, stats
                    .avg_errors as usize
                )
            }
            BuildTrend::Stable => {
                format!(
                    "🔨 Building... | Success Rate: {:.1}% | Last: {} ⚠️  {}",
                    stats.success_rate * 100.0, stats.avg_warnings as usize, stats
                    .avg_errors as usize
                )
            }
        };
        self.main_bar.set_message(message);
        self.main_bar.enable_steady_tick(Duration::from_millis(100));
        if let Some(status) = &self.status_bar {
            status.set_message(format!("Executing: {}", command.yellow()));
            status.enable_steady_tick(Duration::from_millis(80));
        }
    }
    pub fn update_progress(&self, current: u64, total: u64) {
        self.main_bar.set_length(total);
        self.main_bar.set_position(current);
    }
    pub fn update_counters(&self, warnings: usize, errors: usize) {
        self.warning_counter.store(warnings, Ordering::Relaxed);
        self.error_counter.store(errors, Ordering::Relaxed);
        let msg = if errors > 0 {
            format!(
                "{} errors | ⚠️  {} warnings", errors.to_string().red(), warnings
                .to_string().yellow()
            )
                .red()
                .to_string()
        } else if warnings > 0 {
            format!("⚠️  {} warnings", warnings).yellow().to_string()
        } else {
            "✨ Clean build!".green().to_string()
        };
        self.main_bar.set_message(msg);
    }
    pub fn log_message(&self, message: &str) {
        if let Some(status) = &self.status_bar {
            status.set_message(message.to_string());
        }
    }
    pub fn finish(&self, success: bool) {
        if success {
            let warnings = self.warning_counter.load(Ordering::Relaxed);
            let message = if warnings > 0 {
                format!("✅ Build successful with {} warnings", warnings)
                    .yellow()
                    .to_string()
            } else {
                "✅ Build successful! 🎉".green().bold().to_string()
            };
            self.main_bar.finish_with_message(message);
        } else {
            let errors = self.error_counter.load(Ordering::Relaxed);
            self.main_bar
                .finish_with_message(
                    format!("❌ Build failed with {} errors", errors)
                        .red()
                        .bold()
                        .to_string(),
                );
        }
        if let Some(status) = &self.status_bar {
            status.finish_and_clear();
        }
    }
    pub fn get_warning_count(&self) -> usize {
        self.warning_counter.load(Ordering::Relaxed)
    }
    pub fn get_error_count(&self) -> usize {
        self.error_counter.load(Ordering::Relaxed)
    }
    pub fn show_summary(&self) {
        let stats = self.tracker.lock().unwrap().get_stats();
        println!("\n{}", "".repeat(60).cyan());
        println!("{}", "📊 Build Summary".cyan().bold());
        println!("{}", "".repeat(60).cyan());
        println!("Total Builds: {}", stats.total_builds.to_string().yellow());
        println!("Success Rate: {:.1}%", (stats.success_rate * 100.0));
        println!("Average Warnings: {:.1}", stats.avg_warnings);
        println!("Average Errors: {:.1}", stats.avg_errors);
        if let Some(last_success) = &stats.last_success {
            println!(
                "Last Success: {} ({}ms)", last_success.timestamp.format("%H:%M:%S"),
                last_success.duration_ms
            );
        }
        if let Some(last_failure) = &stats.last_failure {
            println!(
                "Last Failure: {} ({} errors)", last_failure.timestamp
                .format("%H:%M:%S"), last_failure.errors
            );
        }
        match stats.trend {
            BuildTrend::Improving => {
                println!("Trend: {} Improving! Keep it up! 🚀", "📈".green())
            }
            BuildTrend::Stable => println!("Trend: {} Stable", "➡️".yellow()),
            BuildTrend::Degrading => {
                println!("Trend: {} Degrading - needs attention", "📉".red())
            }
        }
        println!("{}", "".repeat(60).cyan());
    }
}