@@ -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
6272func 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
176217func (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