Skip to content

Commit

Permalink
feat(clap_complete): Add support for Powershell
Browse files Browse the repository at this point in the history
  • Loading branch information
shannmu authored and epage committed Aug 9, 2024
1 parent 7916e79 commit f9a87bf
Show file tree
Hide file tree
Showing 7 changed files with 450 additions and 4 deletions.
2 changes: 2 additions & 0 deletions clap_complete/src/dynamic/shells/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down
69 changes: 69 additions & 0 deletions clap_complete/src/dynamic/shells/powershell.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
}
12 changes: 11 additions & 1 deletion clap_complete/src/dynamic/shells/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub enum Shell {
Zsh,
/// Elf `SHell` (elvish)
Elvish,
/// Powerful `SHell` (powershel)
Powershell,
}

impl Display for Shell {
Expand Down Expand Up @@ -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> {
Expand All @@ -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"),
})
}
}
Expand All @@ -63,6 +72,7 @@ impl Shell {
Self::Fish => &super::Fish,
Self::Zsh => &super::Zsh,
Self::Elvish => &super::Elvish,
Self::Powershell => &super::Powershell,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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\')'
Expand Down
Loading

0 comments on commit f9a87bf

Please sign in to comment.