use std::sync::atomic::{AtomicBool, Ordering};
use console::Style;
static VERBOSE: AtomicBool = AtomicBool::new(false);
pub fn set_verbose(on: bool) {
VERBOSE.store(on, Ordering::Relaxed);
}
pub fn is_verbose() -> bool {
VERBOSE.load(Ordering::Relaxed)
}
pub fn detail(slide: i32, shape: &str, info: &str) {
if !is_verbose() {
return;
}
let s = Style::new().dim();
println!(" {} {:>2} {} {:<24} {}",
s.apply_to("Slide"),
s.apply_to(slide),
s.apply_to("│"),
s.apply_to(shape),
s.apply_to(info));
}
pub fn check_detail(slide: i32, check_type: &str, shape: &str, passed: bool, info: &str) {
if !is_verbose() {
return;
}
let s = Style::new().dim();
let mark = if passed {
Style::new().green().apply_to("✓")
} else {
Style::new().red().apply_to("✗")
};
println!(" {} {:>2} {} {:<5} {} {:<24} {} {}",
s.apply_to("Slide"),
s.apply_to(slide),
s.apply_to("│"),
s.apply_to(check_type),
s.apply_to("│"),
s.apply_to(shape),
mark,
info);
}
pub fn check_chart_series_diff(name: &str, name_pad: usize, diff_count: usize, total: usize, pairs: &[(f64, f64)], has_more: bool) {
if !is_verbose() {
return;
}
let s_dim = Style::new().dim();
let s_name = Style::new().yellow();
let s_ppt = Style::new().red();
let s_arrow = Style::new().dim();
let s_excel = Style::new().white().bold();
let mut pair_strs = Vec::new();
for (ppt, excel) in pairs {
pair_strs.push(format!("{}{}{}",
s_ppt.apply_to(fmt_short(*ppt)),
s_arrow.apply_to("→"),
s_excel.apply_to(fmt_short(*excel))));
}
let values = pair_strs.join(" ");
let overflow = if has_more { format!(" {}", s_dim.apply_to("...")) } else { String::new() };
let padded_name = format!("'{name}'{}", " ".repeat(name_pad.saturating_sub(name.len())));
let diff_label = format!("{diff_count}/{total} differ");
let prefix_plain_len = 2 + padded_name.len() + 1 + diff_label.len(); let gap = 41usize.saturating_sub(prefix_plain_len);
print!(" {} {} {}{}",
s_dim.apply_to("╰"),
s_name.apply_to(&padded_name),
s_dim.apply_to(&diff_label),
" ".repeat(gap));
if !pair_strs.is_empty() {
print!("{values}");
}
println!("{overflow}");
}
pub fn truncate_middle(name: &str) -> String {
if name.len() <= 14 {
return name.to_string();
}
format!("{}…{}", &name[..7], &name[name.len() - 6..])
}
fn fmt_short(v: f64) -> String {
let s = format!("{v:.2}");
if s.starts_with("0.") {
s[1..].to_string() } else if s.starts_with("-0.") {
format!("-{}", &s[2..]) } else {
s
}
}
pub fn note(msg: &str) {
if !is_verbose() {
return;
}
let s = Style::new().dim();
println!(" {}", s.apply_to(msg));
}