Std out/in/err of processes

This commit is contained in:
bloeys
2022-07-12 19:06:03 +04:00
parent dd09750b04
commit 1572ba4743

122
main.go
View File

@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"io"
"math" "math"
"os" "os"
"os/exec" "os/exec"
@ -26,6 +27,13 @@ import (
"golang.org/x/image/font" "golang.org/x/image/font"
) )
type Cmd struct {
C *exec.Cmd
Stdout io.ReadCloser
Stdin io.WriteCloser
Stderr io.ReadCloser
}
var _ engine.Game = &program{} var _ engine.Game = &program{}
type program struct { type program struct {
@ -50,6 +58,8 @@ type program struct {
cursorPos *gglm.Vec3 cursorPos *gglm.Vec3
scrollPos int64 scrollPos int64
scrollSpd int64 scrollSpd int64
activeCmd *Cmd
} }
const ( const (
@ -207,6 +217,7 @@ func (p *program) Update() {
p.MainUpdate() p.MainUpdate()
} }
// @TODO: These probably need a mutex
func (p *program) WriteToTextBuf(text []rune) { func (p *program) WriteToTextBuf(text []rune) {
newHeadPos := p.textBufHead + int64(len(text)) newHeadPos := p.textBufHead + int64(len(text))
@ -237,10 +248,10 @@ func (p *program) MainUpdate() {
if input.KeyClicked(sdl.K_RETURN) || input.KeyClicked(sdl.K_KP_ENTER) { if input.KeyClicked(sdl.K_RETURN) || input.KeyClicked(sdl.K_KP_ENTER) {
p.WriteToCmdBuf([]rune{'\n'}) p.WriteToCmdBuf([]rune{'\n'})
p.RunCmd() p.HandleReturn()
} }
mouseWheelYNorm := int64(input.GetMouseWheelYNorm()) mouseWheelYNorm := -int64(input.GetMouseWheelYNorm())
if mouseWheelYNorm != 0 { if mouseWheelYNorm != 0 {
p.scrollPos = clamp(p.scrollPos+p.scrollSpd*mouseWheelYNorm, 0, p.textBufHead) p.scrollPos = clamp(p.scrollPos+p.scrollSpd*mouseWheelYNorm, 0, p.textBufHead)
} }
@ -259,12 +270,25 @@ func (p *program) MainUpdate() {
p.DrawCursor() p.DrawCursor()
} }
func (p *program) RunCmd() { func (p *program) HandleReturn() {
cmdRunes := p.cmdBuf[:p.cmdBufHead] cmdRunes := p.cmdBuf[:p.cmdBufHead]
p.WriteToTextBuf(cmdRunes)
p.cmdBufHead = 0 p.cmdBufHead = 0
if p.activeCmd != nil {
_, err := p.activeCmd.Stdin.Write([]byte(string(cmdRunes)))
if err != nil {
p.PrintToTextBuf(fmt.Sprintf("Writing to stdin pipe of '%s' failed. Error: %s\n", p.activeCmd.C.Path, err.Error()))
p.ClearActiveCmd()
return
}
return
}
p.WriteToTextBuf(cmdRunes)
cmdStr := strings.TrimSpace(string(cmdRunes)) cmdStr := strings.TrimSpace(string(cmdRunes))
cmdSplit := strings.Split(cmdStr, " ") cmdSplit := strings.Split(cmdStr, " ")
@ -275,13 +299,99 @@ func (p *program) RunCmd() {
} }
cmd := exec.Command(cmdName, args...) cmd := exec.Command(cmdName, args...)
combOutBytes, err := cmd.CombinedOutput()
outPipe, err := cmd.StdoutPipe()
if err != nil {
p.PrintToTextBuf(fmt.Sprintf("Creating stdout pipe of '%s' failed. Error: %s\n", cmdName, err.Error()))
return
}
inPipe, err := cmd.StdinPipe()
if err != nil {
p.PrintToTextBuf(fmt.Sprintf("Creating stdin pipe of '%s' failed. Error: %s\n", cmdName, err.Error()))
return
}
errPipe, err := cmd.StderrPipe()
if err != nil {
p.PrintToTextBuf(fmt.Sprintf("Creating stderr pipe of '%s' failed. Error: %s\n", cmdName, err.Error()))
return
}
err = cmd.Start()
if err != nil { if err != nil {
p.PrintToTextBuf(fmt.Sprintf("Running '%s' failed. Error: %s\n", cmdName, err.Error())) p.PrintToTextBuf(fmt.Sprintf("Running '%s' failed. Error: %s\n", cmdName, err.Error()))
return return
} }
p.activeCmd = &Cmd{
C: cmd,
Stdout: outPipe,
Stdin: inPipe,
Stderr: errPipe,
}
p.WriteToTextBuf([]rune(string(combOutBytes))) //Stdout
go func() {
defer p.ClearActiveCmd()
buf := make([]byte, 1024)
for p.activeCmd != nil {
readBytes, err := p.activeCmd.Stdout.Read(buf)
if err != nil {
if err == io.EOF {
break
}
p.PrintToTextBuf("Stdout pipe failed. Error: " + err.Error())
return
}
if readBytes == 0 {
continue
}
p.PrintToTextBuf(string(buf[:readBytes]))
}
}()
//Stderr
go func() {
defer p.ClearActiveCmd()
buf := make([]byte, 1024)
for p.activeCmd != nil {
readBytes, err := p.activeCmd.Stderr.Read(buf)
if err != nil {
if err == io.EOF {
break
}
p.PrintToTextBuf("Stderr pipe failed. Error: " + err.Error())
return
}
if readBytes == 0 {
continue
}
p.PrintToTextBuf(string(buf[:readBytes]))
}
}()
}
func (p *program) ClearActiveCmd() {
if p.activeCmd == nil {
return
}
p.activeCmd = nil
} }
func (p *program) PrintToTextBuf(s string) { func (p *program) PrintToTextBuf(s string) {