Very naive REPL
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"esdi/repl"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func replCmdAction(cmd *cobra.Command, args []string) {
|
||||||
|
repl := repl.NewREPL(repl.REPLCfg{
|
||||||
|
PS1: "\rESDI > ",
|
||||||
|
})
|
||||||
|
repl.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeLabelCmd represents the removeLabel command
|
||||||
|
var replCmd = &cobra.Command{
|
||||||
|
Use: "repl",
|
||||||
|
Short: "run the repl to interact with the display",
|
||||||
|
Long: ``,
|
||||||
|
Run: replCmdAction,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(replCmd)
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
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 {
|
||||||
|
os.Exit(0)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type Command struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
Action func(r *REPL, args []string) error
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package repl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseInput(args string) []string {
|
||||||
|
return strings.Split(args, " ")
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Package repl Basic UI for the user
|
||||||
|
package repl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DefaultCfg = REPLCfg{
|
||||||
|
PS1: "\r> ",
|
||||||
|
}
|
||||||
|
|
||||||
|
type REPLCfg struct {
|
||||||
|
PS1 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type REPL struct {
|
||||||
|
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) printPrompt() {
|
||||||
|
_, _ = os.Stdout.Write([]byte(r.Cfg.PS1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *REPL) Start() {
|
||||||
|
reader := bufio.NewScanner(os.Stdin)
|
||||||
|
r.printPrompt()
|
||||||
|
for reader.Scan() {
|
||||||
|
input := reader.Text()
|
||||||
|
args := parseInput(input)
|
||||||
|
|
||||||
|
command, exists := r.Commands[args[0]]
|
||||||
|
if exists {
|
||||||
|
_ = command.Action(r, args[1:])
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No such command `%s`\n", args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
r.printPrompt()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user