123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- // PowerShell completions are based on the amazing work from clap:
- // https://github.com/clap-rs/clap/blob/3294d18efe5f264d12c9035f404c7d189d4824e1/src/completions/powershell.rs
- //
- // The generated scripts require PowerShell v5.0+ (which comes Windows 10, but
- // can be downloaded separately for windows 7 or 8.1).
- package cobra
- import (
- "bytes"
- "fmt"
- "io"
- "os"
- "strings"
- "github.com/spf13/pflag"
- )
- var powerShellCompletionTemplate = `using namespace System.Management.Automation
- using namespace System.Management.Automation.Language
- Register-ArgumentCompleter -Native -CommandName '%s' -ScriptBlock {
- param($wordToComplete, $commandAst, $cursorPosition)
- $commandElements = $commandAst.CommandElements
- $command = @(
- '%s'
- 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) {%s
- })
- $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
- Sort-Object -Property ListItemText
- }`
- func generatePowerShellSubcommandCases(out io.Writer, cmd *Command, previousCommandName string) {
- var cmdName string
- if previousCommandName == "" {
- cmdName = cmd.Name()
- } else {
- cmdName = fmt.Sprintf("%s;%s", previousCommandName, cmd.Name())
- }
- fmt.Fprintf(out, "\n '%s' {", cmdName)
- cmd.Flags().VisitAll(func(flag *pflag.Flag) {
- if nonCompletableFlag(flag) {
- return
- }
- usage := escapeStringForPowerShell(flag.Usage)
- if len(flag.Shorthand) > 0 {
- fmt.Fprintf(out, "\n [CompletionResult]::new('-%s', '%s', [CompletionResultType]::ParameterName, '%s')", flag.Shorthand, flag.Shorthand, usage)
- }
- fmt.Fprintf(out, "\n [CompletionResult]::new('--%s', '%s', [CompletionResultType]::ParameterName, '%s')", flag.Name, flag.Name, usage)
- })
- for _, subCmd := range cmd.Commands() {
- usage := escapeStringForPowerShell(subCmd.Short)
- fmt.Fprintf(out, "\n [CompletionResult]::new('%s', '%s', [CompletionResultType]::ParameterValue, '%s')", subCmd.Name(), subCmd.Name(), usage)
- }
- fmt.Fprint(out, "\n break\n }")
- for _, subCmd := range cmd.Commands() {
- generatePowerShellSubcommandCases(out, subCmd, cmdName)
- }
- }
- func escapeStringForPowerShell(s string) string {
- return strings.Replace(s, "'", "''", -1)
- }
- // GenPowerShellCompletion generates PowerShell completion file and writes to the passed writer.
- func (c *Command) GenPowerShellCompletion(w io.Writer) error {
- buf := new(bytes.Buffer)
- var subCommandCases bytes.Buffer
- generatePowerShellSubcommandCases(&subCommandCases, c, "")
- fmt.Fprintf(buf, powerShellCompletionTemplate, c.Name(), c.Name(), subCommandCases.String())
- _, err := buf.WriteTo(w)
- return err
- }
- // GenPowerShellCompletionFile generates PowerShell completion file.
- func (c *Command) GenPowerShellCompletionFile(filename string) error {
- outFile, err := os.Create(filename)
- if err != nil {
- return err
- }
- defer outFile.Close()
- return c.GenPowerShellCompletion(outFile)
- }
|