Skip to content

Commit 16db39a

Browse files
cli: fix auto-completion bug
Refactors the logic that finds the auto-completion API. Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent 56ea2b5 commit 16db39a

File tree

1 file changed

+71
-43
lines changed

1 file changed

+71
-43
lines changed

cli/completer.go

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ func buildArgOptions(response map[string]interface{}, hasID bool) []argOption {
149149
} else {
150150
opt.Value = name
151151
opt.Detail = detail
152+
if len(name) == 0 {
153+
opt.Value = detail
154+
}
152155
}
153156
argOptions = append(argOptions, opt)
154157
}
@@ -177,6 +180,73 @@ func doInternal(line []rune, pos int, lineLen int, argName []rune) (newLine [][]
177180
return
178181
}
179182

183+
func findAutocompleteAPI(arg *config.APIArg, apiFound *config.API, apiMap map[string][]*config.API) *config.API {
184+
if arg.Type == "map" {
185+
return nil
186+
}
187+
188+
var autocompleteAPI *config.API
189+
argName := strings.Replace(arg.Name, "=", "", -1)
190+
relatedNoun := argName
191+
if argName == "id" || argName == "ids" {
192+
// Heuristic: user is trying to autocomplete for id/ids arg for a list API
193+
relatedNoun = apiFound.Noun
194+
if apiFound.Verb != "list" {
195+
relatedNoun += "s"
196+
}
197+
} else if argName == "account" {
198+
// Heuristic: user is trying to autocomplete for accounts
199+
relatedNoun = "accounts"
200+
} else if argName == "ipaddressid" {
201+
// Heuristic: user is trying to autocomplete for ip addresses
202+
relatedNoun = "publicipaddresses"
203+
} else {
204+
// Heuristic: autocomplete for the arg for which a list<Arg without id/ids>s API exists
205+
// For example, for zoneid arg, listZones API exists
206+
cutIdx := len(argName)
207+
if strings.HasSuffix(argName, "id") {
208+
cutIdx -= 2
209+
} else if strings.HasSuffix(argName, "ids") {
210+
cutIdx -= 3
211+
} else {
212+
}
213+
relatedNoun = argName[:cutIdx] + "s"
214+
}
215+
216+
config.Debug("Possible related noun for the arg: ", relatedNoun, " and type: ", arg.Type)
217+
for _, listAPI := range apiMap["list"] {
218+
if relatedNoun == listAPI.Noun {
219+
autocompleteAPI = listAPI
220+
break
221+
}
222+
}
223+
224+
if autocompleteAPI != nil {
225+
config.Debug("Autocomplete: API found using heuristics: ", autocompleteAPI.Name)
226+
}
227+
228+
if strings.HasSuffix(relatedNoun, "s") {
229+
relatedNoun = relatedNoun[:len(relatedNoun)-1]
230+
}
231+
232+
// Heuristic: find any list API that contains the arg name
233+
if autocompleteAPI == nil {
234+
config.Debug("Finding possible API that have: ", argName, " related APIs: ", arg.Related)
235+
possibleAPIs := []*config.API{}
236+
for _, listAPI := range apiMap["list"] {
237+
if strings.Contains(listAPI.Noun, argName) {
238+
config.Debug("Found possible API: ", listAPI.Name)
239+
possibleAPIs = append(possibleAPIs, listAPI)
240+
}
241+
}
242+
if len(possibleAPIs) == 1 {
243+
autocompleteAPI = possibleAPIs[0]
244+
}
245+
}
246+
247+
return autocompleteAPI
248+
}
249+
180250
type autoCompleter struct {
181251
Config *config.Config
182252
}
@@ -280,49 +350,7 @@ func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int)
280350
return
281351
}
282352

283-
argName := strings.Replace(arg.Name, "=", "", -1)
284-
var autocompleteAPI *config.API
285-
var relatedNoun string
286-
if argName == "id" || argName == "ids" {
287-
relatedNoun = apiFound.Noun
288-
if apiFound.Verb != "list" {
289-
relatedNoun += "s"
290-
}
291-
} else if argName == "account" {
292-
relatedNoun = "accounts"
293-
} else {
294-
relatedNoun = strings.Replace(strings.Replace(argName, "ids", "", -1), "id", "", -1) + "s"
295-
}
296-
297-
for _, listAPI := range apiMap["list"] {
298-
if relatedNoun == listAPI.Noun {
299-
autocompleteAPI = listAPI
300-
break
301-
}
302-
}
303-
304-
if autocompleteAPI == nil {
305-
relatedAPIName := ""
306-
for _, name := range arg.Related {
307-
if strings.HasPrefix(name, "list") {
308-
if len(relatedAPIName) == 0 {
309-
relatedAPIName = name
310-
}
311-
if len(name) < len(relatedAPIName) {
312-
relatedAPIName = name
313-
}
314-
}
315-
}
316-
if len(relatedAPIName) > 0 {
317-
for _, listAPI := range apiMap["list"] {
318-
if relatedAPIName == listAPI.Name {
319-
autocompleteAPI = listAPI
320-
break
321-
}
322-
}
323-
}
324-
}
325-
353+
autocompleteAPI := findAutocompleteAPI(arg, apiFound, apiMap)
326354
if autocompleteAPI == nil {
327355
return nil, 0
328356
}

0 commit comments

Comments
 (0)