Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 38 additions & 11 deletions alix/shell_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def detect_current_shell(self) -> ShellType:
return ShellType.FISH
elif user_shell.endswith("/sh"):
return ShellType.SH
except (ImportError, KeyError, AttributeError):
except (ImportError, KeyError, AttributeError, OSError, PermissionError, RuntimeError, ValueError):
pass

# Method 3: macOS-specific detection using dscl (Directory Service Command Line)
Expand All @@ -80,17 +80,31 @@ def detect_current_shell(self) -> ShellType:
timeout=5,
)
if result.returncode == 0 and result.stdout:
shell_path = result.stdout.split()[-1].lower()
if "zsh" in shell_path:
return ShellType.ZSH
elif "bash" in shell_path:
return ShellType.BASH
elif "fish" in shell_path:
return ShellType.FISH
for line in result.stdout.splitlines():
if line.startswith("UserShell:"):
parts = line.split(":", 1)
if len(parts) == 2:
shell_path = parts[1].strip().lower()
if not shell_path:
return ShellType.UNKNOWN
if "zsh" in shell_path:
return ShellType.ZSH
elif "bash" in shell_path:
return ShellType.BASH
elif "fish" in shell_path:
return ShellType.FISH
elif shell_path.endswith("sh"):
return ShellType.SH
return ShellType.UNKNOWN
except (
subprocess.TimeoutExpired,
subprocess.CalledProcessError,
FileNotFoundError,
OSError,
PermissionError,
RuntimeError,
ValueError,
Exception,
):
pass

Expand Down Expand Up @@ -138,16 +152,29 @@ def detect_current_shell(self) -> ShellType:
timeout=5,
)
if result.returncode == 0:
version = result.stdout.strip()
# macOS 10.15+ (Catalina and later) defaults to zsh
major, minor = map(int, version.split(".")[:2])
version_line = result.stdout.strip().splitlines()[0]
parts = version_line.split(".")

# Require at least 2 parts, all non-empty and numeric
if len(parts) < 2 or any(p == "" or not p.isdigit() for p in parts):
return ShellType.UNKNOWN

try:
major, minor = int(parts[0]), int(parts[1])
except (ValueError, IndexError):
return ShellType.UNKNOWN

if major >= 11 or (major == 10 and minor >= 15):
return ShellType.ZSH
except (
subprocess.TimeoutExpired,
subprocess.CalledProcessError,
ValueError,
FileNotFoundError,
OSError,
PermissionError,
RuntimeError,
Exception,
):
pass

Expand Down
Loading
Loading