Skip to content

Commit bfec5e1

Browse files
authored
feat(shell): cache last autocomplete request (#2846)
1 parent dd77e3c commit bfec5e1

File tree

1 file changed

+63
-5
lines changed

1 file changed

+63
-5
lines changed

internal/core/shell.go

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ func trimLastArg(args []string) []string {
5858
return []string(nil)
5959
}
6060

61+
// trimLastArg returns all arguments but the first one
62+
// return a nil slice if there is no other arguments
63+
func trimFirstArg(args []string) []string {
64+
l := len(args)
65+
if l > 1 {
66+
return args[1:]
67+
}
68+
return []string(nil)
69+
}
70+
6171
// argIsOption returns if an argument is an option
6272
func argIsOption(arg string) bool {
6373
return strings.Contains(arg, "=") || strings.Contains(arg, ".")
@@ -172,18 +182,66 @@ func sortOptions(meta *meta, args []string, toSuggest string, suggestions []stri
172182
return suggests
173183
}
174184

185+
// CompletionCache allows to keep last completion request in cache
186+
// Useful to avoid request spamming when adding a character
187+
type CompletionCache struct {
188+
wordsSum string
189+
arg string
190+
LastResponse *AutocompleteResponse
191+
}
192+
193+
// completionCacheResetCharacterList is the list of character that will trigger cache reset
194+
var completionCacheResetCharacterList = []string{"=", "."}
195+
var completionCache CompletionCache
196+
197+
func (cache *CompletionCache) HasChanged(leftWords []string, currentArg string, rightWords []string) bool {
198+
wordsSum := strings.Join(leftWords, "-") + "_" + strings.Join(rightWords, "-")
199+
if cache.wordsSum != wordsSum {
200+
cache.wordsSum = wordsSum
201+
cache.arg = currentArg
202+
return true
203+
}
204+
205+
for _, character := range completionCacheResetCharacterList {
206+
if strings.Count(cache.arg, character) != strings.Count(currentArg, character) {
207+
cache.arg = currentArg
208+
return true
209+
}
210+
}
211+
212+
cache.arg = currentArg
213+
return false
214+
}
215+
175216
// Complete returns the list of suggestion based on prompt content
176217
func (c *Completer) Complete(d prompt.Document) []prompt.Suggest {
218+
// shell lib can request duplicate Complete request with empty strings as text
219+
// skipping to avoid cache reset
220+
if d.Text == "" {
221+
return nil
222+
}
223+
177224
meta := extractMeta(c.ctx)
178225

179226
argsBeforeCursor := meta.CliConfig.Alias.ResolveAliases(strings.Split(d.TextBeforeCursor(), " "))
180227
argsAfterCursor := meta.CliConfig.Alias.ResolveAliases(strings.Split(d.TextAfterCursor(), " "))
181228
currentArg := lastArg(argsBeforeCursor) + firstArg(argsAfterCursor)
182229

183-
// args contains all arguments before the one with the cursor
184-
args := trimLastArg(argsBeforeCursor)
230+
// leftArgs contains all arguments before the one with the cursor
231+
leftArgs := trimLastArg(argsBeforeCursor)
232+
// rightWords contains all words after the selected one
233+
rightWords := trimFirstArg(argsAfterCursor)
234+
235+
leftWords := append([]string{"scw"}, leftArgs...)
236+
237+
var acr *AutocompleteResponse
185238

186-
acr := AutoComplete(c.ctx, append([]string{"scw"}, args...), currentArg, argsAfterCursor)
239+
if completionCache.HasChanged(leftWords, currentArg, rightWords) {
240+
acr = AutoComplete(c.ctx, leftWords, currentArg, rightWords)
241+
completionCache.LastResponse = acr
242+
} else {
243+
acr = completionCache.LastResponse
244+
}
187245

188246
suggestions := []prompt.Suggest(nil)
189247

@@ -192,13 +250,13 @@ func (c *Completer) Complete(d prompt.Document) []prompt.Suggest {
192250
// if first suggestion is an option, all suggestions should be options
193251
// we sort them
194252
if len(rawSuggestions) > 0 && argIsOption(rawSuggestions[0]) {
195-
rawSuggestions = sortOptions(meta, args, rawSuggestions[0], rawSuggestions)
253+
rawSuggestions = sortOptions(meta, leftArgs, rawSuggestions[0], rawSuggestions)
196254
}
197255

198256
for _, suggest := range rawSuggestions {
199257
suggestions = append(suggestions, prompt.Suggest{
200258
Text: suggest,
201-
Description: getSuggestDescription(meta, args, suggest),
259+
Description: getSuggestDescription(meta, leftArgs, suggest),
202260
})
203261
}
204262

0 commit comments

Comments
 (0)