1use crate::core::ProcessStatus;
6use colored::*;
7
8pub fn format_duration(secs: u64) -> String {
12 if secs < 60 {
13 format!("{}s", secs)
14 } else if secs < 3600 {
15 format!("{}m {}s", secs / 60, secs % 60)
16 } else if secs < 86400 {
17 format!("{}h {}m", secs / 3600, (secs % 3600) / 60)
18 } else {
19 format!("{}d {}h", secs / 86400, (secs % 86400) / 3600)
20 }
21}
22
23pub fn uptime_label(uptime_secs: Option<u64>) -> String {
26 uptime_secs
27 .map(|secs| format!(" up {}", format_duration(secs)))
28 .unwrap_or_default()
29}
30
31pub fn plural(n: usize) -> &'static str {
35 if n == 1 {
36 ""
37 } else {
38 "es"
39 }
40}
41
42pub fn truncate_string(s: &str, max_len: usize) -> String {
44 if s.len() <= max_len {
45 s.to_string()
46 } else {
47 format!("{}...", &s[..max_len.saturating_sub(3)])
48 }
49}
50
51pub fn truncate_path(path: &str, max_len: usize) -> String {
53 if path.len() <= max_len {
54 path.to_string()
55 } else {
56 let start = path.len().saturating_sub(max_len.saturating_sub(3));
57 format!("...{}", &path[start..])
58 }
59}
60
61pub fn format_memory(memory_mb: f64) -> String {
65 if memory_mb < 1.0 {
66 format!("{:.0}KB", memory_mb * 1000.0)
67 } else if memory_mb < 1000.0 {
68 format!("{:.1}MB", memory_mb)
69 } else {
70 format!("{:.1}GB", memory_mb / 1000.0)
71 }
72}
73
74pub fn colorize_status(status: &ProcessStatus, status_str: &str) -> ColoredString {
76 match status {
77 ProcessStatus::Running => status_str.green(),
78 ProcessStatus::Sleeping => status_str.blue(),
79 ProcessStatus::Stopped => status_str.yellow(),
80 ProcessStatus::Zombie => status_str.red(),
81 _ => status_str.white(),
82 }
83}