diff --git a/cli/cmd/prompt.go b/cli/cmd/prompt.go index 3a73e3be8947900c845602c4001b7ffe31f2f6c9..27d6ba966a1ef06a0e32986c228bfdf1a8439c4d 100644 --- a/cli/cmd/prompt.go +++ b/cli/cmd/prompt.go @@ -45,8 +45,6 @@ import ( "github.com/spf13/pflag" ) -var suggestions []prompt.Suggest - // PromptCompleter provides completion for a device type PromptCompleter struct { //NOTE: not too sure about this but for now it should be sufficient @@ -105,32 +103,28 @@ func executeFunc(s string) { } } -func flagVisitor(f *pflag.Flag) { - if !f.Hidden { - suggestions = append(suggestions, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage}) - } -} - func (pc *PromptCompleter) cstmCompleter(d prompt.Document) []prompt.Suggest { // Start with the cobra 'rootCmd' and walk through it // Reference: https://github.com/stromland/cobra-prompt currCmd := rootCmd - inputSplit := removeFlagsFromInputSlice(strings.Fields(d.CurrentLine())) - if c, _, err := currCmd.Find(inputSplit); err == nil { + inputSplit := strings.Fields(d.CurrentLine()) + inputSplitFiltered, inputFlags := filterFlagSlice(inputSplit) + if c, _, err := currCmd.Find(inputSplitFiltered); err == nil { currCmd = c } - return completionBasedOnCmd(pc, currCmd, inputSplit, d) + return completionBasedOnCmd(pc, currCmd, inputSplit, inputFlags, d) } -func removeFlagsFromInputSlice(input []string) []string { - r := []string{} +func filterFlagSlice(input []string) (commandSlice []string, flagSlice []string) { for _, in := range input { if !strings.HasPrefix(in, "--") { - r = append(r, in) + commandSlice = append(commandSlice, in) + } else { + flagSlice = append(flagSlice, strings.Split(in, "=")[0]) } } - return r + return commandSlice, flagSlice } func deviceGetCompletion(c *PromptCompleter, d prompt.Document, inputSplit []string) []prompt.Suggest { @@ -179,28 +173,28 @@ func deviceGetCompletion(c *PromptCompleter, d prompt.Document, inputSplit []str return []prompt.Suggest{} } -func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, loaded []prompt.Suggest) []prompt.Suggest { - suggestions = []prompt.Suggest{} - if len(loaded) > 0 { - suggestions = append(suggestions, loaded...) - } +func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, inputFlags []string, loaded []prompt.Suggest) []prompt.Suggest { if currCmd.HasAvailableFlags() { - // it would be possible to always show the inherited flags, but i think - // this is currently not necessary. - // currCmd.InheritedFlags().VisitAll(flagVisitor) - currCmd.LocalFlags().VisitAll(flagVisitor) + currCmd.LocalFlags().VisitAll( + func(f *pflag.Flag) { + if !f.Hidden && !sliceContains(inputFlags, "--"+f.Name) { + loaded = append(loaded, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage}) + } + }, + ) } for _, cmd := range currCmd.Commands() { - suggestions = append(suggestions, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short}) + loaded = append(loaded, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short}) } - return prompt.FilterHasPrefix(suggestions, d.GetWordBeforeCursor(), true) + + return prompt.FilterHasPrefix(loaded, d.GetWordBeforeCursor(), true) } -func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, d prompt.Document) []prompt.Suggest { +func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, inputFlags []string, d prompt.Document) []prompt.Suggest { switch cmd { case pndUseCmd, pndGetCmd: - return cobraCommandCompletion(cmd, d, getPnds()) + return cobraCommandCompletion(cmd, d, inputFlags, getPnds()) case commitCmd: return getChangesByType(pnd.ChangeState_CHANGE_STATE_PENDING) case confirmCmd: @@ -211,7 +205,7 @@ func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []s devices, _ := getDevices() return devices default: - return cobraCommandCompletion(cmd, d, []prompt.Suggest{}) + return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{}) } } diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go index ee546696da15769bd5747060a30be09cb2657966..0b341581550116ea47eb4287fcbca43ba5f337c1 100644 --- a/cli/cmd/utils.go +++ b/cli/cmd/utils.go @@ -96,3 +96,13 @@ func getChangesByType(cType pnd.ChangeState) []prompt.Suggest { } return completer.SortSuggestionByText(s) } + +// sliceContains checks if a slice contains the given item +func sliceContains[T comparable](slice []T, toCompare T) bool { + for _, sliceEntry := range slice { + if sliceEntry == toCompare { + return true + } + } + return false +}