clap/completions/
powershell.rs1use std::io::Write;
3
4use app::parser::Parser;
6use INTERNAL_ERROR_MSG;
7
8pub struct PowerShellGen<'a, 'b>
9where
10 'a: 'b,
11{
12 p: &'b Parser<'a, 'b>,
13}
14
15impl<'a, 'b> PowerShellGen<'a, 'b> {
16 pub fn new(p: &'b Parser<'a, 'b>) -> Self { PowerShellGen { p: p } }
17
18 pub fn generate_to<W: Write>(&self, buf: &mut W) {
19 let bin_name = self.p.meta.bin_name.as_ref().unwrap();
20
21 let mut names = vec![];
22 let subcommands_cases =
23 generate_inner(self.p, "", &mut names);
24
25 let result = format!(r#"
26using namespace System.Management.Automation
27using namespace System.Management.Automation.Language
28
29Register-ArgumentCompleter -Native -CommandName '{bin_name}' -ScriptBlock {{
30 param($wordToComplete, $commandAst, $cursorPosition)
31
32 $commandElements = $commandAst.CommandElements
33 $command = @(
34 '{bin_name}'
35 for ($i = 1; $i -lt $commandElements.Count; $i++) {{
36 $element = $commandElements[$i]
37 if ($element -isnot [StringConstantExpressionAst] -or
38 $element.StringConstantType -ne [StringConstantType]::BareWord -or
39 $element.Value.StartsWith('-')) {{
40 break
41 }}
42 $element.Value
43 }}) -join ';'
44
45 $completions = @(switch ($command) {{{subcommands_cases}
46 }})
47
48 $completions.Where{{ $_.CompletionText -like "$wordToComplete*" }} |
49 Sort-Object -Property ListItemText
50}}
51"#,
52 bin_name = bin_name,
53 subcommands_cases = subcommands_cases
54 );
55
56 w!(buf, result.as_bytes());
57 }
58}
59
60fn escape_string(string: &str) -> String { string.replace("'", "''") }
62
63fn get_tooltip<T : ToString>(help: Option<&str>, data: T) -> String {
64 match help {
65 Some(help) => escape_string(help),
66 _ => data.to_string()
67 }
68}
69
70fn generate_inner<'a, 'b, 'p>(
71 p: &'p Parser<'a, 'b>,
72 previous_command_name: &str,
73 names: &mut Vec<&'p str>,
74) -> String {
75 debugln!("PowerShellGen::generate_inner;");
76 let command_name = if previous_command_name.is_empty() {
77 p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG).clone()
78 } else {
79 format!("{};{}", previous_command_name, &p.meta.name)
80 };
81
82 let mut completions = String::new();
83 let preamble = String::from("\n [CompletionResult]::new(");
84
85 for option in p.opts() {
86 if let Some(data) = option.s.short {
87 let tooltip = get_tooltip(option.b.help, data);
88 completions.push_str(&preamble);
89 completions.push_str(format!("'-{}', '{}', {}, '{}')",
90 data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
91 }
92 if let Some(data) = option.s.long {
93 let tooltip = get_tooltip(option.b.help, data);
94 completions.push_str(&preamble);
95 completions.push_str(format!("'--{}', '{}', {}, '{}')",
96 data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
97 }
98 }
99
100 for flag in p.flags() {
101 if let Some(data) = flag.s.short {
102 let tooltip = get_tooltip(flag.b.help, data);
103 completions.push_str(&preamble);
104 completions.push_str(format!("'-{}', '{}', {}, '{}')",
105 data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
106 }
107 if let Some(data) = flag.s.long {
108 let tooltip = get_tooltip(flag.b.help, data);
109 completions.push_str(&preamble);
110 completions.push_str(format!("'--{}', '{}', {}, '{}')",
111 data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
112 }
113 }
114
115 for subcommand in &p.subcommands {
116 let data = &subcommand.p.meta.name;
117 let tooltip = get_tooltip(subcommand.p.meta.about, data);
118 completions.push_str(&preamble);
119 completions.push_str(format!("'{}', '{}', {}, '{}')",
120 data, data, "[CompletionResultType]::ParameterValue", tooltip).as_str());
121 }
122
123 let mut subcommands_cases = format!(
124 r"
125 '{}' {{{}
126 break
127 }}",
128 &command_name,
129 completions
130 );
131
132 for subcommand in &p.subcommands {
133 let subcommand_subcommands_cases =
134 generate_inner(&subcommand.p, &command_name, names);
135 subcommands_cases.push_str(&subcommand_subcommands_cases);
136 }
137
138 subcommands_cases
139}