1use std::env;
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, PartialEq)]
6pub enum OsType {
7 Windows,
8 Linux,
9 MacOS,
10}
11
12#[derive(Debug, Clone, PartialEq)]
14pub enum ShellType {
15 Cmd,
16 PowerShell,
17 Bash,
18 Zsh,
19 Fish,
20 Unknown,
21}
22
23#[derive(Debug, Clone)]
25pub struct SystemInfo {
26 pub os: OsType,
27 pub shell: ShellType,
28 pub current_dir: PathBuf,
29 pub username: Option<String>,
30 pub hostname: Option<String>,
31}
32
33pub fn get_system_info() -> SystemInfo {
35 SystemInfo {
36 os: detect_os(),
37 shell: detect_shell(),
38 current_dir: env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
39 username: env::var("USERNAME")
40 .or_else(|_| env::var("USER"))
41 .ok(),
42 hostname: env::var("COMPUTERNAME")
43 .or_else(|_| env::var("HOSTNAME"))
44 .ok(),
45 }
46}
47
48pub fn detect_os() -> OsType {
50 #[cfg(target_os = "windows")]
51 return OsType::Windows;
52
53 #[cfg(target_os = "linux")]
54 return OsType::Linux;
55
56 #[cfg(target_os = "macos")]
57 return OsType::MacOS;
58
59 #[cfg(not(any(target_os = "windows", target_os = "linux", target_os = "macos")))]
60 return OsType::Linux; }
62
63pub fn detect_shell() -> ShellType {
65 if cfg!(target_os = "windows") {
67 if let Ok(comspec) = env::var("COMSPEC")
68 && comspec.to_lowercase().contains("cmd.exe") {
69 return ShellType::Cmd;
70 }
71
72 if env::var("PSModulePath").is_ok() {
74 return ShellType::PowerShell;
75 }
76
77 return ShellType::Cmd; }
79
80 if let Ok(shell) = env::var("SHELL") {
82 let shell_lower = shell.to_lowercase();
83
84 if shell_lower.contains("bash") {
85 return ShellType::Bash;
86 } else if shell_lower.contains("zsh") {
87 return ShellType::Zsh;
88 } else if shell_lower.contains("fish") {
89 return ShellType::Fish;
90 }
91 }
92
93 ShellType::Unknown
97}
98
99impl OsType {
100 pub fn as_str(&self) -> &str {
102 match self {
103 OsType::Windows => "Windows",
104 OsType::Linux => "Linux",
105 OsType::MacOS => "macOS",
106 }
107 }
108}
109
110impl ShellType {
111 pub fn as_str(&self) -> &str {
113 match self {
114 ShellType::Cmd => "cmd.exe",
115 ShellType::PowerShell => "PowerShell",
116 ShellType::Bash => "bash",
117 ShellType::Zsh => "zsh",
118 ShellType::Fish => "fish",
119 ShellType::Unknown => "unknown",
120 }
121 }
122}
123
124impl SystemInfo {
125 pub fn display(&self) -> String {
127 format!(
128 "OS: {}\nShell: {}\nCurrent Dir: {}\nUsername: {}\nHostname: {}",
129 self.os.as_str(),
130 self.shell.as_str(),
131 self.current_dir.display(),
132 self.username.as_deref().unwrap_or("(unknown)"),
133 self.hostname.as_deref().unwrap_or("(unknown)")
134 )
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_detect_os() {
144 let os = detect_os();
145 #[cfg(target_os = "windows")]
146 assert_eq!(os, OsType::Windows);
147 #[cfg(target_os = "linux")]
148 assert_eq!(os, OsType::Linux);
149 #[cfg(target_os = "macos")]
150 assert_eq!(os, OsType::MacOS);
151 }
152
153 #[test]
154 fn test_get_system_info() {
155 let info = get_system_info();
156 assert_eq!(info.os, detect_os());
157 assert_eq!(info.shell, detect_shell());
158 assert!(info.current_dir.as_os_str().len() > 0);
159 }
160
161 #[test]
162 fn test_system_info_display() {
163 let info = SystemInfo {
164 os: OsType::Linux,
165 shell: ShellType::Bash,
166 current_dir: PathBuf::from("/home/user"),
167 username: Some("testuser".to_string()),
168 hostname: None,
169 };
170
171 let display = info.display();
172 assert!(display.contains("OS: Linux"));
173 assert!(display.contains("Username: testuser"));
174 assert!(display.contains("Hostname: (unknown)"));
175 }
176}