refactor(progress): extract format_stage_line with themed styling
Pull the line-formatting logic out of finish_stage() into a standalone public format_stage_line() so that sync.rs can build stage lines without needing a live ProgressBar (e.g. for static multi-line blocks printed after the spinner is cleared). The new function applies Theme::info().bold() to the label and Theme::timing() to the elapsed column, giving every stage line consistent color treatment. finish_stage() now delegates to it. Includes a unit test asserting the formatted output contains the expected icon, label, summary, and elapsed components.
This commit is contained in:
@@ -4,7 +4,7 @@ use std::sync::LazyLock;
|
||||
use std::time::Duration;
|
||||
use tracing_subscriber::fmt::MakeWriter;
|
||||
|
||||
use crate::cli::render::Icons;
|
||||
use crate::cli::render::{Icons, Theme};
|
||||
|
||||
static MULTI: LazyLock<MultiProgress> = LazyLock::new(MultiProgress::new);
|
||||
|
||||
@@ -56,12 +56,21 @@ pub fn nested_progress(msg: &str, len: u64, robot_mode: bool) -> ProgressBar {
|
||||
///
|
||||
/// Output: ` ✓ Label summary elapsed`
|
||||
pub fn finish_stage(pb: &ProgressBar, icon: &str, label: &str, summary: &str, elapsed: Duration) {
|
||||
let elapsed_str = format_elapsed(elapsed);
|
||||
let line = format!(" {icon} {label:<12}{summary:>40} {elapsed_str:>8}",);
|
||||
let line = format_stage_line(icon, label, summary, elapsed);
|
||||
pb.set_style(ProgressStyle::with_template("{msg}").expect("valid template"));
|
||||
pb.finish_with_message(line);
|
||||
}
|
||||
|
||||
/// Build a static stage line showing icon, label, summary, and elapsed.
|
||||
///
|
||||
/// Output: ` ✓ Label summary elapsed`
|
||||
pub fn format_stage_line(icon: &str, label: &str, summary: &str, elapsed: Duration) -> String {
|
||||
let elapsed_str = format_elapsed(elapsed);
|
||||
let styled_label = Theme::info().bold().render(&format!("{label:<12}"));
|
||||
let styled_elapsed = Theme::timing().render(&format!("{elapsed_str:>8}"));
|
||||
format!(" {icon} {styled_label}{summary:>40} {styled_elapsed}")
|
||||
}
|
||||
|
||||
/// Format a Duration as a compact human string (e.g. "1.2s", "42ms", "1m 5s").
|
||||
fn format_elapsed(d: Duration) -> String {
|
||||
let ms = d.as_millis();
|
||||
@@ -203,4 +212,13 @@ mod tests {
|
||||
assert_eq!(format_elapsed(Duration::from_secs(65)), "1m 5s");
|
||||
assert_eq!(format_elapsed(Duration::from_secs(120)), "2m 0s");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_stage_line_includes_label_summary_and_elapsed() {
|
||||
let line = format_stage_line("✔", "Issues", "10 issues", Duration::from_millis(4200));
|
||||
assert!(line.contains("✔"));
|
||||
assert!(line.contains("Issues"));
|
||||
assert!(line.contains("10 issues"));
|
||||
assert!(line.contains("4.2s"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user