/// Print a step header. pub fn step(msg: &str) { println!("\n==> {msg}"); } /// Print a success/info line. pub fn ok(msg: &str) { println!(" {msg}"); } /// Print a warning to stderr. pub fn warn(msg: &str) { eprintln!(" WARN: {msg}"); } /// Return an aligned text table. Columns padded to max width. pub fn table(rows: &[Vec], headers: &[&str]) -> String { if headers.is_empty() { return String::new(); } let mut col_widths: Vec = headers.iter().map(|h| h.len()).collect(); for row in rows { for (i, cell) in row.iter().enumerate() { if i < col_widths.len() { col_widths[i] = col_widths[i].max(cell.len()); } } } let header_line: String = headers .iter() .enumerate() .map(|(i, h)| format!("{:>() .join(" "); let separator: String = col_widths .iter() .map(|&w| "-".repeat(w)) .collect::>() .join(" "); let mut lines = vec![header_line, separator]; for row in rows { let cells: Vec = (0..headers.len()) .map(|i| { let val = row.get(i).map(|s| s.as_str()).unwrap_or(""); format!("{: