Repository: clap-rs/clap
Pull request #5646 (2024-08-09 20:49:57)

feat(clap_complete): Add support for Powershell
<!--
Thanks for helping out!

Please link the appropriate issue from your PR.

If you don't have an issue, we'd recommend starting with one first so the PR can focus on the
implementation (unless its an obvious bug or documentation fix that will have
little conversation).
-->



Patch:
diff --git a/clap_complete/src/dynamic/shells/mod.rs b/clap_complete/src/dynamic/shells/mod.rs
index 8460a44a..713f144d 100644
--- a/clap_complete/src/dynamic/shells/mod.rs
+++ b/clap_complete/src/dynamic/shells/mod.rs
@@ -3,12 +3,14 @@
 mod bash;
 mod elvish;
 mod fish;
+mod powershell;
 mod shell;
 mod zsh;
 
 pub use bash::*;
 pub use elvish::*;
 pub use fish::*;
+pub use powershell::*;
 pub use shell::*;
 pub use zsh::*;
 
diff --git a/clap_complete/src/dynamic/shells/powershell.rs b/clap_complete/src/dynamic/shells/powershell.rs
new file mode 100644
index 00000000..32cd0098
--- /dev/null
+++ b/clap_complete/src/dynamic/shells/powershell.rs
@@ -0,0 +1,69 @@
+/// Completion support for Powershell
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct Powershell;
+
+impl crate::dynamic::shells::ShellCompleter for Powershell {
+    fn file_name(&self, name: &str) -> String {
+        format!("{name}.ps1")
+    }
+
+    fn write_registration(
+        &self,
+        _name: &str,
+        bin: &str,
+        completer: &str,
+        buf: &mut dyn std::io::Write,
+    ) -> Result<(), std::io::Error> {
+        let bin = shlex::try_quote(bin).unwrap_or(std::borrow::Cow::Borrowed(bin));
+        let completer =
+            shlex::try_quote(completer).unwrap_or(std::borrow::Cow::Borrowed(completer));
+
+        writeln!(
+            buf,
+            r#"
+Register-ArgumentCompleter -Native -CommandName {bin} -ScriptBlock {{
+    param($wordToComplete, $commandAst, $cursorPosition)
+
+    $results = Invoke-Expression "&{completer} complete --shell powershell -- $($commandAst.ToString())";
+    $results | ForEach-Object {{
+        $split = $_.Split("`t");
+        $cmd = $split[0];
+
+        if ($split.Length -eq 2) {{
+            $help = $split[1];
+        }}
+        else {{
+            $help = $split[0];
+        }}
+        
+        [System.Management.Automation.CompletionResult]::new($cmd, $cmd, 'ParameterValue', $help)
+    }}
+}};
+        "#
+        )
+    }
+
+    fn write_complete(
+        &self,
+        cmd: &mut clap::Command,
+        args: Vec<std::ffi::OsString>,
+        current_dir: Option<&std::path::Path>,
+        buf: &mut dyn std::io::Write,
+    ) -> Result<(), std::io::Error> {
+        let index = args.len() - 1;
+        let completions = crate::dynamic::complete(cmd, args, index, current_dir)?;
+
+        for candidate in completions {
+            write!(buf, "{}", candidate.get_content().to_string_lossy())?;
+            if let Some(help) = candidate.get_help() {
+                write!(
+                    buf,
+                    "\t{}",
+                    help.to_string().lines().next().unwrap_or_default()
+                )?;
+            }
+            writeln!(buf)?;
+        }
+        Ok(())
+    }
+}
diff --git a/clap_complete/src/dynamic/shells/shell.rs b/clap_complete/src/dynamic/shells/shell.rs
index b3bd28c7..874589f8 100644
--- a/clap_complete/src/dynamic/shells/shell.rs
+++ b/clap_complete/src/dynamic/shells/shell.rs
@@ -16,6 +16,8 @@ pub enum Shell {
     Zsh,
     /// Elf `SHell` (elvish)
     Elvish,
+    /// Powerful `SHell` (powershel)
+    Powershell,
 }
 
 impl Display for Shell {
@@ -43,7 +45,13 @@ impl FromStr for Shell {
 // Hand-rolled so it can work even when `derive` feature is disabled
 impl ValueEnum for Shell {
     fn value_variants<'a>() -> &'a [Self] {
-        &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::Elvish]
+        &[
+            Shell::Bash,
+            Shell::Fish,
+            Shell::Zsh,
+            Shell::Elvish,
+            Shell::Powershell,
+        ]
     }
 
     fn to_possible_value(&self) -> Option<PossibleValue> {
@@ -52,6 +60,7 @@ impl ValueEnum for Shell {
             Shell::Fish => PossibleValue::new("fish"),
             Shell::Zsh => PossibleValue::new("zsh"),
             Shell::Elvish => PossibleValue::new("elvish"),
+            Shell::Powershell => PossibleValue::new("powershell"),
         })
     }
 }
@@ -63,6 +72,7 @@ impl Shell {
             Self::Fish => &super::Fish,
             Self::Zsh => &super::Zsh,
             Self::Elvish => &super::Elvish,
+            Self::Powershell => &super::Powershell,
         }
     }
 }


Test patch:
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
index c552413c..e6dde351 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
@@ -245,7 +245,7 @@ _exhaustive() {
             fi
             case "${prev}" in
                 --shell)
-                    COMPREPLY=($(compgen -W "bash fish zsh elvish" -- "${cur}"))
+                    COMPREPLY=($(compgen -W "bash fish zsh elvish powershell" -- "${cur}"))
                     return 0
                     ;;
                 --register)
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish b/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish
index d371096e..1b4b9bd7 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish
@@ -136,7 +136,7 @@ complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l email -r
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s h -l help -d 'Print help'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s V -l version -d 'Print version'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash\t'',fish\t'',zsh\t'',elvish\t''}"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash\t'',fish\t'',zsh\t'',elvish\t'',powershell\t''}"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -l register -d 'Path to write completion-registration to' -r -F
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -s h -l help -d 'Print help (see more with \'--help\')'
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/powershell/powershell/Microsoft.PowerShell_profile.ps1 b/clap_complete/tests/snapshots/home/static/exhaustive/powershell/powershell/Microsoft.PowerShell_profile.ps1
new file mode 100644
index 00000000..685831f2
--- /dev/null
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/powershell/powershell/Microsoft.PowerShell_profile.ps1
@@ -0,0 +1,365 @@
+
+using namespace System.Management.Automation
+using namespace System.Management.Automation.Language
+
+Register-ArgumentCompleter -Native -CommandName 'exhaustive' -ScriptBlock {
+    param($wordToComplete, $commandAst, $cursorPosition)
+
+    $commandElements = $commandAst.CommandElements
+    $command = @(
+        'exhaustive'
+        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('-') -or
+                $element.Value -eq $wordToComplete) {
+                break
+        }
+        $element.Value
+    }) -join ';'
+
+    $completions = @(switch ($command) {
+        'exhaustive' {
+            [CompletionResult]::new('--generate', 'generate', [CompletionResultType]::ParameterName, 'generate')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('action', 'action', [CompletionResultType]::ParameterValue, 'action')
+            [CompletionResult]::new('quote', 'quote', [CompletionResultType]::ParameterValue, 'quote')
+            [CompletionResult]::new('value', 'value', [CompletionResultType]::ParameterValue, 'value')
+            [CompletionResult]::new('pacman', 'pacman', [CompletionResultType]::ParameterValue, 'pacman')
+            [CompletionResult]::new('last', 'last', [CompletionResultType]::ParameterValue, 'last')
+            [CompletionResult]::new('alias', 'alias', [CompletionResultType]::ParameterValue, 'alias')
+            [CompletionResult]::new('hint', 'hint', [CompletionResultType]::ParameterValue, 'hint')
+            [CompletionResult]::new('complete', 'complete', [CompletionResultType]::ParameterValue, 'Register shell completions for this program')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'exhaustive;action' {
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'value')
+            [CompletionResult]::new('--choice', 'choice', [CompletionResultType]::ParameterName, 'enum')
+            [CompletionResult]::new('--set-true', 'set-true', [CompletionResultType]::ParameterName, 'bool')
+            [CompletionResult]::new('--count', 'count', [CompletionResultType]::ParameterName, 'number')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote' {
+            [CompletionResult]::new('--choice', 'choice', [CompletionResultType]::ParameterName, 'choice')
+            [CompletionResult]::new('--single-quotes', 'single-quotes', [CompletionResultType]::ParameterName, 'Can be ''always'', ''auto'', or ''never''')
+            [CompletionResult]::new('--double-quotes', 'double-quotes', [CompletionResultType]::ParameterName, 'Can be "always", "auto", or "never"')
+            [CompletionResult]::new('--backticks', 'backticks', [CompletionResultType]::ParameterName, 'For more information see `echo test`')
+            [CompletionResult]::new('--backslash', 'backslash', [CompletionResultType]::ParameterName, 'Avoid ''\n''')
+            [CompletionResult]::new('--brackets', 'brackets', [CompletionResultType]::ParameterName, 'List packages [filter]')
+            [CompletionResult]::new('--expansions', 'expansions', [CompletionResultType]::ParameterName, 'Execute the shell command with $SHELL')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('cmd-single-quotes', 'cmd-single-quotes', [CompletionResultType]::ParameterValue, 'Can be ''always'', ''auto'', or ''never''')
+            [CompletionResult]::new('cmd-double-quotes', 'cmd-double-quotes', [CompletionResultType]::ParameterValue, 'Can be "always", "auto", or "never"')
+            [CompletionResult]::new('cmd-backticks', 'cmd-backticks', [CompletionResultType]::ParameterValue, 'For more information see `echo test`')
+            [CompletionResult]::new('cmd-backslash', 'cmd-backslash', [CompletionResultType]::ParameterValue, 'Avoid ''\n''')
+            [CompletionResult]::new('cmd-brackets', 'cmd-brackets', [CompletionResultType]::ParameterValue, 'List packages [filter]')
+            [CompletionResult]::new('cmd-expansions', 'cmd-expansions', [CompletionResultType]::ParameterValue, 'Execute the shell command with $SHELL')
+            [CompletionResult]::new('escape-help', 'escape-help', [CompletionResultType]::ParameterValue, '\tab	"'' New Line')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'exhaustive;quote;cmd-single-quotes' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;cmd-double-quotes' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;cmd-backticks' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;cmd-backslash' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;cmd-brackets' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;cmd-expansions' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;escape-help' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;quote;help' {
+            [CompletionResult]::new('cmd-single-quotes', 'cmd-single-quotes', [CompletionResultType]::ParameterValue, 'Can be ''always'', ''auto'', or ''never''')
+            [CompletionResult]::new('cmd-double-quotes', 'cmd-double-quotes', [CompletionResultType]::ParameterValue, 'Can be "always", "auto", or "never"')
+            [CompletionResult]::new('cmd-backticks', 'cmd-backticks', [CompletionResultType]::ParameterValue, 'For more information see `echo test`')
+            [CompletionResult]::new('cmd-backslash', 'cmd-backslash', [CompletionResultType]::ParameterValue, 'Avoid ''\n''')
+            [CompletionResult]::new('cmd-brackets', 'cmd-brackets', [CompletionResultType]::ParameterValue, 'List packages [filter]')
+            [CompletionResult]::new('cmd-expansions', 'cmd-expansions', [CompletionResultType]::ParameterValue, 'Execute the shell command with $SHELL')
+            [CompletionResult]::new('escape-help', 'escape-help', [CompletionResultType]::ParameterValue, '\tab	"'' New Line')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'exhaustive;quote;help;cmd-single-quotes' {
+            break
+        }
+        'exhaustive;quote;help;cmd-double-quotes' {
+            break
+        }
+        'exhaustive;quote;help;cmd-backticks' {
+            break
+        }
+        'exhaustive;quote;help;cmd-backslash' {
+            break
+        }
+        'exhaustive;quote;help;cmd-brackets' {
+            break
+        }
+        'exhaustive;quote;help;cmd-expansions' {
+            break
+        }
+        'exhaustive;quote;help;escape-help' {
+            break
+        }
+        'exhaustive;quote;help;help' {
+            break
+        }
+        'exhaustive;value' {
+            [CompletionResult]::new('--delim', 'delim', [CompletionResultType]::ParameterName, 'delim')
+            [CompletionResult]::new('--tuple', 'tuple', [CompletionResultType]::ParameterName, 'tuple')
+            [CompletionResult]::new('--require-eq', 'require-eq', [CompletionResultType]::ParameterName, 'require-eq')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;pacman' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('one', 'one', [CompletionResultType]::ParameterValue, 'one')
+            [CompletionResult]::new('two', 'two', [CompletionResultType]::ParameterValue, 'two')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'exhaustive;pacman;one' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;pacman;two' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;pacman;help' {
+            [CompletionResult]::new('one', 'one', [CompletionResultType]::ParameterValue, 'one')
+            [CompletionResult]::new('two', 'two', [CompletionResultType]::ParameterValue, 'two')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'exhaustive;pacman;help;one' {
+            break
+        }
+        'exhaustive;pacman;help;two' {
+            break
+        }
+        'exhaustive;pacman;help;help' {
+            break
+        }
+        'exhaustive;last' {
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;alias' {
+            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'cmd option')
+            [CompletionResult]::new('-O', 'O ', [CompletionResultType]::ParameterName, 'cmd option')
+            [CompletionResult]::new('--option', 'option', [CompletionResultType]::ParameterName, 'cmd option')
+            [CompletionResult]::new('--opt', 'opt', [CompletionResultType]::ParameterName, 'cmd option')
+            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'cmd flag')
+            [CompletionResult]::new('-F', 'F ', [CompletionResultType]::ParameterName, 'cmd flag')
+            [CompletionResult]::new('--flag', 'flag', [CompletionResultType]::ParameterName, 'cmd flag')
+            [CompletionResult]::new('--flg', 'flg', [CompletionResultType]::ParameterName, 'cmd flag')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;hint' {
+            [CompletionResult]::new('--choice', 'choice', [CompletionResultType]::ParameterName, 'choice')
+            [CompletionResult]::new('--unknown', 'unknown', [CompletionResultType]::ParameterName, 'unknown')
+            [CompletionResult]::new('--other', 'other', [CompletionResultType]::ParameterName, 'other')
+            [CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'p')
+            [CompletionResult]::new('--path', 'path', [CompletionResultType]::ParameterName, 'path')
+            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'f')
+            [CompletionResult]::new('--file', 'file', [CompletionResultType]::ParameterName, 'file')
+            [CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'd')
+            [CompletionResult]::new('--dir', 'dir', [CompletionResultType]::ParameterName, 'dir')
+            [CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'e')
+            [CompletionResult]::new('--exe', 'exe', [CompletionResultType]::ParameterName, 'exe')
+            [CompletionResult]::new('--cmd-name', 'cmd-name', [CompletionResultType]::ParameterName, 'cmd-name')
+            [CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'c')
+            [CompletionResult]::new('--cmd', 'cmd', [CompletionResultType]::ParameterName, 'cmd')
+            [CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'u')
+            [CompletionResult]::new('--user', 'user', [CompletionResultType]::ParameterName, 'user')
+            [CompletionResult]::new('-H', 'H ', [CompletionResultType]::ParameterName, 'H')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host')
+            [CompletionResult]::new('--url', 'url', [CompletionResultType]::ParameterName, 'url')
+            [CompletionResult]::new('--email', 'email', [CompletionResultType]::ParameterName, 'email')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;complete' {
+            [CompletionResult]::new('--shell', 'shell', [CompletionResultType]::ParameterName, 'Specify shell to complete for')
+            [CompletionResult]::new('--register', 'register', [CompletionResultType]::ParameterName, 'Path to write completion-registration to')
+            [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, 'everywhere')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
+        'exhaustive;help' {
+            [CompletionResult]::new('action', 'action', [CompletionResultType]::ParameterValue, 'action')
+            [CompletionResult]::new('quote', 'quote', [CompletionResultType]::ParameterValue, 'quote')
+            [CompletionResult]::new('value', 'value', [CompletionResultType]::ParameterValue, 'value')
+            [CompletionResult]::new('pacman', 'pacman', [CompletionResultType]::ParameterValue, 'pacman')
+            [CompletionResult]::new('last', 'last', [CompletionResultType]::ParameterValue, 'last')
+            [CompletionResult]::new('alias', 'alias', [CompletionResultType]::ParameterValue, 'alias')
+            [CompletionResult]::new('hint', 'hint', [CompletionResultType]::ParameterValue, 'hint')
+            [CompletionResult]::new('complete', 'complete', [CompletionResultType]::ParameterValue, 'Register shell completions for this program')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'exhaustive;help;action' {
+            break
+        }
+        'exhaustive;help;quote' {
+            [CompletionResult]::new('cmd-single-quotes', 'cmd-single-quotes', [CompletionResultType]::ParameterValue, 'Can be ''always'', ''auto'', or ''never''')
+            [CompletionResult]::new('cmd-double-quotes', 'cmd-double-quotes', [CompletionResultType]::ParameterValue, 'Can be "always", "auto", or "never"')
+            [CompletionResult]::new('cmd-backticks', 'cmd-backticks', [CompletionResultType]::ParameterValue, 'For more information see `echo test`')
+            [CompletionResult]::new('cmd-backslash', 'cmd-backslash', [CompletionResultType]::ParameterValue, 'Avoid ''\n''')
+            [CompletionResult]::new('cmd-brackets', 'cmd-brackets', [CompletionResultType]::ParameterValue, 'List packages [filter]')
+            [CompletionResult]::new('cmd-expansions', 'cmd-expansions', [CompletionResultType]::ParameterValue, 'Execute the shell command with $SHELL')
+            [CompletionResult]::new('escape-help', 'escape-help', [CompletionResultType]::ParameterValue, '\tab	"'' New Line')
+            break
+        }
+        'exhaustive;help;quote;cmd-single-quotes' {
+            break
+        }
+        'exhaustive;help;quote;cmd-double-quotes' {
+            break
+        }
+        'exhaustive;help;quote;cmd-backticks' {
+            break
+        }
+        'exhaustive;help;quote;cmd-backslash' {
+            break
+        }
+        'exhaustive;help;quote;cmd-brackets' {
+            break
+        }
+        'exhaustive;help;quote;cmd-expansions' {
+            break
+        }
+        'exhaustive;help;quote;escape-help' {
+            break
+        }
+        'exhaustive;help;value' {
+            break
+        }
+        'exhaustive;help;pacman' {
+            [CompletionResult]::new('one', 'one', [CompletionResultType]::ParameterValue, 'one')
+            [CompletionResult]::new('two', 'two', [CompletionResultType]::ParameterValue, 'two')
+            break
+        }
+        'exhaustive;help;pacman;one' {
+            break
+        }
+        'exhaustive;help;pacman;two' {
+            break
+        }
+        'exhaustive;help;last' {
+            break
+        }
+        'exhaustive;help;alias' {
+            break
+        }
+        'exhaustive;help;hint' {
+            break
+        }
+        'exhaustive;help;complete' {
+            break
+        }
+        'exhaustive;help;help' {
+            break
+        }
+    })
+
+    $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
+        Sort-Object -Property ListItemText
+}
+function prompt {
+    '% '
+}
+Set-PSReadLineOption -PredictionSource None
\ No newline at end of file
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
index 67fe3c40..9683cac4 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
@@ -325,7 +325,7 @@ _arguments "${_arguments_options[@]}" : \
 ;;
 (complete)
 _arguments "${_arguments_options[@]}" : \
-'--shell=[Specify shell to complete for]:SHELL:(bash fish zsh elvish)' \
+'--shell=[Specify shell to complete for]:SHELL:(bash fish zsh elvish powershell)' \
 '--register=[Path to write completion-registration to]:REGISTER:_files' \
 '--global[everywhere]' \
 '-h[Print help (see more with '\''--help'\'')]' \