]> git.proxmox.com Git - rustc.git/blame - src/vendor/clap/src/completions/bash.rs
New upstream version 1.20.0+dfsg1
[rustc.git] / src / vendor / clap / src / completions / bash.rs
CommitLineData
8bb4bdeb
XL
1// Std
2use std::io::Write;
3
4// Internal
5use app::parser::Parser;
6use args::{ArgSettings, OptBuilder};
7use completions;
8
9pub struct BashGen<'a, 'b>
10 where 'a: 'b
11{
12 p: &'b Parser<'a, 'b>,
13}
14
15impl<'a, 'b> BashGen<'a, 'b> {
16 pub fn new(p: &'b Parser<'a, 'b>) -> Self { BashGen { p: p } }
17
18 pub fn generate_to<W: Write>(&self, buf: &mut W) {
19
20 w!(buf,
21 format!("_{name}() {{
22 local i cur prev opts cmds
23 COMPREPLY=()
24 cur=\"${{COMP_WORDS[COMP_CWORD]}}\"
25 prev=\"${{COMP_WORDS[COMP_CWORD-1]}}\"
26 cmd=\"\"
27 opts=\"\"
28
29 for i in ${{COMP_WORDS[@]}}
30 do
31 case \"${{i}}\" in
32 {name})
33 cmd=\"{name}\"
34 ;;
35 {subcmds}
36 *)
37 ;;
38 esac
39 done
40
41 case \"${{cmd}}\" in
42 {name})
43 opts=\"{name_opts}\"
44 if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq 1 ]] ; then
45 COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
46 return 0
47 fi
48 case \"${{prev}}\" in
49 {name_opts_details}
50 *)
51 COMPREPLY=()
52 ;;
53 esac
54 COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
55 return 0
56 ;;
57 {subcmd_details}
58 esac
59}}
60
61complete -F _{name} -o bashdefault -o default {name}
62",
63 name = self.p.meta.bin_name.as_ref().unwrap(),
64 name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
65 name_opts_details =
66 self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
67 subcmds = self.all_subcommands(),
68 subcmd_details = self.subcommand_details())
69 .as_bytes());
70 }
71
72 fn all_subcommands(&self) -> String {
041b39d2 73 debugln!("BashGen::all_subcommands;");
8bb4bdeb
XL
74 let mut subcmds = String::new();
75 let scs = completions::all_subcommand_names(self.p);
76
77 for sc in &scs {
78 subcmds = format!("{}
79 {name})
041b39d2 80 cmd+=\"__{name}\"
8bb4bdeb
XL
81 ;;",
82 subcmds,
041b39d2 83 name = sc.replace("-", "__"));
8bb4bdeb
XL
84 }
85
86 subcmds
87 }
88
89 fn subcommand_details(&self) -> String {
041b39d2 90 debugln!("BashGen::subcommand_details;");
8bb4bdeb
XL
91 let mut subcmd_dets = String::new();
92 let mut scs = completions::get_all_subcommand_paths(self.p, true);
93 scs.sort();
94 scs.dedup();
95
96 for sc in &scs {
97 subcmd_dets = format!("{}
98 {subcmd})
99 opts=\"{sc_opts}\"
100 if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then
101 COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
102 return 0
103 fi
104 case \"${{prev}}\" in
105 {opts_details}
106 *)
107 COMPREPLY=()
108 ;;
109 esac
110 COMPREPLY=( $(compgen -W \"${{opts}}\" -- ${{cur}}) )
111 return 0
112 ;;",
113 subcmd_dets,
041b39d2 114 subcmd = sc.replace("-", "__"),
8bb4bdeb 115 sc_opts = self.all_options_for_path(&*sc),
041b39d2 116 level = sc.split("__").map(|_| 1).fold(0, |acc, n| acc + n),
8bb4bdeb
XL
117 opts_details = self.option_details_for_path(&*sc));
118 }
119
120 subcmd_dets
121 }
122
123 fn option_details_for_path(&self, path: &str) -> String {
041b39d2 124 debugln!("BashGen::option_details_for_path: path={}", path);
8bb4bdeb 125 let mut p = self.p;
041b39d2
XL
126 for sc in path.split("__").skip(1) {
127 debugln!("BashGen::option_details_for_path:iter: sc={}", sc);
128 p = &find_subcmd!(p, sc).unwrap().p;
8bb4bdeb
XL
129 }
130 let mut opts = String::new();
131 for o in p.opts() {
132 if let Some(l) = o.s.long {
133 opts = format!("{}
134 --{})
135 COMPREPLY=({})
136 return 0
137 ;;",
138 opts,
139 l,
140 self.vals_for(o));
141 }
142 if let Some(s) = o.s.short {
143 opts = format!("{}
144 -{})
145 COMPREPLY=({})
146 return 0
147 ;;",
148 opts,
149 s,
150 self.vals_for(o));
151 }
152 }
153 opts
154 }
155
156 fn vals_for(&self, o: &OptBuilder) -> String {
041b39d2 157 debugln!("BashGen::vals_for: o={}", o.b.name);
8bb4bdeb
XL
158 use args::AnyArg;
159 let mut ret = String::new();
160 let mut needs_quotes = true;
161 if let Some(vals) = o.possible_vals() {
162 needs_quotes = false;
163 ret = format!("$(compgen -W \"{}\" -- ${{cur}})", vals.join(" "));
164 } else if let Some(vec) = o.val_names() {
165 let mut it = vec.iter().peekable();
166 while let Some((_, val)) = it.next() {
167 ret = format!("{}<{}>{}",
168 ret,
169 val,
170 if it.peek().is_some() { " " } else { "" });
171 }
172 let num = vec.len();
173 if o.is_set(ArgSettings::Multiple) && num == 1 {
174 ret = format!("{}...", ret);
175 }
176 } else if let Some(num) = o.num_vals() {
177 let mut it = (0..num).peekable();
178 while let Some(_) = it.next() {
179 ret = format!("{}<{}>{}",
180 ret,
181 o.name(),
182 if it.peek().is_some() { " " } else { "" });
183 }
184 if o.is_set(ArgSettings::Multiple) && num == 1 {
185 ret = format!("{}...", ret);
186 }
187 } else {
188 ret = format!("<{}>", o.name());
189 if o.is_set(ArgSettings::Multiple) {
190 ret = format!("{}...", ret);
191 }
192 }
193 if needs_quotes {
194 ret = format!("\"{}\"", ret);
195 }
196 ret
197 }
198 fn all_options_for_path(&self, path: &str) -> String {
041b39d2 199 debugln!("BashGen::all_options_for_path: path={}", path);
8bb4bdeb 200 let mut p = self.p;
041b39d2
XL
201 for sc in path.split("__").skip(1) {
202 debugln!("BashGen::all_options_for_path:iter: sc={}", sc);
203 p = &find_subcmd!(p, sc).unwrap().p;
8bb4bdeb 204 }
041b39d2 205 let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s));
8bb4bdeb
XL
206 opts = format!("{} {}",
207 opts,
041b39d2 208 longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
8bb4bdeb
XL
209 opts = format!("{} {}",
210 opts,
211 p.positionals
212 .values()
213 .fold(String::new(), |acc, p| format!("{} {}", acc, p)));
214 opts = format!("{} {}",
215 opts,
216 p.subcommands
217 .iter()
218 .fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name)));
219 for sc in &p.subcommands {
220 if let Some(ref aliases) = sc.p.meta.aliases {
221 opts = format!("{} {}",
222 opts,
223 aliases.iter()
224 .map(|&(n, _)| n)
225 .fold(String::new(), |acc, a| format!("{} {}", acc, a)));
226 }
227 }
228 opts
229 }
230}