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