use super::ShellType;
use crate::tools::is_tty;
use sysinfo::{Pid, Process, System};
pub fn get_parent_process_name() -> Option<String> {
let mut system = System::new();
system.refresh_processes_specifics(
sysinfo::ProcessesToUpdate::All,
true,
sysinfo::ProcessRefreshKind::everything(),
);
let current_pid = sysinfo::get_current_pid().ok()?;
let current_process = system.process(current_pid)?;
let parent_pid = current_process.parent()?;
let parent_process = system.process(parent_pid)?;
Some(parent_process.name().to_string_lossy().to_string())
}
pub fn detect_shell_from_parent() -> Option<ShellType> {
let parent_name = get_parent_process_name()?;
detect_shell_from_string(&parent_name.to_lowercase())
}
fn detect_shell_from_string(shell_str: &str) -> Option<ShellType> {
if shell_str.contains("bash") {
Some(ShellType::Bash)
} else if shell_str.contains("zsh") {
Some(ShellType::Zsh)
} else if shell_str.contains("fish") {
Some(ShellType::Fish)
} else if shell_str.contains("powershell") || shell_str.contains("pwsh") {
Some(ShellType::PowerShell)
} else if shell_str.contains("cmd") {
Some(ShellType::Cmd)
} else if shell_str.contains("tcsh") || shell_str.contains("csh") {
Some(ShellType::Tcsh)
} else if shell_str.contains("nu") {
Some(ShellType::Nu)
} else if shell_str.contains("sh") && !shell_str.contains("bash") && !shell_str.contains("zsh")
{
Some(ShellType::Posix)
} else {
None
}
}
pub fn detect_shell() -> ShellType {
if cfg!(windows) {
tracing::debug!(target: "shell_detection", "cfg!(windows)");
detect_windows_shell()
} else {
tracing::debug!(target: "shell_detection", "cfg!(not(windows))");
detect_unix_shell()
}
}
fn detect_windows_shell() -> ShellType {
if is_tty() {
if let Some(shell) = detect_shell_from_parent() {
return shell;
}
}
if std::env::var("WSL_DISTRO_NAME").is_ok() || std::env::var("WSL_INTEROP").is_ok() {
if let Ok(shell) = std::env::var("SHELL") {
if let Some(detected) = detect_shell_from_string(&shell) {
return detected;
}
}
return ShellType::Bash; }
if std::env::var("PSModulePath").is_ok() {
return ShellType::PowerShell;
}
if let Ok(term_program) = std::env::var("TERM_PROGRAM") {
if term_program == "vscode" {
if let Ok(vscode_shell) = std::env::var("VSCODE_SHELL_INTEGRATION") {
if let Some(shell) = detect_shell_from_string(&vscode_shell) {
return shell;
}
}
}
}
ShellType::PowerShell
}
fn detect_unix_shell() -> ShellType {
if is_tty() {
if let Some(shell) = detect_shell_from_parent() {
return shell;
}
}
if let Ok(shell) = std::env::var("SHELL") {
if let Some(detected) = detect_shell_from_string(&shell) {
return detected;
}
}
if let Ok(term_program) = std::env::var("TERM_PROGRAM") {
if term_program == "vscode" {
if let Ok(vscode_shell) = std::env::var("VSCODE_SHELL_INTEGRATION") {
if let Some(shell) = detect_shell_from_string(&vscode_shell) {
return shell;
}
}
}
}
ShellType::Unknown
}