diff --git a/go.mod b/go.mod index 49ea9a0..254450e 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,14 @@ go 1.23.3 require ( github.com/aymanbagabas/go-pty v0.2.2 + github.com/hymkor/gmnlisp v0.7.3 github.com/hymkor/go-windows1x-virtualterminal v0.5.0 - golang.org/x/term v0.15.0 + golang.org/x/term v0.26.0 ) require ( github.com/creack/pty v1.1.21 // indirect github.com/u-root/u-root v0.11.0 // indirect golang.org/x/crypto v0.17.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sys v0.27.0 // indirect ) diff --git a/go.sum b/go.sum index 37f8a22..43515bd 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/aymanbagabas/go-pty v0.2.2 h1:YZREB4eSj+1xdbbItIokX0ekjjeifgJOA+ZvxU4 github.com/aymanbagabas/go-pty v0.2.2/go.mod h1:gfvlwH+0U66BCwxJREjJaAOEs9H1OFf3YFjI9WSiZ04= github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/hymkor/gmnlisp v0.7.3 h1:LDolAFXisJvY4j/8VrJvC12J2NL5KXLKilTLG47l0RI= +github.com/hymkor/gmnlisp v0.7.3/go.mod h1:5GY1Nxnu68pufvGdhrk9Kyp9XSNkYLfNpXznLk+eS74= github.com/hymkor/go-windows1x-virtualterminal v0.5.0 h1:UIMMK09QSLCdM9Up4ny6qmBOrrn3rozxIRPfEUhxmTo= github.com/hymkor/go-windows1x-virtualterminal v0.5.0/go.mod h1:M/X0FJL+4wQtrm03JnL9gVyvhyscJk3t+ItZ29sla2g= github.com/u-root/gobusybox/src v0.0.0-20221229083637-46b2883a7f90 h1:zTk5683I9K62wtZ6eUa6vu6IWwVHXPnoKK5n2unAwv0= @@ -10,7 +12,7 @@ github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8= github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= diff --git a/main.go b/main.go index 2e2fc95..c2bf102 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,57 @@ package main import ( + "context" "fmt" "io" "os" - "time" + + "github.com/hymkor/gmnlisp" ) +type Global struct { + w *Watcher + term *Term + closer []func() +} + +func (g *Global) Close() { + for i := len(g.closer) - 1; i >= 0; i-- { + g.closer[i]() + } + g.closer = nil +} + +func (g *Global) sendln(ctx context.Context, w *gmnlisp.World, arg gmnlisp.Node) (gmnlisp.Node, error) { + io.WriteString(g.term, arg.String()) + g.term.Write([]byte{'\r'}) + return gmnlisp.Null, nil +} + +func (g *Global) spawn(ctx context.Context, w *gmnlisp.World, args []gmnlisp.Node) (gmnlisp.Node, error) { + + argStrings := make([]string, 0, len(args)) + for _, s := range args { + argStrings = append(argStrings, s.String()) + } + + sh := g.term.Command(argStrings[0], argStrings[1:]...) + if err := sh.Start(); err != nil { + return nil, err + } + g.closer = append(g.closer, func() { sh.Wait() }) + return gmnlisp.Null, nil +} + +func (g *Global) expect(ctx context.Context, w *gmnlisp.World, args []gmnlisp.Node) (gmnlisp.Node, error) { + patterns := make([]string, 0, len(args)) + for _, arg := range args { + patterns = append(patterns, arg.String()) + } + result := g.w.Expect(patterns...) + return gmnlisp.Integer(result), nil +} + func mains() error { term, err := NewTerm() if err != nil { @@ -16,16 +61,35 @@ func mains() error { watcher := NewWatcher(term) - sh := term.Command("cmd.exe") - if err := sh.Start(); err != nil { - return err + g := &Global{ + term: term, + w: watcher, } + defer g.Close() - i := watcher.ExpectWithTimeout(time.Duration(10*time.Second), "100") - // i := watcher.Expect("100") - io.WriteString(term, "\x03exit\r") - println(i) - return sh.Wait() + lisp := gmnlisp.New() + + lisp = lisp.Flet( + gmnlisp.Functions{ + gmnlisp.NewSymbol("sendln"): gmnlisp.Function1(g.sendln), + gmnlisp.NewSymbol("spawn"): &gmnlisp.Function{Min: 1, F: g.spawn}, + gmnlisp.NewSymbol("expect*"): &gmnlisp.Function{Min: 1, F: g.expect}, + }) + + _, err = lisp.Interpret(context.Background(), ` + (spawn "cmd.exe") + (block main + (while t + (case (expect* "xxx" "yyy") + ((0) + (sendln (format nil "~Aexit" (convert 3 ))) + (return-from main nil) + ) + ((1) + (sendln (format nil "~Arem" (convert 3 ))) + ) + )))`) + return err } func main() {