package main import ( "bufio" "fmt" "io" "log" "time" // "math" "container/ring" "os/exec" "github.com/jroimartin/gocui" "github.com/pelletier/go-toml" ) var settings *toml.Tree var stdout_ring *ring.Ring var srv_stdin io.WriteCloser // reload settings (and maybe other things too) func reload() { settings, _ = toml.LoadFile("serverwrapper.toml") } //builds the cmd which is called to run the server func build_cmd() (string, []string) { return "ping", []string{"-t", "8.8.8.8"} } //run the server-thread func server_run() { //create the command cmd_str, cmd_args := build_cmd() cmd := exec.Command(cmd_str, cmd_args...) //connect pipes stdout, err := cmd.StdoutPipe() cmd.Stderr = cmd.Stdout srv_stdin, err = cmd.StdinPipe() //this one is global, because we write to it elsewhere // run the process err = cmd.Start() if err != nil { log.Panicln("Failed to call server command \"" + cmd.String() + "\"") } //read pipes and write them to the ring buffer buf := bufio.NewScanner(stdout) for { if buf.Scan() { stdout_ring.Value = buf.Text() stdout_ring = stdout_ring.Next() } else { time.Sleep(300 * time.Millisecond) } } } //refresh the screen func refresh(g *gocui.Gui) error { v, err := g.View("srv_log") if err != nil { log.Panicln(err) } v.Clear() _, vH := v.Size() r := stdout_ring v.Overwrite = true for i := 0; i < vH; i++ { v.SetCursor(4, vH - i) if r.Value != nil { fmt.Fprint(v, r.Value) } r = r.Prev() } return nil } func main() { //initialize settings by "re"loading them from disk reload() //initialize the stdout/err ringbuffer stdout_ring = ring.New(255) //init the CUI g, err := gocui.NewGui(gocui.OutputNormal) if err != nil { log.Panicln(err) } defer g.Close() g.SetManagerFunc(layout) if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { log.Panicln(err) } go server_run() //run the CUI main loop if err := g.MainLoop(); err != nil && err != gocui.ErrQuit { log.Panicln(err) } } //create the CUI layout func layout(g *gocui.Gui) error { maxX, maxY := g.Size() if _, err := g.SetView("srv_log", 0, 0, maxX-1, int(float32(maxY) * 0.8)); err != nil { if err != gocui.ErrUnknownView { return err } } refresh(g) return nil } func quit(g *gocui.Gui, v *gocui.View) error { return gocui.ErrQuit }