feat(hilbish.run): accept sink as streams, accept stdin input

pull/291/head
sammyette 2024-04-27 20:06:17 -04:00
parent 9491e3e67f
commit b09be2e131
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
2 changed files with 53 additions and 23 deletions

66
api.go
View File

@ -16,6 +16,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io"
"os" "os"
"os/exec" "os/exec"
"runtime" "runtime"
@ -153,6 +154,35 @@ func unsetVimMode() {
util.SetField(l, hshMod, "vimMode", rt.NilValue) util.SetField(l, hshMod, "vimMode", rt.NilValue)
} }
func handleStream(v rt.Value, strms *streams, errStream bool) error {
ud, ok := v.TryUserData()
if !ok {
return errors.New("expected metatable argument")
}
val := ud.Value()
var varstrm io.Writer
if f, ok := val.(*iolib.File); ok {
varstrm = f.Handle()
}
if f, ok := val.(*sink); ok {
varstrm = f.writer
}
if varstrm == nil {
return errors.New("expected either a sink or file")
}
if errStream {
strms.stderr = varstrm
} else {
strms.stdout = varstrm
}
return nil
}
// run(cmd, streams) -> exitCode (number), stdout (string), stderr (string) // run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)
// Runs `cmd` in Hilbish's shell script interpreter. // Runs `cmd` in Hilbish's shell script interpreter.
// #param cmd string // #param cmd string
@ -168,7 +198,7 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, err return nil, err
} }
var strms *streams strms := &streams{}
var terminalOut bool var terminalOut bool
if len(c.Etc()) != 0 { if len(c.Etc()) != 0 {
tout := c.Etc()[0] tout := c.Etc()[0]
@ -181,35 +211,31 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, errors.New("bad argument to run (expected boolean or table, got " + tout.TypeName() + ")") return nil, errors.New("bad argument to run (expected boolean or table, got " + tout.TypeName() + ")")
} }
var stdoutStream, stderrStream *iolib.File handleStream(luastreams.Get(rt.StringValue("stdout")), strms, false)
handleStream(luastreams.Get(rt.StringValue("stderr")), strms, true)
stdoutstrm := luastreams.Get(rt.StringValue("stdout")) stdinstrm := luastreams.Get(rt.StringValue("stdin"))
if !stdoutstrm.IsNil() { if !stdinstrm.IsNil() {
f, ok := iolib.ValueToFile(stdoutstrm) ud, ok := stdinstrm.TryUserData()
if !ok { if !ok {
return nil, errors.New("bad argument to run streams table (expected file, got " + stdoutstrm.TypeName() + ")") return nil, errors.New("bad type as run stdin stream (expected userdata as either sink or file, got " + stdinstrm.TypeName() + ")")
} }
stdoutStream = f val := ud.Value()
var varstrm io.Reader
if f, ok := val.(*iolib.File); ok {
varstrm = f.Handle()
} }
stderrstrm := luastreams.Get(rt.StringValue("stderr")) if f, ok := val.(*sink); ok {
if !stderrstrm.IsNil() { varstrm = f.reader
f, ok := iolib.ValueToFile(stderrstrm)
if !ok {
return nil, errors.New("bad argument to run streams table (expected file, got " + stderrstrm.TypeName() + ")")
} }
stderrStream = f if varstrm == nil {
return nil, errors.New("bad type as run stdin stream (expected userdata as either sink or file)")
} }
strms = &streams{} strms.stdin = varstrm
if stdoutStream != nil {
strms.stdout = stdoutStream.Handle()
}
if stderrStream != nil {
strms.stderr = stderrStream.Handle()
} }
} else { } else {
if !terminalOut { if !terminalOut {

View File

@ -283,7 +283,11 @@ func execCommand(cmd string, strms *streams) (io.Writer, io.Writer, error) {
strms.stderr = os.Stderr strms.stderr = os.Stderr
} }
interp.StdIO(os.Stdin, strms.stdout, strms.stderr)(runner) if strms.stdin == nil {
strms.stdin = os.Stdin
}
interp.StdIO(strms.stdin, strms.stdout, strms.stderr)(runner)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
printer := syntax.NewPrinter() printer := syntax.NewPrinter()