From 2f3bc6eb8421eb742d1304371d077015a74e218c Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 12 Nov 2024 11:07:48 +0300 Subject: [PATCH] [#1396] cli/playground: Improve terminal control key handling Signed-off-by: Alexander Chuprov --- .../modules/container/policy_playground.go | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 095ab6438..6885d35f2 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -1,11 +1,10 @@ package container import ( - "bufio" "encoding/hex" "encoding/json" + "errors" "fmt" - "io" "os" "strings" @@ -14,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/chzyer/readline" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -163,6 +163,16 @@ func (repl *policyPlaygroundREPL) netMap() netmap.NetMap { return nm } +var policyPlaygroundCompleter = readline.NewPrefixCompleter( + readline.PcItem("list"), + readline.PcItem("ls"), + readline.PcItem("add"), + readline.PcItem("load"), + readline.PcItem("remove"), + readline.PcItem("rm"), + readline.PcItem("eval"), +) + func (repl *policyPlaygroundREPL) run() error { if len(viper.GetString(commonflags.RPC)) > 0 { key := key.GetOrGenerate(repl.cmd) @@ -189,15 +199,32 @@ func (repl *policyPlaygroundREPL) run() error { "rm": repl.handleRemove, "eval": repl.handleEval, } - for reader := bufio.NewReader(os.Stdin); ; { - fmt.Print("> ") - line, err := reader.ReadString('\n') + + rl, err := readline.NewEx(&readline.Config{ + Prompt: "> ", + InterruptPrompt: "^C", + AutoComplete: policyPlaygroundCompleter, + }) + if err != nil { + return fmt.Errorf("error initializing readline: %w", err) + } + defer rl.Close() + + var exit bool + for { + line, err := rl.Readline() if err != nil { - if err == io.EOF { - return nil + if errors.Is(err, readline.ErrInterrupt) { + if exit { + return nil + } + exit = true + continue } return fmt.Errorf("reading line: %v", err) } + exit = false + parts := strings.Fields(line) if len(parts) == 0 { continue