Skip to content

Custom autocompletion after double dash (--) #1877

Open
@richard-kramer

Description

@richard-kramer

I'm currently trying out the cobra framework and stumbled upon an issue with dynamic autocompletion and cmd.ArgsLenAtDash().

I'm trying to provide autocompletion for a predefined set of possible positional parameters until a -- is added. Everything after that should be passed down to another command (or otherwise processed differently to all args before the double dash) and should provide different autocompletion results.

Unfortunately, because of the added -- here, the result of cmd.ArgsLenAtDash() inside ValidArgsFunction is always at least 0, even when there is no -- in my command. This makes it impossible to detect, if a -- hasn't been added to the arguments yet. As soon as I add another argument behind the --, cmd.ArgsLenAtDash() returns the correct result.

Now I'm not sure, if this is simply not a supported use case, if I'm missing something or if this is actually a bug.

Example Code

This is an example cmd/test.go file inside an initialized cobra project, added to the root command.

// cmd/test.go

// …

var validArgs = []string{"foo", "bar", "baz"}

// TestCmd represents the test command
var TestCmd = &cobra.Command{
  Use:   "test",
  ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
    cobra.CompDebugln(fmt.Sprint(cmd.ArgsLenAtDash()), true) // => always at least `0`, even when it should be `-1`

    possibleArgs := append(validArgs, "--")

    if cmd.ArgsLenAtDash() < 0 {
      return possibleArgs, cobra.ShellCompDirectiveNoFileComp
    }

    return nil, cobra.ShellCompDirectiveDefault
  },
  Run: func(cmd *cobra.Command, args []string) {
    cmdArgsEnd := len(args)
    if cmd.ArgsLenAtDash() > -1 {
      cmdArgsEnd = cmd.ArgsLenAtDash()
    }

    fmt.Println("test called")
    fmt.Println()
    fmt.Printf("args: %+q\n", args[:cmdArgsEnd])
    fmt.Printf("ArgsLenAtDash: %d\n", cmd.ArgsLenAtDash())
    fmt.Printf("args after --: %+q\n", args[cmdArgsEnd:])
  },
}

// …

I'm expecting to get completions like these:

go run ./main.go __complete test ""
# >
# [Debug] -1
# foo
# bar
# baz
# --
# :4
# Completion ended with directive: ShellCompDirectiveNoFileComp
go run ./main.go __complete test foo ""
# >
# [Debug] -1
# foo
# bar
# baz
# --
# :4
# Completion ended with directive: ShellCompDirectiveNoFileComp
go run ./main.go __complete test foo -- ""
# >
# [Debug] 1
# :0
# Completion ended with directive: ShellCompDirectiveDefault
go run ./main.go __complete test foo -- bar ""
# >
# [Debug] 1
# :0
# Completion ended with directive: ShellCompDirectiveDefault

But I'm always getting the last return values:

go run ./main.go __complete test ""
# >
# [Debug] 0
# :0
# Completion ended with directive: ShellCompDirectiveDefault
go run ./main.go __complete test foo ""
# >
# [Debug] 1
# :0
# Completion ended with directive: ShellCompDirectiveDefault

My goal is to add different autocompletion for possible arguments after the --, but the only issue with that is the correct detection of when the -- has been added.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions