github.com/madlambda/nash@v0.2.2-0.20230113003044-f2284521680b/internal/sh/builtin.go (about) 1 package sh 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/madlambda/nash/errors" 8 "github.com/madlambda/nash/internal/sh/builtin" 9 "github.com/madlambda/nash/sh" 10 ) 11 12 type ( 13 // builtinFn maps a builtin function to a nash sh.FnDef 14 // avoiding a lot of duplicated code and decoupling the 15 // builtin functions of some unnecessary details on how 16 // the sh.Fn works (lots of complexity to provide features of 17 // other kinds of runners/functions). 18 builtinFn struct { 19 stdin io.Reader 20 stdout, stderr io.Writer 21 22 done chan struct{} 23 err error 24 results []sh.Obj 25 26 name string 27 fn builtin.Fn 28 } 29 ) 30 31 func NewBuiltinFn( 32 name string, 33 fn builtin.Fn, 34 in io.Reader, 35 out io.Writer, 36 outerr io.Writer, 37 ) *builtinFn { 38 return &builtinFn{ 39 name: name, 40 fn: fn, 41 stdin: in, 42 stdout: out, 43 stderr: outerr, 44 } 45 } 46 47 func (f *builtinFn) Name() string { 48 return f.name 49 } 50 51 func (f *builtinFn) ArgNames() []sh.FnArg { 52 return f.fn.ArgNames() 53 } 54 55 func (f *builtinFn) Start() error { 56 f.done = make(chan struct{}) 57 58 go func() { 59 f.results, f.err = f.fn.Run(f.stdin, f.stdout, f.stderr) 60 f.done <- struct{}{} 61 }() 62 63 return nil 64 } 65 66 func (f *builtinFn) Wait() error { 67 <-f.done 68 return f.err 69 } 70 71 func (f *builtinFn) Results() []sh.Obj { 72 return f.results 73 } 74 75 func (f *builtinFn) String() string { 76 return fmt.Sprintf("<builtin function %q>", f.Name()) 77 } 78 79 func (f *builtinFn) SetArgs(args []sh.Obj) error { 80 return f.fn.SetArgs(args) 81 } 82 83 func (f *builtinFn) SetEnviron(env []string) { 84 // do nothing 85 // terrible design smell having functions that do nothing =/ 86 } 87 88 func (f *builtinFn) SetStdin(r io.Reader) { 89 f.stdin = r 90 } 91 func (f *builtinFn) SetStderr(w io.Writer) { 92 f.stderr = w 93 } 94 func (f *builtinFn) SetStdout(w io.Writer) { 95 f.stdout = w 96 } 97 func (f *builtinFn) StdoutPipe() (io.ReadCloser, error) { 98 return nil, errors.NewError("builtin functions doesn't works with pipes") 99 } 100 func (f *builtinFn) Stdin() io.Reader { return f.stdin } 101 func (f *builtinFn) Stdout() io.Writer { return f.stdout } 102 func (f *builtinFn) Stderr() io.Writer { return f.stderr }