1use colored::Colorize;
9use indicatif::{ProgressBar, ProgressStyle};
10use std::path::Path;
11use std::time::Duration;
12
13pub fn clean_path<P: AsRef<Path>>(path: P) -> String {
15 let s = path.as_ref().display().to_string();
16 let s = if let Some(stripped) = s.strip_prefix(r"\\?\") {
17 stripped.to_string()
18 } else {
19 s
20 };
21 let s = if let Some(stripped) = s.strip_prefix("/private/var/") {
22 format!("/var/{stripped}")
23 } else if let Some(stripped) = s.strip_prefix("/private/tmp/") {
24 format!("/tmp/{stripped}")
25 } else {
26 s
27 };
28 s.replace("//", "/")
29}
30
31pub fn create_spinner(msg: &'static str) -> ProgressBar {
33 let pb = ProgressBar::new_spinner();
34 pb.set_style(
35 ProgressStyle::default_spinner()
36 .tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏")
37 .template("{spinner:.cyan} {msg}")
38 .expect("Invalid progress bar template"),
39 );
40 pb.set_message(msg);
41 pb.enable_steady_tick(Duration::from_millis(80));
42 pb
43}
44
45pub fn print_success(msg: &str) {
47 println!("{} {}", "✓".green().bold(), msg);
48}
49
50pub fn print_warning(msg: &str) {
52 println!("{} {}", "⚠".yellow().bold(), msg);
53}
54
55pub fn print_error(msg: &str) {
57 eprintln!("{} {}", "✗".red().bold(), msg);
58}
59
60pub fn print_info(msg: &str) {
62 println!("{} {}", "→".blue().bold(), msg);
63}
64
65pub fn print_notice(msg: &str) {
72 eprintln!("{} {}", "→".blue().bold(), msg);
73}
74
75pub fn print_header(msg: &str) {
77 println!("\n{}", msg.bold().underline());
78}
79
80pub fn print_banner() {
82 let art = format!(
83 r#"
84 ___ _____ __ __ ____ ____ _ _ _ _ _____
85| _ \ | ____|\ \ / / | _ \| _ \| | | | \ | | ____|
86| | | || _| \ \ / / | |_) | |_) | | | | \| | _|
87| |_| || |___ \ V / | __/| _ <| |_| | |\ | |___
88|____/ |_____| \_/ |_| |_| \_\\___/|_| \_|_____| v{}
89"#,
90 crate::constants::VERSION
91 );
92 println!("{}", art.truecolor(64, 224, 208).bold());
93}
94
95pub fn plural<'a>(count: usize, one: &'a str, many: &'a str) -> &'a str {
100 if count == 1 { one } else { many }
101}
102
103pub fn format_bytes(bytes: u64) -> String {
105 use humansize::{BINARY, format_size};
106 format_size(bytes, BINARY)
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_format_bytes() {
115 assert_eq!(format_bytes(0), "0 B");
116 assert_eq!(format_bytes(1024), "1 KiB");
117 assert_eq!(format_bytes(1024 * 1024), "1 MiB");
118 assert_eq!(format_bytes(1024 * 1024 * 1024), "1 GiB");
119 }
120
121 #[test]
122 fn test_clean_path() {
123 assert_eq!(clean_path(r"\\?\C:\Users\krish"), r"C:\Users\krish");
124 assert_eq!(clean_path(r"/private/var/tmp/repo"), r"/var/tmp/repo");
125 assert_eq!(clean_path(r"//home//user//repo"), r"/home/user/repo");
126 }
127}