Skip to content

Commit

Permalink
Add support for string | run(...) to set stdin (#238)
Browse files Browse the repository at this point in the history
* Add support for `string | run(...)` to set stdin

* Fix lint

* make test more likely work across os

* try#2 at wc output check
  • Loading branch information
ldemailly authored Sep 17, 2024
1 parent a2041f5 commit dda178b
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 0 deletions.
11 changes: 11 additions & 0 deletions eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ func (s *State) evalInternal(node any) object.Object { //nolint:funlen,gocognit,
if node.Token.Type() == token.OR && left == object.TRUE {
return object.TRUE
}
// Pipe operator, for now only for string | call expressions:
if node.Token.Type() == token.BITOR && left.Type() == object.STRING && node.Right.Value().Type() == token.LPAREN {
return s.evalPipe(left, node.Right)
}
right := s.Eval(node.Right)
if right.Type() == object.ERROR {
return right
Expand Down Expand Up @@ -308,6 +312,13 @@ func (s *State) evalInternal(node any) object.Object { //nolint:funlen,gocognit,
return s.Errorf("unknown node type: %T", node)
}

func (s *State) evalPipe(left object.Object, right ast.Node) object.Object {
s.PipeVal = []byte(left.(object.String).Value)
res := s.evalInternal(right)
s.PipeVal = nil
return res
}

func (s *State) evalIndexExpression(left object.Object, node *ast.IndexExpression) object.Object {
if left.Type() == object.ERROR {
return left
Expand Down
5 changes: 5 additions & 0 deletions eval/eval_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type State struct {
// To enforce a max duration or cancel evals.
Context context.Context //nolint:containedctx // we need a context for callbacks from extensions and to set it without API change.
Cancel context.CancelFunc
PipeVal []byte // value to return from pipe() function
}

func NewState() *State {
Expand Down Expand Up @@ -217,3 +218,7 @@ func (s *State) NumMacros() int {
}

// TriggerNoCache() is replaced by DontCache boolean in object.Extension.

func (s *State) GetPipeValue() []byte {
return s.PipeVal
}
3 changes: 3 additions & 0 deletions extensions/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ func createShellFunctions() {
var sout, serr bytes.Buffer
cmd.Stdout = &sout
cmd.Stderr = &serr
if obj := s.GetPipeValue(); obj != nil {
cmd.Stdin = bytes.NewReader(obj)
}
err := cmd.Run()
res := object.MakeQuad(stdout, object.String{Value: sout.String()},
stderr, object.String{Value: serr.String()})
Expand Down
1 change: 1 addition & 0 deletions tests/shell.gr
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ IsErr("non zero exit", run("false"), "exit status 1")
NoErr("exec captures", exec("false").err, `^exit status 1$`)
NoErr("exec captures", exec("echo", "-n", "foo").stdout, "^foo$")
NoErr("exec captures", exec("ls", "/no/such/file").stderr, "No such file or directory")
NoErr("pipe exec", ("abcde" | exec("wc", "-c")).stdout, "5\n$") // wc output dffers on different systems

0 comments on commit dda178b

Please sign in to comment.