github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/cmds/elvish/eval/builtin_fn_io.go (about)

     1  package eval
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  
    10  	"github.com/u-root/u-root/cmds/elvish/eval/vals"
    11  )
    12  
    13  // Input and output.
    14  
    15  func init() {
    16  	addBuiltinFns(map[string]interface{}{
    17  		// Value output
    18  		"put": put,
    19  
    20  		// Bytes output
    21  		"print":  print,
    22  		"echo":   echo,
    23  		"pprint": pprint,
    24  		"repr":   repr,
    25  
    26  		// Bytes to value
    27  		"slurp":      slurp,
    28  		"from-lines": fromLines,
    29  		"from-json":  fromJSON,
    30  
    31  		// Value to bytes
    32  		"to-lines": toLines,
    33  		"to-json":  toJSON,
    34  
    35  		// File and pipe
    36  		"fopen":   fopen,
    37  		"fclose":  fclose,
    38  		"pipe":    pipe,
    39  		"prclose": prclose,
    40  		"pwclose": pwclose,
    41  	})
    42  }
    43  
    44  func put(fm *Frame, args ...interface{}) {
    45  	out := fm.ports[1].Chan
    46  	for _, a := range args {
    47  		out <- a
    48  	}
    49  }
    50  
    51  func print(fm *Frame, rawOpts RawOptions, args ...interface{}) {
    52  	opts := struct{ Sep string }{" "}
    53  	rawOpts.Scan(&opts)
    54  
    55  	out := fm.ports[1].File
    56  	for i, arg := range args {
    57  		if i > 0 {
    58  			out.WriteString(opts.Sep)
    59  		}
    60  		out.WriteString(vals.ToString(arg))
    61  	}
    62  }
    63  
    64  func echo(fm *Frame, opts RawOptions, args ...interface{}) {
    65  	print(fm, opts, args...)
    66  	fm.ports[1].File.WriteString("\n")
    67  }
    68  
    69  func pprint(fm *Frame, args ...interface{}) {
    70  	out := fm.ports[1].File
    71  	for _, arg := range args {
    72  		out.WriteString(vals.Repr(arg, 0))
    73  		out.WriteString("\n")
    74  	}
    75  }
    76  
    77  func repr(fm *Frame, args ...interface{}) {
    78  	out := fm.ports[1].File
    79  	for i, arg := range args {
    80  		if i > 0 {
    81  			out.WriteString(" ")
    82  		}
    83  		out.WriteString(vals.Repr(arg, vals.NoPretty))
    84  	}
    85  	out.WriteString("\n")
    86  }
    87  
    88  func slurp(fm *Frame) (string, error) {
    89  	b, err := ioutil.ReadAll(fm.ports[0].File)
    90  	return string(b), err
    91  }
    92  
    93  func fromLines(fm *Frame) {
    94  	linesToChan(fm.ports[0].File, fm.ports[1].Chan)
    95  }
    96  
    97  // fromJSON parses a stream of JSON data into Value's.
    98  func fromJSON(fm *Frame) error {
    99  	in := fm.ports[0].File
   100  	out := fm.ports[1].Chan
   101  
   102  	dec := json.NewDecoder(in)
   103  	var v interface{}
   104  	for {
   105  		err := dec.Decode(&v)
   106  		if err != nil {
   107  			if err == io.EOF {
   108  				return nil
   109  			}
   110  			return err
   111  		}
   112  		out <- FromJSONInterface(v)
   113  	}
   114  }
   115  
   116  func toLines(fm *Frame, inputs Inputs) {
   117  	out := fm.ports[1].File
   118  
   119  	inputs(func(v interface{}) {
   120  		fmt.Fprintln(out, vals.ToString(v))
   121  	})
   122  }
   123  
   124  // toJSON converts a stream of Value's to JSON data.
   125  func toJSON(fm *Frame, inputs Inputs) {
   126  	out := fm.ports[1].File
   127  
   128  	enc := json.NewEncoder(out)
   129  	inputs(func(v interface{}) {
   130  		err := enc.Encode(v)
   131  		maybeThrow(err)
   132  	})
   133  }
   134  
   135  func fopen(fm *Frame, name string) (vals.File, error) {
   136  	// TODO support opening files for writing etc as well.
   137  	f, err := os.Open(name)
   138  	return vals.File{f}, err
   139  }
   140  
   141  func fclose(f vals.File) error {
   142  	return f.Inner.Close()
   143  }
   144  
   145  func pipe() (vals.Pipe, error) {
   146  	r, w, err := os.Pipe()
   147  	return vals.Pipe{r, w}, err
   148  }
   149  
   150  func prclose(p vals.Pipe) error {
   151  	return p.ReadEnd.Close()
   152  }
   153  
   154  func pwclose(p vals.Pipe) error {
   155  	return p.WriteEnd.Close()
   156  }