status-go/cmd/statusd-cli/repl.go

96 lines
1.9 KiB
Go

package main
import (
"bufio"
"fmt"
"net"
"os"
"strconv"
"strings"
)
// REPL implements the read-eval-print loop for the commands
// to be sent to statusd.
type REPL struct {
addr string
}
// NewREPL creates a REPL instance communicating with the
// addressed statusd.
func NewREPL(addr string) *REPL {
return &REPL{
addr: addr,
}
}
// Run operates the loop to read a command and its arguments,
// execute it via the client, and print the result.
func (r *REPL) Run() error {
var (
conn net.Conn
reader *bufio.Reader
writer *bufio.Writer
err error
)
input := bufio.NewReader(os.Stdin)
connect := true
for {
// Connect first time and after connection errors.
if connect {
conn, err = net.Dial("tcp", r.addr)
if err != nil {
return fmt.Errorf("error connecting to statusd: %v", err)
}
connect = false
reader = bufio.NewReader(conn)
writer = bufio.NewWriter(conn)
}
// Read command line.
fmt.Print(">>> ")
command, err := input.ReadString('\n')
if err != nil {
fmt.Printf("ERR %v\n", err)
continue
}
// Check for possible end.
if strings.ToLower(command) == "quit\n" {
return nil
}
// Execute on statusd.
_, err = writer.WriteString(command)
if err != nil {
fmt.Printf("ERR %v\n", err)
connect = true
continue
}
err = writer.Flush()
if err != nil {
fmt.Printf("ERR %v\n", err)
connect = true
continue
}
// Read number of expected result lines.
countStr, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("ERR %v\n", err)
connect = true
continue
}
count, err := strconv.Atoi(strings.TrimSuffix(countStr, "\n"))
if err != nil {
fmt.Printf("ERR %v\n", err)
continue
}
// Read and print result lines.
for i := 0; i < count; i++ {
reply, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("ERR %v\n", err)
continue
}
fmt.Print("<<< ")
fmt.Print(reply)
}
}
}