Mountain/IPC/WindServiceHandlers/Terminal/
LocalPTYGetProfiles.rs1use serde_json::{Value, json};
14
15use crate::dev_log;
16
17pub async fn Fn() -> Result<Value, String> {
18 let mut Profiles = Vec::new();
19
20 #[cfg(unix)]
21 {
22 let DefaultShell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
23
24 let UnixShells = [
25 "/bin/zsh",
26 "/bin/bash",
27 "/bin/sh",
28 "/usr/bin/zsh",
29 "/usr/bin/bash",
30 "/usr/bin/fish",
31 "/usr/local/bin/fish",
32 "/usr/local/bin/zsh",
33 "/usr/local/bin/bash",
34 "/bin/dash",
35 "/usr/bin/ksh",
36 "/usr/bin/tcsh",
37 "/bin/csh",
38 "/usr/bin/pwsh",
39 "/usr/local/bin/pwsh",
40 ];
41
42 for Shell in &UnixShells {
43 if std::path::Path::new(Shell).exists() {
44 let Name = std::path::Path::new(Shell)
45 .file_name()
46 .and_then(|N| N.to_str())
47 .unwrap_or("shell");
48
49 Profiles.push(json!({
50 "profileName": Name,
51 "path": Shell,
52 "isDefault": *Shell == DefaultShell.as_str(),
53 "args": [],
54 "env": {},
55 "icon": "terminal"
56 }));
57 }
58 }
59
60 if let Ok(ShellsFile) = std::fs::read_to_string("/etc/shells") {
61 for Line in ShellsFile.lines() {
62 let Trimmed = Line.trim();
63
64 if Trimmed.starts_with('/') && !Trimmed.starts_with('#') {
65 let AlreadyAdded = Profiles.iter().any(|P| P.get("path").and_then(|V| V.as_str()) == Some(Trimmed));
66
67 if !AlreadyAdded && std::path::Path::new(Trimmed).exists() {
68 let Name = std::path::Path::new(Trimmed)
69 .file_name()
70 .and_then(|N| N.to_str())
71 .unwrap_or("shell");
72
73 Profiles.push(json!({
74 "profileName": Name,
75 "path": Trimmed,
76 "isDefault": Trimmed == DefaultShell.as_str(),
77 "args": [],
78 "env": {},
79 "icon": "terminal"
80 }));
81 }
82 }
83 }
84 }
85 }
86
87 #[cfg(target_os = "windows")]
88 {
89 let SystemRoot = std::env::var("SystemRoot").unwrap_or_else(|_| "C:\\Windows".to_string());
90
91 let ProgramFiles = std::env::var("ProgramFiles").unwrap_or_else(|_| "C:\\Program Files".to_string());
92
93 let LocalAppData =
94 std::env::var("LOCALAPPDATA").unwrap_or_else(|_| "C:\\Users\\User\\AppData\\Local".to_string());
95
96 let WindowsShells:Vec<(&str, String, Vec<&str>)> = vec![
97 (
98 "PowerShell",
99 format!("{}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", SystemRoot),
100 vec!["-NoLogo"],
101 ),
102 (
103 "PowerShell 7",
104 format!("{}\\PowerShell\\7\\pwsh.exe", ProgramFiles),
105 vec!["-NoLogo"],
106 ),
107 ("Command Prompt", format!("{}\\System32\\cmd.exe", SystemRoot), vec![]),
108 (
109 "Git Bash",
110 format!("{}\\Git\\bin\\bash.exe", ProgramFiles),
111 vec!["--login", "-i"],
112 ),
113 (
114 "Git Bash (User)",
115 format!("{}\\Programs\\Git\\bin\\bash.exe", LocalAppData),
116 vec!["--login", "-i"],
117 ),
118 ("WSL", format!("{}\\System32\\wsl.exe", SystemRoot), vec![]),
119 ("MSYS2", "C:\\msys64\\usr\\bin\\bash.exe".to_string(), vec!["--login", "-i"]),
120 ("Cygwin", "C:\\cygwin64\\bin\\bash.exe".to_string(), vec!["--login", "-i"]),
121 ];
122
123 let mut IsFirstFound = true;
124
125 for (Name, Path, Args) in &WindowsShells {
126 if std::path::Path::new(Path).exists() {
127 Profiles.push(json!({
128 "profileName": Name,
129 "path": Path,
130 "isDefault": IsFirstFound,
131 "args": Args,
132 "env": {},
133 "icon": "terminal"
134 }));
135
136 IsFirstFound = false;
137 }
138 }
139 }
140
141 dev_log!("terminal", "[GetProfiles] returning {} profiles", Profiles.len());
142
143 Ok(json!(Profiles))
144}