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