1use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
11pub enum Shell {
12 #[default]
14 Bash,
15 Zsh,
17 Fish,
19 #[serde(rename = "powershell")]
21 PowerShell,
22}
23
24impl Shell {
25 pub fn detect(target: Option<&str>) -> Self {
27 if let Some(t) = target {
28 return Self::parse(t);
29 }
30
31 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 Shell::Bash
44 }
45
46 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 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 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}