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 std::time::Duration;
|
||||||
use tracing_subscriber::fmt::MakeWriter;
|
use tracing_subscriber::fmt::MakeWriter;
|
||||||
|
|
||||||
use crate::cli::render::Icons;
|
use crate::cli::render::{Icons, Theme};
|
||||||
|
|
||||||
static MULTI: LazyLock<MultiProgress> = LazyLock::new(MultiProgress::new);
|
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`
|
/// Output: ` ✓ Label summary elapsed`
|
||||||
pub fn finish_stage(pb: &ProgressBar, icon: &str, label: &str, summary: &str, elapsed: Duration) {
|
pub fn finish_stage(pb: &ProgressBar, icon: &str, label: &str, summary: &str, elapsed: Duration) {
|
||||||
let elapsed_str = format_elapsed(elapsed);
|
let line = format_stage_line(icon, label, summary, elapsed);
|
||||||
let line = format!(" {icon} {label:<12}{summary:>40} {elapsed_str:>8}",);
|
|
||||||
pb.set_style(ProgressStyle::with_template("{msg}").expect("valid template"));
|
pb.set_style(ProgressStyle::with_template("{msg}").expect("valid template"));
|
||||||
pb.finish_with_message(line);
|
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").
|
/// Format a Duration as a compact human string (e.g. "1.2s", "42ms", "1m 5s").
|
||||||
fn format_elapsed(d: Duration) -> String {
|
fn format_elapsed(d: Duration) -> String {
|
||||||
let ms = d.as_millis();
|
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(65)), "1m 5s");
|
||||||
assert_eq!(format_elapsed(Duration::from_secs(120)), "2m 0s");
|
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