hyperi_rustlib/cli/
output.rs1use std::fmt;
14
15pub fn print_success(msg: &str) {
17 eprintln!("[ok] {msg}");
18}
19
20pub fn print_error(msg: &str) {
22 eprintln!("[error] {msg}");
23}
24
25pub fn print_warn(msg: &str) {
27 eprintln!("[warn] {msg}");
28}
29
30pub fn print_info(msg: &str) {
32 eprintln!("[info] {msg}");
33}
34
35pub fn print_kv(key: &str, value: &dyn fmt::Display) {
37 eprintln!(" {key:<16} {value}");
38}
39
40pub fn print_table(headers: &[&str], rows: &[Vec<String>]) {
44 if headers.is_empty() {
45 return;
46 }
47
48 let mut widths: Vec<usize> = headers.iter().map(|h| h.len()).collect();
50 for row in rows {
51 for (i, cell) in row.iter().enumerate() {
52 if i < widths.len() {
53 widths[i] = widths[i].max(cell.len());
54 }
55 }
56 }
57
58 let header_line: Vec<String> = headers
60 .iter()
61 .zip(&widths)
62 .map(|(h, w)| format!("{h:<w$}"))
63 .collect();
64 eprintln!(" {}", header_line.join(" "));
65
66 let sep_line: Vec<String> = widths.iter().map(|w| "-".repeat(*w)).collect();
68 eprintln!(" {}", sep_line.join(" "));
69
70 for row in rows {
72 let cells: Vec<String> = row
73 .iter()
74 .zip(&widths)
75 .map(|(c, w)| format!("{c:<w$}"))
76 .collect();
77 eprintln!(" {}", cells.join(" "));
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_print_table_empty_headers() {
87 print_table(&[], &[]);
89 }
90
91 #[test]
92 fn test_print_table_formats() {
93 let headers = &["Name", "Value"];
95 let rows = vec![
96 vec!["key1".to_string(), "val1".to_string()],
97 vec!["longer_key".to_string(), "v".to_string()],
98 ];
99 print_table(headers, &rows);
100 }
101}