Moved the REPL thing to its own package
This commit is contained in:
+2
-1
@@ -2,10 +2,11 @@ package cmd
|
||||
|
||||
import (
|
||||
"esdi/peripheral"
|
||||
"esdi/repl"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
repl "github.com/ESilva15/ESgoRepl"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
module esdi
|
||||
|
||||
go 1.23.2
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/ESilva15/ESgoRepl v0.1.0
|
||||
github.com/ESilva15/gobngsdk v0.0.2
|
||||
github.com/ESilva15/goirsdk v0.2.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
github.com/ESilva15/ESgoRepl v0.1.0 h1:hOVcRBfdP8Yw1kLr2tFoM3SetV7vxFswKjzfAtq8UgM=
|
||||
github.com/ESilva15/ESgoRepl v0.1.0/go.mod h1:O2JQMyEgHy0zf9UvzvLNvp2w95T2uazc3torrzRmG9Y=
|
||||
github.com/ESilva15/gobngsdk v0.0.2 h1:N6stNOE14Wg80BAZMFu/Qd9Qa/J0DmExCfdPoDf7lco=
|
||||
github.com/ESilva15/gobngsdk v0.0.2/go.mod h1:cKLaZRgM0tGGXDvosaSjHnxeyC5Y6rg7zCLqEUJnOzw=
|
||||
github.com/ESilva15/goirsdk v0.2.0 h1:zmtYyH3ayGRcDfzzLrJmEpX6zdmCHTUqbs4tnV2hXmI=
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package repl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
helpCmd = Command{
|
||||
Name: ".help",
|
||||
Usage: " type `.help` for help",
|
||||
Action: func(r *REPL, args []string) error {
|
||||
for _, cmd := range r.Commands {
|
||||
fmt.Printf("%-20s\t%s\n", cmd.Name, cmd.Usage)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
clearCmd = Command{
|
||||
Name: ".clear",
|
||||
Usage: " type `.clear` to clear the screen",
|
||||
Action: func(r *REPL, args []string) error {
|
||||
_, _ = os.Stdout.Write([]byte("\033[2J\033[H"))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
exitCmd = Command{
|
||||
Name: ".exit",
|
||||
Usage: " type `.exit` to exit this REPL",
|
||||
Action: func(r *REPL, args []string) error {
|
||||
r.Stop = true
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
Name string
|
||||
Usage string
|
||||
Action func(r *REPL, args []string) error
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package repl
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseInput(args string) []string {
|
||||
return strings.Split(args, " ")
|
||||
}
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
// Package repl Basic UI for the user
|
||||
package repl
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var DefaultCfg = REPLCfg{
|
||||
PS1: "\r> ",
|
||||
}
|
||||
|
||||
type REPLCfg struct {
|
||||
PS1 string
|
||||
}
|
||||
|
||||
type REPL struct {
|
||||
Stop bool
|
||||
Cfg REPLCfg
|
||||
Commands map[string]Command
|
||||
}
|
||||
|
||||
func NewREPL(cfg REPLCfg) *REPL {
|
||||
return &REPL{
|
||||
Cfg: cfg,
|
||||
Commands: map[string]Command{
|
||||
helpCmd.Name: helpCmd,
|
||||
clearCmd.Name: clearCmd,
|
||||
exitCmd.Name: exitCmd,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *REPL) Close() {
|
||||
// Do whatever cleanup we have to do
|
||||
}
|
||||
|
||||
func (r *REPL) RegisterCMD(newCMD Command) {
|
||||
// Add a verification to check that the command doesn't exist. Fatal if it does
|
||||
r.Commands[newCMD.Name] = newCMD
|
||||
}
|
||||
|
||||
func (r *REPL) printPrompt() {
|
||||
_, _ = os.Stdout.Write([]byte(r.Cfg.PS1))
|
||||
}
|
||||
|
||||
func (r *REPL) SetPS1(s string) {
|
||||
r.Cfg.PS1 = s
|
||||
}
|
||||
|
||||
func parseArgs(l string) ([]string, error) {
|
||||
args := []string{}
|
||||
input := strings.TrimSpace(l)
|
||||
|
||||
type ArgParserState uint8
|
||||
const (
|
||||
readingQuotedStr ArgParserState = iota
|
||||
readingNormalStr
|
||||
storeArg
|
||||
)
|
||||
|
||||
curState := readingNormalStr
|
||||
|
||||
curStr := []byte{}
|
||||
for k := 0; k < len(input); {
|
||||
switch curState {
|
||||
case readingNormalStr:
|
||||
switch input[k] {
|
||||
case '"':
|
||||
curState = readingQuotedStr
|
||||
case ' ':
|
||||
curState = storeArg
|
||||
default:
|
||||
curStr = append(curStr, input[k])
|
||||
}
|
||||
k++
|
||||
case readingQuotedStr:
|
||||
switch input[k] {
|
||||
case '"':
|
||||
if k+1 < len(input) {
|
||||
k++
|
||||
}
|
||||
curState = storeArg
|
||||
default:
|
||||
curStr = append(curStr, input[k])
|
||||
}
|
||||
k++
|
||||
case storeArg:
|
||||
args = append(args, string(curStr))
|
||||
curStr = nil
|
||||
curState = readingNormalStr
|
||||
}
|
||||
|
||||
if k == len(input) {
|
||||
args = append(args, string(curStr))
|
||||
curStr = nil
|
||||
}
|
||||
}
|
||||
|
||||
if curState == readingQuotedStr {
|
||||
return []string{}, fmt.Errorf("quoted string was not closed: %s", curStr)
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (r *REPL) mainLoop() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
r.printPrompt()
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
fmt.Println("error: ", err)
|
||||
continue
|
||||
}
|
||||
|
||||
args, err := parseArgs(line)
|
||||
if err != nil {
|
||||
fmt.Printf("%s\n", err.Error())
|
||||
}
|
||||
|
||||
command, exists := r.Commands[args[0]]
|
||||
if exists {
|
||||
err = command.Action(r, args[1:])
|
||||
if err != nil {
|
||||
fmt.Printf("error: %s\n", err.Error())
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("No such command `%s`\n", args[0])
|
||||
}
|
||||
|
||||
if r.Stop {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *REPL) Start() {
|
||||
// Setup handlers and whatnot
|
||||
r.mainLoop()
|
||||
}
|
||||
Reference in New Issue
Block a user