diff --git a/main.go b/main.go index ab47e80..66a958e 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,19 @@ import ( "github.com/hymkor/go-windows1x-virtualterminal" ) +func loop(ptmx pty.Pty) error { + watcher := NewWatcher(ptmx) + + sh := ptmx.Command("cmd.exe") + if err := sh.Start(); err != nil { + return err + } + + _ = watcher.Expect("100") + io.WriteString(ptmx, "exit\r") + return sh.Wait() +} + func mains() error { disableStdout, err := virtualterminal.EnableStdout() if err != nil { @@ -43,16 +56,7 @@ func mains() error { } defer term.Restore(int(os.Stdin.Fd()), oldState) - go io.Copy(ptmx, os.Stdin) - go io.Copy(os.Stdout, ptmx) - - // sh := ptmx.Command(fields[0], fields[1:]...) - // if err := sh.Start(); err != nil { - // return err - // } - // return sh.Wait() - - return nil + return loop(ptmx) } func main() { diff --git a/watcher.go b/watcher.go new file mode 100644 index 0000000..6fa7103 --- /dev/null +++ b/watcher.go @@ -0,0 +1,59 @@ +package main + +import ( + "io" + "os" + "strings" + + "github.com/aymanbagabas/go-pty" +) + +type Watcher struct { + ch <-chan string + lastline string +} + +func NewWatcher(ptmx pty.Pty) *Watcher { + pipeline := make(chan string, 1024) + go io.Copy(ptmx, os.Stdin) + go func() { + for { + var buffer [1024]byte + n, err := ptmx.Read(buffer[:]) + if err != nil { + close(pipeline) + return + } + // If the code below spends a lot of time, + // It hangs up to io.Copy(ptmx, os.Stdin) + // The reason is unknown. + os.Stdout.Write(buffer[:n]) + pipeline <- string(buffer[:n]) + } + }() + + return &Watcher{ch: pipeline} +} + +func (W *Watcher) updateLastLine() { + newLinePos := strings.LastIndexByte(W.lastline, '\n') + if newLinePos >= 0 { + W.lastline = W.lastline[newLinePos+1:] + } else { + W.lastline = "" + } +} + +func (W *Watcher) Expect(words ...string) int { + for frag := range W.ch { + W.lastline += frag + for i, word := range words { + if strings.Contains(W.lastline, word) { + W.updateLastLine() + return i + } + } + W.updateLastLine() + } + return -1 +}