make repl an engine feature
This commit is contained in:
parent
056f0cf5d5
commit
4a4c8669df
3 changed files with 102 additions and 97 deletions
98
engine/repl.go
Normal file
98
engine/repl.go
Normal file
|
@ -0,0 +1,98 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (g *Game) REPL(src io.Reader, dst io.Writer, assets fs.FS) error {
|
||||
sc := bufio.NewScanner(src)
|
||||
for sc.Scan() {
|
||||
tok := strings.Split(sc.Text(), " ")
|
||||
if len(tok) == 0 {
|
||||
continue
|
||||
}
|
||||
switch tok[0] {
|
||||
case "quit":
|
||||
os.Exit(0)
|
||||
case "pause":
|
||||
g.Disable()
|
||||
case "resume", "unpause":
|
||||
g.Enable()
|
||||
case "save":
|
||||
if len(tok) != 2 {
|
||||
fmt.Fprintln(dst, "Usage: save ID")
|
||||
break
|
||||
}
|
||||
id := tok[1]
|
||||
c := g.Component(id)
|
||||
if c == nil {
|
||||
fmt.Fprintf(dst, "Component %q not found\n", id)
|
||||
break
|
||||
}
|
||||
s, ok := c.(Saver)
|
||||
if !ok {
|
||||
fmt.Fprintf(dst, "Component %q not a Saver (type %T)\n", id, c)
|
||||
break
|
||||
}
|
||||
if err := s.Save(); err != nil {
|
||||
fmt.Fprintf(dst, "Couldn't save %q: %v\n", id, err)
|
||||
}
|
||||
case "reload":
|
||||
g.Disable()
|
||||
g.Hide()
|
||||
if err := g.Load(assets); err != nil {
|
||||
fmt.Fprintf(dst, "Couldn't load: %v\n", err)
|
||||
break
|
||||
}
|
||||
g.Prepare()
|
||||
g.Enable()
|
||||
g.Show()
|
||||
case "tree":
|
||||
|
||||
var c interface{} = g
|
||||
if len(tok) == 2 {
|
||||
// subtree
|
||||
id := tok[1]
|
||||
c = g.Component(id)
|
||||
if c == nil {
|
||||
fmt.Fprintf(dst, "Component %q not found\n", id)
|
||||
break
|
||||
}
|
||||
}
|
||||
type item struct {
|
||||
c interface{}
|
||||
depth int
|
||||
}
|
||||
stack := []item{{c, 0}}
|
||||
for len(stack) > 0 {
|
||||
tail := len(stack) - 1
|
||||
x := stack[tail]
|
||||
stack = stack[:tail]
|
||||
c := x.c
|
||||
|
||||
indent := ""
|
||||
if x.depth > 0 {
|
||||
indent = strings.Repeat(" ", x.depth-1) + "↳ "
|
||||
}
|
||||
i, ok := c.(Identifier)
|
||||
if ok {
|
||||
fmt.Fprintf(dst, "%s%T %s\n", indent, c, i.Ident())
|
||||
} else {
|
||||
fmt.Fprintf(dst, "%s%T\n", indent, c)
|
||||
}
|
||||
|
||||
if s, ok := c.(Scanner); ok {
|
||||
for _, y := range s.Scan() {
|
||||
stack = append(stack, item{y, x.depth + 1})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sc.Err()
|
||||
}
|
Binary file not shown.
101
main.go
101
main.go
|
@ -1,12 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
_ "image/png"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"drjosh.dev/gurgle/engine"
|
||||
"drjosh.dev/gurgle/game"
|
||||
|
@ -38,104 +36,13 @@ func main() {
|
|||
}
|
||||
g.Prepare()
|
||||
|
||||
// Run a repl on the console.
|
||||
go repl(g)
|
||||
if runtime.GOOS != "js" {
|
||||
// Run a repl on the console.
|
||||
go g.REPL(os.Stdin, os.Stdout, game.Assets)
|
||||
}
|
||||
|
||||
// ... while the game also runs
|
||||
if err := ebiten.RunGame(g); err != nil {
|
||||
log.Fatalf("Game error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func repl(g *engine.Game) {
|
||||
if runtime.GOOS == "js" {
|
||||
// can't os.Stdin on js
|
||||
return
|
||||
}
|
||||
sc := bufio.NewScanner(os.Stdin)
|
||||
for sc.Scan() {
|
||||
tok := strings.Split(sc.Text(), " ")
|
||||
if len(tok) == 0 {
|
||||
continue
|
||||
}
|
||||
switch tok[0] {
|
||||
case "quit":
|
||||
os.Exit(0)
|
||||
case "pause":
|
||||
g.Disable()
|
||||
case "resume", "unpause":
|
||||
g.Enable()
|
||||
case "save":
|
||||
if len(tok) != 2 {
|
||||
log.Print("Usage: save ID")
|
||||
break
|
||||
}
|
||||
id := tok[1]
|
||||
c := g.Component(id)
|
||||
if c == nil {
|
||||
log.Printf("Component %q not found", id)
|
||||
break
|
||||
}
|
||||
s, ok := c.(engine.Saver)
|
||||
if !ok {
|
||||
log.Printf("Component %q not a Saver (type %T)", id, c)
|
||||
break
|
||||
}
|
||||
if err := s.Save(); err != nil {
|
||||
log.Printf("Couldn't save %q: %v", id, err)
|
||||
}
|
||||
case "reload":
|
||||
g.Disable()
|
||||
g.Hide()
|
||||
if err := g.Load(game.Assets); err != nil {
|
||||
log.Printf("Couldn't load: %v", err)
|
||||
break
|
||||
}
|
||||
g.Prepare()
|
||||
g.Enable()
|
||||
g.Show()
|
||||
case "tree":
|
||||
var c interface{} = g
|
||||
if len(tok) == 2 {
|
||||
// subtree
|
||||
id := tok[1]
|
||||
c = g.Component(id)
|
||||
if c == nil {
|
||||
log.Printf("Component %q not found", id)
|
||||
break
|
||||
}
|
||||
}
|
||||
type item struct {
|
||||
c interface{}
|
||||
depth int
|
||||
}
|
||||
stack := []item{{c, 0}}
|
||||
for len(stack) > 0 {
|
||||
tail := len(stack) - 1
|
||||
x := stack[tail]
|
||||
stack = stack[:tail]
|
||||
c := x.c
|
||||
|
||||
indent := ""
|
||||
if x.depth > 0 {
|
||||
indent = strings.Repeat(" ", x.depth-1) + "↳ "
|
||||
}
|
||||
i, ok := c.(engine.Identifier)
|
||||
if ok {
|
||||
log.Printf("%s%T %s", indent, c, i.Ident())
|
||||
} else {
|
||||
log.Printf("%s%T", indent, c)
|
||||
}
|
||||
|
||||
if s, ok := c.(engine.Scanner); ok {
|
||||
for _, y := range s.Scan() {
|
||||
stack = append(stack, item{y, x.depth + 1})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := sc.Err(); err != nil {
|
||||
log.Fatalf("Couldn't scan stdin: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue