1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::{io, str::FromStr};
use clap::App;
use clap_generate::{generate, generators};
use miette::{Diagnostic, SourceSpan};
use quickcheck::{Arbitrary, Gen};
use thiserror::Error;
#[allow(clippy::enum_variant_names)]
#[derive(Eq, PartialEq, Debug, Clone, clap::ArgEnum, Copy)]
pub enum Shell {
Bash,
Elvish,
Fish,
PowerShell,
Zsh,
}
impl Arbitrary for Shell {
fn arbitrary(g: &mut Gen) -> Self {
*g.choose(&[
Self::Bash,
Self::Elvish,
Self::Fish,
Self::PowerShell,
Self::Zsh,
])
.unwrap()
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let options = [
Self::Bash,
Self::Elvish,
Self::Fish,
Self::PowerShell,
Self::Zsh,
];
let index = options.iter().position(|other| self.eq(other));
match index {
None | Some(0) => quickcheck::empty_shrinker(),
Some(index) => options
.get(index - 1)
.map_or(quickcheck::empty_shrinker(), |item| {
quickcheck::single_shrinker(*item)
}),
}
}
}
impl FromStr for Shell {
type Err = ShellFromStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"bash" => Ok(Self::Bash),
"fish" => Ok(Self::Fish),
"elvish" => Ok(Self::Elvish),
"powershell" => Ok(Self::PowerShell),
"zsh" => Ok(Self::Zsh),
_ => Err(ShellFromStrError {
source_code: s.to_string(),
underline: (0, s.len()).into(),
}),
}
}
}
impl From<Shell> for String {
fn from(shell: Shell) -> Self {
match shell {
Shell::Bash => "bash",
Shell::Elvish => "elvish",
Shell::Fish => "fish",
Shell::PowerShell => "powershell",
Shell::Zsh => "zsh",
}
.to_string()
}
}
#[derive(Debug, Eq, PartialEq, Error, Diagnostic)]
#[error("could not parse a shell from the given string")]
#[diagnostic(
url(docsrs),
help("valid shells are: bash, elvish, fish, powershell, and zsh")
)]
pub struct ShellFromStrError {
#[source_code]
source_code: String,
#[label("unknown shell")]
underline: SourceSpan,
}
pub fn print_completions(writer: &mut dyn io::Write, app: &mut App<'_>, shell: Shell) {
match shell {
Shell::Bash => generate::<_, _>(generators::Bash, app, app.get_name().to_string(), writer),
Shell::Elvish => {
generate::<_, _>(generators::Elvish, app, app.get_name().to_string(), writer);
}
Shell::Fish => generate::<_, _>(generators::Fish, app, app.get_name().to_string(), writer),
Shell::PowerShell => {
generate::<_, _>(
generators::PowerShell,
app,
app.get_name().to_string(),
writer,
);
}
Shell::Zsh => generate::<_, _>(generators::Zsh, app, app.get_name().to_string(), writer),
}
}