Allow user to add completion for powershell alias

When a user has an alias in powershell, she will need to register that
alias for completion.  To make that possible, we store the completion
logic into a scriptblock variable which can easily be accessed by the
user to register aliases.

For example, if the user defines an alias for `helm`:
   PS> sal h helm
she will need to register the alias like so:
   PS> Register-ArgumentCompleter -CommandName 'h' -ScriptBlock $__helmCompleterBlock

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
This commit is contained in:
Marc Khouzam 2022-01-11 08:46:36 -05:00 committed by Marc Khouzam
parent a281c8b47b
commit 6ba7ebbc1f
2 changed files with 32 additions and 9 deletions

View file

@ -22,9 +22,15 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"strings"
) )
func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) { func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) {
// Variables should not contain a '-' or ':' character
nameForVar := name
nameForVar = strings.Replace(nameForVar, "-", "_", -1)
nameForVar = strings.Replace(nameForVar, ":", "_", -1)
compCmd := ShellCompRequestCmd compCmd := ShellCompRequestCmd
if !includeDesc { if !includeDesc {
compCmd = ShellCompNoDescRequestCmd compCmd = ShellCompNoDescRequestCmd
@ -41,7 +47,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
`+" $_ -replace '\\s|#|@|\\$|;|,|''|\\{|\\}|\\(|\\)|\"|`|\\||<|>|&','`$&'"+` `+" $_ -replace '\\s|#|@|\\$|;|,|''|\\{|\\}|\\(|\\)|\"|`|\\||<|>|&','`$&'"+`
} }
Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { [scriptblock]$__%[2]sCompleterBlock = {
param( param(
$WordToComplete, $WordToComplete,
$CommandAst, $CommandAst,
@ -66,17 +72,17 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
} }
__%[1]s_debug "Truncated command: $Command" __%[1]s_debug "Truncated command: $Command"
$ShellCompDirectiveError=%[3]d $ShellCompDirectiveError=%[4]d
$ShellCompDirectiveNoSpace=%[4]d $ShellCompDirectiveNoSpace=%[5]d
$ShellCompDirectiveNoFileComp=%[5]d $ShellCompDirectiveNoFileComp=%[6]d
$ShellCompDirectiveFilterFileExt=%[6]d $ShellCompDirectiveFilterFileExt=%[7]d
$ShellCompDirectiveFilterDirs=%[7]d $ShellCompDirectiveFilterDirs=%[8]d
# Prepare the command to request completions for the program. # Prepare the command to request completions for the program.
# Split the command at the first space to separate the program and arguments. # Split the command at the first space to separate the program and arguments.
$Program,$Arguments = $Command.Split(" ",2) $Program,$Arguments = $Command.Split(" ",2)
$RequestComp="$Program %[2]s $Arguments" $RequestComp="$Program %[3]s $Arguments"
__%[1]s_debug "RequestComp: $RequestComp" __%[1]s_debug "RequestComp: $RequestComp"
# we cannot use $WordToComplete because it # we cannot use $WordToComplete because it
@ -106,7 +112,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
__%[1]s_debug "Calling $RequestComp" __%[1]s_debug "Calling $RequestComp"
# First disable ActiveHelp which is not supported for Powershell # First disable ActiveHelp which is not supported for Powershell
$env:%[8]s=0 $env:%[9]s=0
#call the command store the output in $out and redirect stderr and stdout to null #call the command store the output in $out and redirect stderr and stdout to null
# $Out is an array contains each line per element # $Out is an array contains each line per element
@ -257,7 +263,9 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
} }
} }
`, name, compCmd,
Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock
`, name, nameForVar, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
} }

View file

@ -535,6 +535,21 @@ search for a keyword in charts
$ helm s[tab] $ helm s[tab]
search show status search show status
``` ```
### Aliases
You can also configure `powershell` aliases for your program and they will also support completions.
```
$ sal aliasname origcommand
$ Register-ArgumentCompleter -CommandName 'aliasname' -ScriptBlock $__origcommandCompleterBlock
# and now when you run `aliasname` completion will make
# suggestions as it did for `origcommand`.
$ aliasname <tab>
completion firstcommand secondcommand
```
The name of the completer block variable is of the form `$__<programName>CompleterBlock` where every `-` and `:` in the program name have been replaced with `_`, to respect powershell naming syntax.
### Limitations ### Limitations