1use crate::table::{OxurTable, Tabled};
7use oxur_repl::metadata::SystemMetadata;
8
9pub fn show_system_info(metadata: &SystemMetadata, _color_enabled: bool) -> String {
14 let mut output = String::new();
15
16 output.push_str(&header("System Information", _color_enabled));
17 output.push('\n');
18
19 #[derive(Tabled)]
20 struct InfoRow {
21 #[tabled(rename = "Property")]
22 property: String,
23 #[tabled(rename = "Value")]
24 value: String,
25 }
26
27 let rows = vec![
29 InfoRow { property: "Oxur Version".to_string(), value: metadata.oxur_version.clone() },
30 InfoRow { property: "Rust Version".to_string(), value: metadata.rust_version.clone() },
31 InfoRow { property: "Cargo Version".to_string(), value: metadata.cargo_version.clone() },
32 InfoRow {
33 property: "Operating System".to_string(),
34 value: format!("{} {}", metadata.os_name, metadata.os_version),
35 },
36 InfoRow { property: "Architecture".to_string(), value: metadata.arch.clone() },
37 InfoRow { property: "Hostname".to_string(), value: metadata.hostname.clone() },
38 InfoRow { property: "Process ID".to_string(), value: metadata.pid.to_string() },
39 InfoRow {
40 property: "Working Directory".to_string(),
41 value: metadata.cwd.display().to_string(),
42 },
43 InfoRow { property: "Uptime".to_string(), value: format_uptime(metadata.uptime_seconds()) },
44 ];
45
46 output.push_str(&OxurTable::new(rows).with_title("SYSTEM INFO").with_footer().render());
47 output.push('\n');
48
49 output
50}
51
52fn header(text: &str, color_enabled: bool) -> String {
54 if color_enabled {
55 format!("\x1b[1;36m{}\x1b[0m\n{}\n", text, "═".repeat(text.len()))
56 } else {
57 format!("{}\n{}\n", text, "=".repeat(text.len()))
58 }
59}
60
61fn format_uptime(seconds: f64) -> String {
63 let secs = seconds as u64;
64 const MINUTE: u64 = 60;
65 const HOUR: u64 = MINUTE * 60;
66 const DAY: u64 = HOUR * 24;
67
68 if secs >= DAY {
69 let days = secs / DAY;
70 let hours = (secs % DAY) / HOUR;
71 format!("{}d {}h", days, hours)
72 } else if secs >= HOUR {
73 let hours = secs / HOUR;
74 let mins = (secs % HOUR) / MINUTE;
75 format!("{}h {}m", hours, mins)
76 } else if secs >= MINUTE {
77 let mins = secs / MINUTE;
78 let s = secs % MINUTE;
79 format!("{}m {}s", mins, s)
80 } else {
81 format!("{:.1}s", seconds)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_format_uptime_seconds() {
91 assert_eq!(format_uptime(0.0), "0.0s");
92 assert_eq!(format_uptime(5.5), "5.5s");
93 assert_eq!(format_uptime(30.0), "30.0s");
94 }
95
96 #[test]
97 fn test_format_uptime_minutes() {
98 assert_eq!(format_uptime(60.0), "1m 0s");
99 assert_eq!(format_uptime(90.0), "1m 30s");
100 assert_eq!(format_uptime(3599.0), "59m 59s");
101 }
102
103 #[test]
104 fn test_format_uptime_hours() {
105 assert_eq!(format_uptime(3600.0), "1h 0m");
106 assert_eq!(format_uptime(7200.0), "2h 0m");
107 assert_eq!(format_uptime(5400.0), "1h 30m");
108 }
109
110 #[test]
111 fn test_format_uptime_days() {
112 assert_eq!(format_uptime(86400.0), "1d 0h");
113 assert_eq!(format_uptime(172800.0), "2d 0h");
114 assert_eq!(format_uptime(90000.0), "1d 1h");
115 }
116
117 #[test]
118 fn test_show_system_info() {
119 let metadata = SystemMetadata::capture();
120 let output = show_system_info(&metadata, false);
121
122 assert!(output.contains("System Information"));
124 assert!(output.contains("SYSTEM INFO"));
125 assert!(output.contains("Oxur Version"));
126 assert!(output.contains("Rust Version"));
127 assert!(output.contains("Process ID"));
128 assert!(output.contains("Working Directory"));
129 assert!(output.contains("Uptime"));
130 }
131
132 #[test]
133 fn test_show_system_info_with_color() {
134 let metadata = SystemMetadata::capture();
135 let output = show_system_info(&metadata, true);
136
137 assert!(output.contains("\x1b["));
139 }
140
141 #[test]
142 fn test_header_with_color() {
143 let header = header("Test", true);
144 assert!(header.contains("\x1b[1;36m"));
145 assert!(header.contains("Test"));
146 }
147
148 #[test]
149 fn test_header_without_color() {
150 let header = header("Test", false);
151 assert!(!header.contains("\x1b["));
152 assert!(header.contains("Test"));
153 assert!(header.contains("===="));
154 }
155}