clap_complete/aot/shells/
shell.rs
1use std::fmt::Display;
2use std::path::Path;
3use std::str::FromStr;
4
5use clap::builder::PossibleValue;
6use clap::ValueEnum;
7
8use crate::shells;
9use crate::Generator;
10
11#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
13#[non_exhaustive]
14pub enum Shell {
15 Bash,
17 Elvish,
19 Fish,
21 PowerShell,
23 Zsh,
25}
26
27impl Display for Shell {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 self.to_possible_value()
30 .expect("no values are skipped")
31 .get_name()
32 .fmt(f)
33 }
34}
35
36impl FromStr for Shell {
37 type Err = String;
38
39 fn from_str(s: &str) -> Result<Self, Self::Err> {
40 for variant in Self::value_variants() {
41 if variant.to_possible_value().unwrap().matches(s, false) {
42 return Ok(*variant);
43 }
44 }
45 Err(format!("invalid variant: {s}"))
46 }
47}
48
49impl ValueEnum for Shell {
51 fn value_variants<'a>() -> &'a [Self] {
52 &[
53 Shell::Bash,
54 Shell::Elvish,
55 Shell::Fish,
56 Shell::PowerShell,
57 Shell::Zsh,
58 ]
59 }
60
61 fn to_possible_value(&self) -> Option<PossibleValue> {
62 Some(match self {
63 Shell::Bash => PossibleValue::new("bash"),
64 Shell::Elvish => PossibleValue::new("elvish"),
65 Shell::Fish => PossibleValue::new("fish"),
66 Shell::PowerShell => PossibleValue::new("powershell"),
67 Shell::Zsh => PossibleValue::new("zsh"),
68 })
69 }
70}
71
72impl Generator for Shell {
73 fn file_name(&self, name: &str) -> String {
74 match self {
75 Shell::Bash => shells::Bash.file_name(name),
76 Shell::Elvish => shells::Elvish.file_name(name),
77 Shell::Fish => shells::Fish.file_name(name),
78 Shell::PowerShell => shells::PowerShell.file_name(name),
79 Shell::Zsh => shells::Zsh.file_name(name),
80 }
81 }
82
83 fn generate(&self, cmd: &clap::Command, buf: &mut dyn std::io::Write) {
84 match self {
85 Shell::Bash => shells::Bash.generate(cmd, buf),
86 Shell::Elvish => shells::Elvish.generate(cmd, buf),
87 Shell::Fish => shells::Fish.generate(cmd, buf),
88 Shell::PowerShell => shells::PowerShell.generate(cmd, buf),
89 Shell::Zsh => shells::Zsh.generate(cmd, buf),
90 }
91 }
92}
93
94impl Shell {
95 pub fn from_shell_path<P: AsRef<Path>>(path: P) -> Option<Shell> {
107 parse_shell_from_path(path.as_ref())
108 }
109
110 pub fn from_env() -> Option<Shell> {
133 if let Some(env_shell) = std::env::var_os("SHELL") {
134 Shell::from_shell_path(env_shell)
135 } else if cfg!(windows) {
136 Some(Shell::PowerShell)
137 } else {
138 None
139 }
140 }
141}
142
143fn parse_shell_from_path(path: &Path) -> Option<Shell> {
146 let name = path.file_stem()?.to_str()?;
147 match name {
148 "bash" => Some(Shell::Bash),
149 "zsh" => Some(Shell::Zsh),
150 "fish" => Some(Shell::Fish),
151 "elvish" => Some(Shell::Elvish),
152 "powershell" | "powershell_ise" => Some(Shell::PowerShell),
153 _ => None,
154 }
155}