github.com/NeowayLabs/nash@v0.2.2-0.20200127205349-a227041ffd50/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 }