Skip to content

Commit

Permalink
Merge pull request mitchellh#62 from mitchellh/b-deep
Browse files Browse the repository at this point in the history
Properly build autocompletion tree for 2+ deep subcommands
  • Loading branch information
mitchellh authored Aug 24, 2017
2 parents b633c78 + 4834712 commit 0ce7cd5
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 17 deletions.
19 changes: 7 additions & 12 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,27 +398,22 @@ func (c *CLI) initAutocomplete() {
func (c *CLI) initAutocompleteSub(prefix string) complete.Command {
var cmd complete.Command
walkFn := func(k string, raw interface{}) bool {
// Keep track of the full key so that we can nest further if necessary
fullKey := k

if len(prefix) > 0 {
// If we have a prefix, trim the prefix + 1 (for the space)
// Example: turns "sub one" to "one" with prefix "sub"
k = k[len(prefix)+1:]
}

// Keep track of the full key so that we can nest further if necessary
fullKey := k

if idx := strings.LastIndex(k, " "); idx >= 0 {
// If there is a space, we trim up to the space
if idx := strings.Index(k, " "); idx >= 0 {
// If there is a space, we trim up to the space. This turns
// "sub sub2 sub3" into "sub". The prefix trim above will
// trim our current depth properly.
k = k[:idx]
}

if idx := strings.LastIndex(k, " "); idx >= 0 {
// This catches the scenario just in case where we see "sub one"
// before "sub". This will let us properly setup the subcommand
// regardless.
k = k[idx+1:]
}

if _, ok := cmd.Sub[k]; ok {
// If we already tracked this subcommand then ignore
return false
Expand Down
23 changes: 18 additions & 5 deletions cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -857,18 +857,25 @@ func TestCLIAutocomplete_root(t *testing.T) {
// Make sure global flags work on subcommands
{[]string{"sub"}, "-v", nil},
{[]string{"sub"}, "o", []string{"one"}},
{[]string{"sub"}, "su", []string{"sub2"}},
{[]string{"sub", "sub2"}, "o", []string{"one"}},
{[]string{"deep", "deep2"}, "a", []string{"a1"}},
}

for _, tc := range cases {
t.Run(tc.Last, func(t *testing.T) {
command := new(MockCommand)
cli := &CLI{
Commands: map[string]CommandFactory{
"foo": func() (Command, error) { return command, nil },
"nodes": func() (Command, error) { return command, nil },
"noodles": func() (Command, error) { return command, nil },
"sub one": func() (Command, error) { return command, nil },
"sub two": func() (Command, error) { return command, nil },
"foo": func() (Command, error) { return command, nil },
"nodes": func() (Command, error) { return command, nil },
"noodles": func() (Command, error) { return command, nil },
"sub one": func() (Command, error) { return command, nil },
"sub two": func() (Command, error) { return command, nil },
"sub sub2 one": func() (Command, error) { return command, nil },
"sub sub2 two": func() (Command, error) { return command, nil },
"deep deep2 a1": func() (Command, error) { return command, nil },
"deep deep2 b2": func() (Command, error) { return command, nil },
},

Autocomplete: true,
Expand All @@ -877,8 +884,14 @@ func TestCLIAutocomplete_root(t *testing.T) {
// Initialize
cli.init()

// Build All value
var all []string
all = append(all, tc.Completed...)
all = append(all, tc.Last)

// Test the autocompleter
actual := cli.autocomplete.Command.Predict(complete.Args{
All: all,
Completed: tc.Completed,
Last: tc.Last,
})
Expand Down

0 comments on commit 0ce7cd5

Please sign in to comment.