Skip to content

Commit b17ca12

Browse files
authored
feat(autocomplete): cache in arg completion instead of shell (#2952)
1 parent cbda14e commit b17ca12

File tree

3 files changed

+56
-43
lines changed

3 files changed

+56
-43
lines changed

internal/cache/cache.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package cache
2+
3+
import "strings"
4+
5+
type Cache struct {
6+
m map[string]interface{}
7+
}
8+
9+
func New() *Cache {
10+
return &Cache{
11+
m: map[string]interface{}{},
12+
}
13+
}
14+
15+
func (c *Cache) Set(cmd string, resp interface{}) {
16+
if c == nil {
17+
return
18+
}
19+
c.m[cmd] = resp
20+
}
21+
22+
func (c *Cache) Get(cmd string) interface{} {
23+
if c == nil {
24+
return nil
25+
}
26+
return c.m[cmd]
27+
}
28+
29+
func (c *Cache) Update(namespace string) {
30+
if c == nil {
31+
return
32+
}
33+
for k := range c.m {
34+
if strings.HasPrefix(k, namespace) {
35+
delete(c.m, k)
36+
}
37+
}
38+
}

internal/core/autocomplete_utils.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@ package core
22

33
import (
44
"context"
5+
"fmt"
56
"reflect"
67
"strings"
78

89
"github.com/scaleway/scaleway-cli/v2/internal/args"
10+
"github.com/scaleway/scaleway-cli/v2/internal/cache"
911
"github.com/scaleway/scaleway-sdk-go/scw"
1012
"github.com/scaleway/scaleway-sdk-go/strcase"
1113
)
1214

15+
var autoCompleteCache *cache.Cache
16+
1317
func AutocompleteProfileName() AutoCompleteArgFunc {
1418
return func(ctx context.Context, prefix string) AutocompleteSuggestions {
1519
res := AutocompleteSuggestions(nil)
@@ -96,9 +100,15 @@ func AutocompleteGetArg(ctx context.Context, cmd *Command, argSpec *ArgSpec, com
96100
return runner(ctx, argsI)
97101
}
98102
}
99-
resp, err := listCmd.Interceptor(ctx, listCmdArgs, listCmd.Run)
100-
if err != nil {
101-
return nil
103+
104+
rawCommand := fmt.Sprintf("%s %s", listCmd.getPath(), strings.Join(listRawArgs, " "))
105+
resp := autoCompleteCache.Get(rawCommand)
106+
if resp == nil {
107+
resp, err = listCmd.Interceptor(ctx, listCmdArgs, listCmd.Run)
108+
if err != nil {
109+
return nil
110+
}
111+
autoCompleteCache.Set(rawCommand, resp)
102112
}
103113

104114
// As we run the "list" verb instead of using the sdk ListResource, response is already the slice

internal/core/shell.go

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"strings"
1414

1515
"github.com/c-bata/go-prompt"
16+
"github.com/scaleway/scaleway-cli/v2/internal/cache"
1617
"github.com/scaleway/scaleway-cli/v2/internal/interactive"
1718
"github.com/spf13/cobra"
1819
)
@@ -182,37 +183,6 @@ func sortOptions(meta *meta, args []string, toSuggest string, suggestions []stri
182183
return suggests
183184
}
184185

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-
216186
// Complete returns the list of suggestion based on prompt content
217187
func (c *Completer) Complete(d prompt.Document) []prompt.Suggest {
218188
// shell lib can request duplicate Complete request with empty strings as text
@@ -234,17 +204,9 @@ func (c *Completer) Complete(d prompt.Document) []prompt.Suggest {
234204

235205
leftWords := append([]string{"scw"}, leftArgs...)
236206

237-
var acr *AutocompleteResponse
238-
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-
}
207+
acr := AutoComplete(c.ctx, leftWords, currentArg, rightWords)
245208

246209
suggestions := []prompt.Suggest(nil)
247-
248210
rawSuggestions := []string(acr.Suggestions)
249211

250212
// if first suggestion is an option, all suggestions should be options
@@ -289,6 +251,8 @@ func shellExecutor(rootCmd *cobra.Command, printer *Printer, meta *meta) func(s
289251
return
290252
}
291253

254+
autoCompleteCache.Update(meta.command.Namespace)
255+
292256
printErr := printer.Print(meta.result, meta.command.getHumanMarshalerOpt())
293257
if printErr != nil {
294258
_, _ = fmt.Fprintln(os.Stderr, printErr)
@@ -309,6 +273,7 @@ func getShellCommand(rootCmd *cobra.Command) *cobra.Command {
309273

310274
// RunShell will run an interactive shell that runs cobra commands
311275
func RunShell(ctx context.Context, printer *Printer, meta *meta, rootCmd *cobra.Command, args []string) {
276+
autoCompleteCache = cache.New()
312277
completer := NewShellCompleter(ctx)
313278

314279
shellCobraCommand := getShellCommand(rootCmd)

0 commit comments

Comments
 (0)