Skip to content

Commit fbc8e2d

Browse files
committed
fix: prefer Git for Windows bash.exe when available on Windows
Per @orhun's review on orhun#66: most users running terminal apps on Windows want a POSIX shell so the Ratatui demos behave the same as on Linux/macOS. The default-shell lookup now walks, in order: 1. `$SHELL` (already supported — useful when launching from Git Bash so the inherited shell is honoured). 2. Git for Windows `bash.exe` in well-known install locations: - `%ProgramW6432%\Git\{bin,usr/bin}\bash.exe` - `%ProgramFiles%\Git\{bin,usr/bin}\bash.exe` - `%ProgramFiles(x86)%\Git\{bin,usr/bin}\bash.exe` - `%LOCALAPPDATA%\Programs\Git\{bin,usr/bin}\bash.exe` 3. `bash.exe` anywhere on `PATH` (covers scoop / chocolatey installs). 4. `%COMSPEC%` (typically resolves to `cmd.exe`). 5. Literal `cmd.exe` as the final fallback. Verified on Windows 11 with Git for Windows installed at the default location — `bash.exe` is now the spawned PTY child: ProcessId : 204736 Name : bash.exe CommandLine : "C:\Program Files\Git/bin/bash.exe" Removing the Git install reverts to the `%COMSPEC%` / `cmd.exe` fallback verified by the previous commit.
1 parent 46cfe53 commit fbc8e2d

1 file changed

Lines changed: 55 additions & 2 deletions

File tree

src/runtime.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,17 @@ pub struct TerminalRuntime {
186186

187187
/// Returns the default shell for the current platform.
188188
///
189-
/// On Windows this prefers `%COMSPEC%` (the resolved command processor) and
190-
/// falls back to `cmd.exe`. On other platforms it falls back to `/bin/sh`.
189+
/// On Windows this prefers Git for Windows' `bash.exe` when it can be found
190+
/// (most users running terminal apps on Windows want a POSIX shell so the
191+
/// Ratatui demos behave the same as on Linux/macOS), then `%COMSPEC%` (the
192+
/// resolved command processor), and finally `cmd.exe`. On other platforms
193+
/// it falls back to `/bin/sh`.
191194
fn default_shell() -> String {
192195
#[cfg(windows)]
193196
{
197+
if let Some(bash) = find_git_bash() {
198+
return bash;
199+
}
194200
env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".to_string())
195201
}
196202
#[cfg(not(windows))]
@@ -199,6 +205,53 @@ fn default_shell() -> String {
199205
}
200206
}
201207

208+
/// Looks for a Git for Windows `bash.exe` in the well-known install
209+
/// locations, then on `PATH`. Returns the first match.
210+
///
211+
/// `usr/bin/bash.exe` is the MSYS shell bundled with Git for Windows;
212+
/// `bin/bash.exe` is the shim used by the Git Bash launcher. Either works
213+
/// as a PTY shell.
214+
#[cfg(windows)]
215+
fn find_git_bash() -> Option<String> {
216+
use std::path::PathBuf;
217+
218+
// Flat candidate table keeps every probe path on one footing: each entry
219+
// is `(env_var, subpath_under_that_directory)`. New install layouts (Git
220+
// via Scoop, Chocolatey, custom installers) only need another row here.
221+
const CANDIDATES: &[(&str, &str)] = &[
222+
("ProgramW6432", "Git/bin/bash.exe"),
223+
("ProgramW6432", "Git/usr/bin/bash.exe"),
224+
("ProgramFiles", "Git/bin/bash.exe"),
225+
("ProgramFiles", "Git/usr/bin/bash.exe"),
226+
("ProgramFiles(x86)", "Git/bin/bash.exe"),
227+
("ProgramFiles(x86)", "Git/usr/bin/bash.exe"),
228+
("LOCALAPPDATA", "Programs/Git/bin/bash.exe"),
229+
("LOCALAPPDATA", "Programs/Git/usr/bin/bash.exe"),
230+
];
231+
232+
for (env_var, sub) in CANDIDATES {
233+
let Ok(base) = env::var(env_var) else {
234+
continue;
235+
};
236+
let candidate = PathBuf::from(base).join(sub);
237+
if candidate.is_file() {
238+
return candidate.into_os_string().into_string().ok();
239+
}
240+
}
241+
242+
// Final fallback: walk PATH so custom installs (Scoop shims, etc.) work.
243+
if let Ok(path) = env::var("PATH") {
244+
for entry in env::split_paths(&path) {
245+
let candidate = entry.join("bash.exe");
246+
if candidate.is_file() {
247+
return candidate.into_os_string().into_string().ok();
248+
}
249+
}
250+
}
251+
252+
None
253+
}
254+
202255
impl TerminalRuntime {
203256
/// Spawns the shell PTY runtime.
204257
///

0 commit comments

Comments
 (0)