1 #[macro_use]
2 mod macros;
3 mod bash;
4 mod elvish;
5 mod fish;
6 mod powershell;
7 mod shell;
8 mod zsh;
9
10 // Std
11 use std::io::Write;
12
13 // Internal
14 use self::bash::BashGen;
15 use self::elvish::ElvishGen;
16 use self::fish::FishGen;
17 use self::powershell::PowerShellGen;
18 pub use self::shell::Shell;
19 use self::zsh::ZshGen;
20 use app::parser::Parser;
21
22 pub struct ComplGen<'a, 'b>
23 where
24 'a: 'b,
25 {
26 p: &'b Parser<'a, 'b>,
27 }
28
29 impl<'a, 'b> ComplGen<'a, 'b> {
new(p: &'b Parser<'a, 'b>) -> Self30 pub fn new(p: &'b Parser<'a, 'b>) -> Self {
31 ComplGen { p: p }
32 }
33
generate<W: Write>(&self, for_shell: Shell, buf: &mut W)34 pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) {
35 match for_shell {
36 Shell::Bash => BashGen::new(self.p).generate_to(buf),
37 Shell::Fish => FishGen::new(self.p).generate_to(buf),
38 Shell::Zsh => ZshGen::new(self.p).generate_to(buf),
39 Shell::PowerShell => PowerShellGen::new(self.p).generate_to(buf),
40 Shell::Elvish => ElvishGen::new(self.p).generate_to(buf),
41 }
42 }
43 }
44
45 // Gets all subcommands including child subcommands in the form of 'name' where the name
46 // is a single word (i.e. "install") of the path to said subcommand (i.e.
47 // "rustup toolchain install")
48 //
49 // Also note, aliases are treated as their own subcommands but duplicates of whatever they're
50 // aliasing.
all_subcommand_names(p: &Parser) -> Vec<String>51 pub fn all_subcommand_names(p: &Parser) -> Vec<String> {
52 debugln!("all_subcommand_names;");
53 let mut subcmds: Vec<_> = subcommands_of(p)
54 .iter()
55 .map(|&(ref n, _)| n.clone())
56 .collect();
57 for sc_v in p.subcommands.iter().map(|s| all_subcommand_names(&s.p)) {
58 subcmds.extend(sc_v);
59 }
60 subcmds.sort();
61 subcmds.dedup();
62 subcmds
63 }
64
65 // Gets all subcommands including child subcommands in the form of ('name', 'bin_name') where the name
66 // is a single word (i.e. "install") of the path and full bin_name of said subcommand (i.e.
67 // "rustup toolchain install")
68 //
69 // Also note, aliases are treated as their own subcommands but duplicates of whatever they're
70 // aliasing.
all_subcommands(p: &Parser) -> Vec<(String, String)>71 pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> {
72 debugln!("all_subcommands;");
73 let mut subcmds: Vec<_> = subcommands_of(p);
74 for sc_v in p.subcommands.iter().map(|s| all_subcommands(&s.p)) {
75 subcmds.extend(sc_v);
76 }
77 subcmds
78 }
79
80 // Gets all subcommands excluding child subcommands in the form of (name, bin_name) where the name
81 // is a single word (i.e. "install") and the bin_name is a space delineated list of the path to said
82 // subcommand (i.e. "rustup toolchain install")
83 //
84 // Also note, aliases are treated as their own subcommands but duplicates of whatever they're
85 // aliasing.
subcommands_of(p: &Parser) -> Vec<(String, String)>86 pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
87 debugln!(
88 "subcommands_of: name={}, bin_name={}",
89 p.meta.name,
90 p.meta.bin_name.as_ref().unwrap()
91 );
92 let mut subcmds = vec![];
93
94 debugln!(
95 "subcommands_of: Has subcommands...{:?}",
96 p.has_subcommands()
97 );
98 if !p.has_subcommands() {
99 let mut ret = vec![];
100 debugln!("subcommands_of: Looking for aliases...");
101 if let Some(ref aliases) = p.meta.aliases {
102 for &(n, _) in aliases {
103 debugln!("subcommands_of:iter:iter: Found alias...{}", n);
104 let mut als_bin_name: Vec<_> =
105 p.meta.bin_name.as_ref().unwrap().split(' ').collect();
106 als_bin_name.push(n);
107 let old = als_bin_name.len() - 2;
108 als_bin_name.swap_remove(old);
109 ret.push((n.to_owned(), als_bin_name.join(" ")));
110 }
111 }
112 return ret;
113 }
114 for sc in &p.subcommands {
115 debugln!(
116 "subcommands_of:iter: name={}, bin_name={}",
117 sc.p.meta.name,
118 sc.p.meta.bin_name.as_ref().unwrap()
119 );
120
121 debugln!("subcommands_of:iter: Looking for aliases...");
122 if let Some(ref aliases) = sc.p.meta.aliases {
123 for &(n, _) in aliases {
124 debugln!("subcommands_of:iter:iter: Found alias...{}", n);
125 let mut als_bin_name: Vec<_> =
126 p.meta.bin_name.as_ref().unwrap().split(' ').collect();
127 als_bin_name.push(n);
128 let old = als_bin_name.len() - 2;
129 als_bin_name.swap_remove(old);
130 subcmds.push((n.to_owned(), als_bin_name.join(" ")));
131 }
132 }
133 subcmds.push((
134 sc.p.meta.name.clone(),
135 sc.p.meta.bin_name.as_ref().unwrap().clone(),
136 ));
137 }
138 subcmds
139 }
140
get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String>141 pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String> {
142 debugln!("get_all_subcommand_paths;");
143 let mut subcmds = vec![];
144 if !p.has_subcommands() {
145 if !first {
146 let name = &*p.meta.name;
147 let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__");
148 let mut ret = vec![path.clone()];
149 if let Some(ref aliases) = p.meta.aliases {
150 for &(n, _) in aliases {
151 ret.push(path.replace(name, n));
152 }
153 }
154 return ret;
155 }
156 return vec![];
157 }
158 for sc in &p.subcommands {
159 let name = &*sc.p.meta.name;
160 let path =
161 sc.p.meta
162 .bin_name
163 .as_ref()
164 .unwrap()
165 .clone()
166 .replace(" ", "__");
167 subcmds.push(path.clone());
168 if let Some(ref aliases) = sc.p.meta.aliases {
169 for &(n, _) in aliases {
170 subcmds.push(path.replace(name, n));
171 }
172 }
173 }
174 for sc_v in p
175 .subcommands
176 .iter()
177 .map(|s| get_all_subcommand_paths(&s.p, false))
178 {
179 subcmds.extend(sc_v);
180 }
181 subcmds
182 }
183