1use crate::{
2 errors::{Error, Result},
3 infer::Infer,
4};
5use core::fmt;
6use std::str::FromStr;
7
8impl Shell {
9 pub fn infer() -> Result<Self> {
19 Infer::infer()
20 }
21}
22
23macro_rules! define_shells {
24 ($( $name:literal $(| $alias:literal ),* => $shell:tt ),*) => {
25 #[derive(Clone, Debug)]
28 pub enum Shell {
29 $(
30 $shell,
31 )*
32 }
33
34 impl FromStr for Shell {
35 type Err = Error;
36
37 fn from_str(s: &str) -> Result<Self, Self::Err> {
38 match s {
39 $(
40 $name $(| $alias)* => Ok(Self::$shell),
41 )*
42 _ => Err(Error::NoShellFound),
43 }
44 }
45 }
46
47 impl fmt::Display for Shell {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 match self {
50 $(
51 Self::$shell => write!(f, $name),
52 )*
53 }
54 }
55 }
56 };
57}
58
59define_shells!(
60 "sh" => Sh,
61 "bash" => Bash,
62 "zsh" => Zsh,
63 "fish" => Fish,
64 "nu" => Nushell,
65 "powershell" | "pwsh" => PowerShell,
66 "cmd" => Cmd
67);
68
69#[cfg(test)]
70mod test {
71 use super::*;
72 use std::env;
73
74 #[test]
75 fn integrate() {
76 let actual = env::var("ACTUAL_SHELL").expect("env var \"ACTUAL_SHELL\" is not specified");
77
78 let res = Shell::infer().unwrap();
79 assert_eq!(actual, res.to_string());
80 }
81}