cuenv_core/
shell.rs

1//! Shell type definitions and utilities for cuenv
2//!
3//! This module provides shell detection and formatting utilities
4//! used across cuenv for shell integration features.
5
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// Supported shell types for environment integration
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
11pub enum Shell {
12    /// Bash shell
13    #[default]
14    Bash,
15    /// Z shell
16    Zsh,
17    /// Fish shell
18    Fish,
19    /// PowerShell/pwsh
20    #[serde(rename = "powershell")]
21    PowerShell,
22}
23
24impl Shell {
25    /// Detect shell from environment or argument
26    pub fn detect(target: Option<&str>) -> Self {
27        if let Some(t) = target {
28            return Self::parse(t);
29        }
30
31        // Try to detect from environment
32        if let Ok(shell) = std::env::var("SHELL") {
33            if shell.contains("fish") {
34                return Shell::Fish;
35            } else if shell.contains("zsh") {
36                return Shell::Zsh;
37            } else if shell.contains("bash") {
38                return Shell::Bash;
39            }
40        }
41
42        // Default to bash
43        Shell::Bash
44    }
45
46    /// Parse shell from string
47    pub fn parse(s: &str) -> Self {
48        match s.to_lowercase().as_str() {
49            "zsh" => Shell::Zsh,
50            "fish" => Shell::Fish,
51            "powershell" | "pwsh" => Shell::PowerShell,
52            _ => Shell::Bash,
53        }
54    }
55
56    /// Get the name of the shell
57    pub fn name(&self) -> &'static str {
58        match self {
59            Shell::Bash => "bash",
60            Shell::Zsh => "zsh",
61            Shell::Fish => "fish",
62            Shell::PowerShell => "powershell",
63        }
64    }
65
66    /// Check if this shell is supported for integration
67    pub fn is_supported(&self) -> bool {
68        matches!(self, Shell::Bash | Shell::Zsh | Shell::Fish)
69    }
70}
71
72impl fmt::Display for Shell {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        write!(f, "{}", self.name())
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_shell_detection() {
84        assert_eq!(Shell::parse("bash"), Shell::Bash);
85        assert_eq!(Shell::parse("zsh"), Shell::Zsh);
86        assert_eq!(Shell::parse("fish"), Shell::Fish);
87        assert_eq!(Shell::parse("powershell"), Shell::PowerShell);
88        assert_eq!(Shell::parse("pwsh"), Shell::PowerShell);
89        assert_eq!(Shell::parse("unknown"), Shell::Bash);
90    }
91
92    #[test]
93    fn test_shell_name() {
94        assert_eq!(Shell::Bash.name(), "bash");
95        assert_eq!(Shell::Zsh.name(), "zsh");
96        assert_eq!(Shell::Fish.name(), "fish");
97        assert_eq!(Shell::PowerShell.name(), "powershell");
98    }
99
100    #[test]
101    fn test_shell_support() {
102        assert!(Shell::Bash.is_supported());
103        assert!(Shell::Zsh.is_supported());
104        assert!(Shell::Fish.is_supported());
105        assert!(!Shell::PowerShell.is_supported());
106    }
107
108    #[test]
109    fn test_shell_display() {
110        assert_eq!(format!("{}", Shell::Bash), "bash");
111        assert_eq!(format!("{}", Shell::Zsh), "zsh");
112        assert_eq!(format!("{}", Shell::Fish), "fish");
113        assert_eq!(format!("{}", Shell::PowerShell), "powershell");
114    }
115}