aboutsummaryrefslogtreecommitdiff
path: root/clap/src/completions/powershell.rs
diff options
context:
space:
mode:
Diffstat (limited to 'clap/src/completions/powershell.rs')
-rw-r--r--clap/src/completions/powershell.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/clap/src/completions/powershell.rs b/clap/src/completions/powershell.rs
new file mode 100644
index 0000000..9fc77c7
--- /dev/null
+++ b/clap/src/completions/powershell.rs
@@ -0,0 +1,139 @@
+// Std
+use std::io::Write;
+
+// Internal
+use app::parser::Parser;
+use INTERNAL_ERROR_MSG;
+
+pub struct PowerShellGen<'a, 'b>
+where
+ 'a: 'b,
+{
+ p: &'b Parser<'a, 'b>,
+}
+
+impl<'a, 'b> PowerShellGen<'a, 'b> {
+ pub fn new(p: &'b Parser<'a, 'b>) -> Self { PowerShellGen { p: p } }
+
+ pub fn generate_to<W: Write>(&self, buf: &mut W) {
+ let bin_name = self.p.meta.bin_name.as_ref().unwrap();
+
+ let mut names = vec![];
+ let subcommands_cases =
+ generate_inner(self.p, "", &mut names);
+
+ let result = format!(r#"
+using namespace System.Management.Automation
+using namespace System.Management.Automation.Language
+
+Register-ArgumentCompleter -Native -CommandName '{bin_name}' -ScriptBlock {{
+ param($wordToComplete, $commandAst, $cursorPosition)
+
+ $commandElements = $commandAst.CommandElements
+ $command = @(
+ '{bin_name}'
+ for ($i = 1; $i -lt $commandElements.Count; $i++) {{
+ $element = $commandElements[$i]
+ if ($element -isnot [StringConstantExpressionAst] -or
+ $element.StringConstantType -ne [StringConstantType]::BareWord -or
+ $element.Value.StartsWith('-')) {{
+ break
+ }}
+ $element.Value
+ }}) -join ';'
+
+ $completions = @(switch ($command) {{{subcommands_cases}
+ }})
+
+ $completions.Where{{ $_.CompletionText -like "$wordToComplete*" }} |
+ Sort-Object -Property ListItemText
+}}
+"#,
+ bin_name = bin_name,
+ subcommands_cases = subcommands_cases
+ );
+
+ w!(buf, result.as_bytes());
+ }
+}
+
+// Escape string inside single quotes
+fn escape_string(string: &str) -> String { string.replace("'", "''") }
+
+fn get_tooltip<T : ToString>(help: Option<&str>, data: T) -> String {
+ match help {
+ Some(help) => escape_string(help),
+ _ => data.to_string()
+ }
+}
+
+fn generate_inner<'a, 'b, 'p>(
+ p: &'p Parser<'a, 'b>,
+ previous_command_name: &str,
+ names: &mut Vec<&'p str>,
+) -> String {
+ debugln!("PowerShellGen::generate_inner;");
+ let command_name = if previous_command_name.is_empty() {
+ p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG).clone()
+ } else {
+ format!("{};{}", previous_command_name, &p.meta.name)
+ };
+
+ let mut completions = String::new();
+ let preamble = String::from("\n [CompletionResult]::new(");
+
+ for option in p.opts() {
+ if let Some(data) = option.s.short {
+ let tooltip = get_tooltip(option.b.help, data);
+ completions.push_str(&preamble);
+ completions.push_str(format!("'-{}', '{}', {}, '{}')",
+ data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
+ }
+ if let Some(data) = option.s.long {
+ let tooltip = get_tooltip(option.b.help, data);
+ completions.push_str(&preamble);
+ completions.push_str(format!("'--{}', '{}', {}, '{}')",
+ data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
+ }
+ }
+
+ for flag in p.flags() {
+ if let Some(data) = flag.s.short {
+ let tooltip = get_tooltip(flag.b.help, data);
+ completions.push_str(&preamble);
+ completions.push_str(format!("'-{}', '{}', {}, '{}')",
+ data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
+ }
+ if let Some(data) = flag.s.long {
+ let tooltip = get_tooltip(flag.b.help, data);
+ completions.push_str(&preamble);
+ completions.push_str(format!("'--{}', '{}', {}, '{}')",
+ data, data, "[CompletionResultType]::ParameterName", tooltip).as_str());
+ }
+ }
+
+ for subcommand in &p.subcommands {
+ let data = &subcommand.p.meta.name;
+ let tooltip = get_tooltip(subcommand.p.meta.about, data);
+ completions.push_str(&preamble);
+ completions.push_str(format!("'{}', '{}', {}, '{}')",
+ data, data, "[CompletionResultType]::ParameterValue", tooltip).as_str());
+ }
+
+ let mut subcommands_cases = format!(
+ r"
+ '{}' {{{}
+ break
+ }}",
+ &command_name,
+ completions
+ );
+
+ for subcommand in &p.subcommands {
+ let subcommand_subcommands_cases =
+ generate_inner(&subcommand.p, &command_name, names);
+ subcommands_cases.push_str(&subcommand_subcommands_cases);
+ }
+
+ subcommands_cases
+}