]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | |
2 | // Std | |
3 | use std::io::Write; | |
4 | ||
5 | // Internal | |
6 | use app::parser::Parser; | |
7 | ||
8 | pub struct FishGen<'a, 'b> | |
9 | where 'a: 'b | |
10 | { | |
11 | p: &'b Parser<'a, 'b>, | |
12 | } | |
13 | ||
14 | impl<'a, 'b> FishGen<'a, 'b> { | |
15 | pub fn new(p: &'b Parser<'a, 'b>) -> Self { FishGen { p: p } } | |
16 | ||
17 | pub fn generate_to<W: Write>(&self, buf: &mut W) { | |
18 | let command = self.p.meta.bin_name.as_ref().unwrap(); | |
19 | ||
20 | // function to detect subcommand | |
21 | let detect_subcommand_function = r#"function __fish_using_command | |
22 | set cmd (commandline -opc) | |
23 | if [ (count $cmd) -eq (count $argv) ] | |
24 | for i in (seq (count $argv)) | |
25 | if [ $cmd[$i] != $argv[$i] ] | |
26 | return 1 | |
27 | end | |
28 | end | |
29 | return 0 | |
30 | end | |
31 | return 1 | |
32 | end | |
33 | ||
34 | "# | |
35 | .to_string(); | |
36 | ||
37 | let mut buffer = detect_subcommand_function; | |
38 | gen_fish_inner(command, self, &command.to_string(), &mut buffer); | |
39 | w!(buf, buffer.as_bytes()); | |
40 | } | |
41 | } | |
42 | ||
43 | fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buffer: &mut String) { | |
8bb4bdeb XL |
44 | // example : |
45 | // | |
46 | // complete | |
47 | // -c {command} | |
48 | // -d "{description}" | |
49 | // -s {short} | |
50 | // -l {long} | |
51 | // -a "{possible_arguments}" | |
52 | // -r # if require parameter | |
53 | // -f # don't use file completion | |
54 | // -n "__fish_using_command myprog subcmd1" # complete for command "myprog subcmd1" | |
55 | ||
56 | let basic_template = format!("complete -c {} -n \"__fish_using_command {}\"", | |
57 | root_command, | |
58 | parent_cmds); | |
59 | ||
60 | for option in comp_gen.p.opts() { | |
61 | let mut template = basic_template.clone(); | |
62 | if let Some(data) = option.s.short { | |
63 | template.push_str(format!(" -s {}", data).as_str()); | |
64 | } | |
65 | if let Some(data) = option.s.long { | |
66 | template.push_str(format!(" -l {}", data).as_str()); | |
67 | } | |
68 | if let Some(data) = option.b.help { | |
69 | template.push_str(format!(" -d \"{}\"", data).as_str()); | |
70 | } | |
71 | if let Some(ref data) = option.v.possible_vals { | |
72 | template.push_str(format!(" -r -f -a \"{}\"", data.join(" ")).as_str()); | |
73 | } | |
74 | buffer.push_str(template.as_str()); | |
75 | buffer.push_str("\n"); | |
76 | } | |
77 | ||
78 | for flag in comp_gen.p.flags() { | |
79 | let mut template = basic_template.clone(); | |
80 | if let Some(data) = flag.s.short { | |
81 | template.push_str(format!(" -s {}", data).as_str()); | |
82 | } | |
83 | if let Some(data) = flag.s.long { | |
84 | template.push_str(format!(" -l {}", data).as_str()); | |
85 | } | |
86 | if let Some(data) = flag.b.help { | |
87 | template.push_str(format!(" -d \"{}\"", data).as_str()); | |
88 | } | |
89 | buffer.push_str(template.as_str()); | |
90 | buffer.push_str("\n"); | |
91 | } | |
92 | ||
93 | for subcommand in &comp_gen.p.subcommands { | |
94 | let mut template = basic_template.clone(); | |
95 | template.push_str(" -f"); | |
96 | template.push_str(format!(" -a \"{}\"", &subcommand.p.meta.name).as_str()); | |
97 | buffer.push_str(template.as_str()); | |
98 | buffer.push_str("\n"); | |
99 | } | |
100 | ||
101 | // generate options of subcommands | |
102 | for subcommand in &comp_gen.p.subcommands { | |
103 | let sub_comp_gen = FishGen::new(&subcommand.p); | |
104 | // make new "parent_cmds" for different subcommands | |
105 | let mut sub_parent_cmds = parent_cmds.to_string(); | |
106 | if !sub_parent_cmds.is_empty() { | |
107 | sub_parent_cmds.push_str(" "); | |
108 | } | |
109 | sub_parent_cmds.push_str(&subcommand.p.meta.name); | |
110 | gen_fish_inner(root_command, &sub_comp_gen, &sub_parent_cmds, buffer); | |
111 | } | |
112 | } |