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 }