Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/WindServiceHandlers/Terminal/
LocalPTYGetProfiles.rs

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