@@ -58,6 +58,16 @@ func trimLastArg(args []string) []string {
58
58
return []string (nil )
59
59
}
60
60
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
+
61
71
// argIsOption returns if an argument is an option
62
72
func argIsOption (arg string ) bool {
63
73
return strings .Contains (arg , "=" ) || strings .Contains (arg , "." )
@@ -172,18 +182,66 @@ func sortOptions(meta *meta, args []string, toSuggest string, suggestions []stri
172
182
return suggests
173
183
}
174
184
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
+
175
216
// Complete returns the list of suggestion based on prompt content
176
217
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
+
177
224
meta := extractMeta (c .ctx )
178
225
179
226
argsBeforeCursor := meta .CliConfig .Alias .ResolveAliases (strings .Split (d .TextBeforeCursor (), " " ))
180
227
argsAfterCursor := meta .CliConfig .Alias .ResolveAliases (strings .Split (d .TextAfterCursor (), " " ))
181
228
currentArg := lastArg (argsBeforeCursor ) + firstArg (argsAfterCursor )
182
229
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
185
238
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
+ }
187
245
188
246
suggestions := []prompt.Suggest (nil )
189
247
@@ -192,13 +250,13 @@ func (c *Completer) Complete(d prompt.Document) []prompt.Suggest {
192
250
// if first suggestion is an option, all suggestions should be options
193
251
// we sort them
194
252
if len (rawSuggestions ) > 0 && argIsOption (rawSuggestions [0 ]) {
195
- rawSuggestions = sortOptions (meta , args , rawSuggestions [0 ], rawSuggestions )
253
+ rawSuggestions = sortOptions (meta , leftArgs , rawSuggestions [0 ], rawSuggestions )
196
254
}
197
255
198
256
for _ , suggest := range rawSuggestions {
199
257
suggestions = append (suggestions , prompt.Suggest {
200
258
Text : suggest ,
201
- Description : getSuggestDescription (meta , args , suggest ),
259
+ Description : getSuggestDescription (meta , leftArgs , suggest ),
202
260
})
203
261
}
204
262
0 commit comments