1use colored::Colorize;
2use indicatif::{ProgressBar, ProgressStyle};
3
4fn prefix() -> String {
9 "[mvm]".bold().cyan().to_string()
10}
11
12pub fn info(msg: &str) {
14 println!("{} {}", prefix(), msg);
15}
16
17pub fn success(msg: &str) {
19 println!("{} {}", prefix(), msg.green());
20}
21
22pub fn error(msg: &str) {
24 eprintln!("{} {}", "[mvm]".bold().red(), msg.red());
25}
26
27pub fn warn(msg: &str) {
29 println!("{} {}", prefix(), msg.yellow());
30}
31
32pub fn step(n: u32, total: u32, msg: &str) {
34 println!(
35 "\n{} {} {}",
36 prefix(),
37 format!("Step {}/{}:", n, total).bold().yellow(),
38 msg,
39 );
40}
41
42pub fn banner(lines: &[&str]) {
48 let width = lines.iter().map(|l| l.len()).max().unwrap_or(0) + 4;
49 let rule = "=".repeat(width);
50
51 println!();
52 println!("{}", rule.bold().green());
53 for line in lines {
54 let pad = width - line.len() - 4;
55 println!(
56 "{}",
57 format!(" {}{} ", line, " ".repeat(pad)).bold().green()
58 );
59 }
60 println!("{}", rule.bold().green());
61 println!();
62}
63
64pub fn status_header() {
70 println!("{}", "mvm status".bold());
71 println!("{}", "----------".dimmed());
72}
73
74pub fn status_line(label: &str, value: &str) {
77 let colored_value = if value.starts_with("Running") {
78 value.green().to_string()
79 } else if value == "Stopped" {
80 value.yellow().to_string()
81 } else if value.starts_with("Not ") || value == "-" {
82 value.dimmed().to_string()
83 } else if value.starts_with("Starting") {
84 value.yellow().to_string()
85 } else {
86 value.to_string()
87 };
88
89 println!("{} {}", format!("{:<14}", label).bold(), colored_value);
90}
91
92pub fn confirm(msg: &str) -> bool {
98 inquire::Confirm::new(msg)
99 .with_default(false)
100 .prompt()
101 .unwrap_or(false)
102}
103
104pub fn spinner(msg: &str) -> ProgressBar {
111 let pb = ProgressBar::new_spinner();
112 pb.set_style(
113 ProgressStyle::default_spinner()
114 .tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"])
115 .template("{spinner:.cyan} {msg}")
116 .expect("invalid spinner template"),
117 );
118 pb.set_message(msg.to_string());
119 pb.enable_steady_tick(std::time::Duration::from_millis(80));
120 pb
121}