Skip to content

Commit c79972f

Browse files
committed
Fix map field autocomplete dispatch
1 parent 86a757d commit c79972f

2 files changed

Lines changed: 88 additions & 13 deletions

File tree

‎cli/completer.go‎

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,45 @@ func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int)
437437
// Auto-complete API arg
438438
splitLine := strings.Split(string(line), " ")
439439
line = trimSpaceLeft([]rune(splitLine[len(splitLine)-1]))
440+
440441
for _, arg := range apiFound.Args {
442+
443+
if arg.Type == "map" {
444+
suggestions := mapFieldSuggestions(arg)
445+
input := string(line)
446+
mapName := strings.TrimSuffix(arg.Name, "=")
447+
448+
matchInput := input
449+
matchOffset := len(line)
450+
451+
// Replace the trailing '=' in tags= with the indexed field.
452+
if strings.HasSuffix(input, "=") &&
453+
strings.TrimSuffix(input, "=") == mapName {
454+
matchInput = mapName
455+
matchOffset--
456+
}
457+
458+
if matchInput == mapName ||
459+
strings.HasPrefix(matchInput, mapName+"[") {
460+
var mapOptions [][]rune
461+
462+
for _, suggestion := range suggestions {
463+
if strings.HasPrefix(suggestion, matchInput) {
464+
mapOptions = append(
465+
mapOptions,
466+
[]rune(suggestion[len(matchInput):]),
467+
)
468+
}
469+
}
470+
471+
if len(mapOptions) > 0 {
472+
options = append(options, mapOptions...)
473+
offset = matchOffset
474+
return
475+
}
476+
}
477+
}
478+
441479
search := arg.Name
442480
if !hasPrefix(line, []rune(search)) {
443481
sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
@@ -457,19 +495,6 @@ func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int)
457495
return
458496
}
459497

460-
if arg.Type == "map" {
461-
suggestions := mapFieldSuggestions(arg)
462-
463-
for _, suggestion := range suggestions {
464-
if strings.HasPrefix(suggestion, string(line)) {
465-
options = append(options, []rune(suggestion[len(line):]))
466-
}
467-
}
468-
469-
offset = len(line)
470-
return
471-
}
472-
473498
if arg.Type == config.FAKE && arg.Name == "filter=" {
474499
offset = 0
475500
filterInputs := strings.Split(strings.Replace(argInput, ",", ",|", -1), "|")

‎cli/completer_test.go‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,53 @@ func TestMapFieldSuggestionsWithNonKeyValueMap(t *testing.T) {
389389
t.Fatalf("expected no suggestions, got %v", got)
390390
}
391391
}
392+
393+
func TestMapAutocompleteThroughDo(t *testing.T) {
394+
cfg := &config.Config{}
395+
396+
// Restore the normal API cache after this test.
397+
defer config.LoadCache(cfg)
398+
399+
cfg.UpdateCache(map[string]interface{}{
400+
"count": 1,
401+
"api": []interface{}{
402+
map[string]interface{}{
403+
"name": "listVirtualMachines",
404+
"isasync": false,
405+
"description": "List virtual machines",
406+
"params": []interface{}{
407+
map[string]interface{}{
408+
"name": "tags",
409+
"type": "map",
410+
"required": false,
411+
"description": "List resources by tags (key/value pairs)",
412+
},
413+
},
414+
"response": []interface{}{},
415+
},
416+
},
417+
})
418+
419+
completer := &autoCompleter{Config: cfg}
420+
line := []rune("list virtualmachines tags=")
421+
422+
options, offset := completer.Do(line, len(line))
423+
424+
var got []string
425+
for _, option := range options {
426+
got = append(got, string(option))
427+
}
428+
429+
expected := []string{
430+
"[0].key=",
431+
"[0].value=",
432+
}
433+
434+
if !reflect.DeepEqual(got, expected) {
435+
t.Fatalf("expected suggestions %v, got %v", expected, got)
436+
}
437+
438+
if offset != len("tags=")-1 {
439+
t.Fatalf("expected offset %d, got %d", len("tags=")-1, offset)
440+
}
441+
}

0 commit comments

Comments
 (0)