github.com/elves/Elvish@v0.12.0/eval/builtin_fn_misc.go (about) 1 package eval 2 3 // Builtin functions. 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "math/rand" 9 "net" 10 "path/filepath" 11 "time" 12 "unicode/utf8" 13 14 "github.com/elves/elvish/eval/vals" 15 "github.com/elves/elvish/parse" 16 ) 17 18 // Builtins that have not been put into their own groups go here. 19 20 func init() { 21 addBuiltinFns(map[string]interface{}{ 22 "nop": nop, 23 "kind-of": kindOf, 24 "constantly": constantly, 25 26 "resolve": resolve, 27 28 "-source": source, 29 30 // Time 31 "esleep": sleep, 32 "-time": _time, 33 34 "-ifaddrs": _ifaddrs, 35 }) 36 37 // For rand and randint. 38 rand.Seed(time.Now().UTC().UnixNano()) 39 } 40 41 func nop(opts RawOptions, args ...interface{}) { 42 // Do nothing 43 } 44 45 func kindOf(fm *Frame, args ...interface{}) { 46 out := fm.ports[1].Chan 47 for _, a := range args { 48 out <- vals.Kind(a) 49 } 50 } 51 52 func constantly(args ...interface{}) Callable { 53 // XXX Repr of this fn is not right 54 return NewBuiltinFn( 55 "created by constantly", 56 func(fm *Frame) { 57 out := fm.ports[1].Chan 58 for _, v := range args { 59 out <- v 60 } 61 }, 62 ) 63 } 64 65 func resolve(fm *Frame, head string) string { 66 // Emulate static resolution of a command head. This needs to be kept in 67 // sync with (*compiler).form. 68 69 _, special := builtinSpecials[head] 70 if special { 71 return "special" 72 } else { 73 explode, ns, name := ParseVariableRef(head) 74 if !explode && fm.ResolveVar(ns, name+FnSuffix) != nil { 75 return "$" + head + FnSuffix 76 } else { 77 return "(external " + parse.Quote(head) + ")" 78 } 79 } 80 } 81 82 func source(fm *Frame, fname string) error { 83 path, err := filepath.Abs(fname) 84 if err != nil { 85 return err 86 } 87 code, err := readFileUTF8(path) 88 if err != nil { 89 return err 90 } 91 n, err := parse.Parse(fname, code) 92 if err != nil { 93 return err 94 } 95 scriptGlobal := fm.local.static() 96 for name := range fm.up.static() { 97 scriptGlobal.set(name) 98 } 99 op, err := compile(fm.Builtin.static(), 100 scriptGlobal, n, NewScriptSource(fname, path, code)) 101 if err != nil { 102 return err 103 } 104 return fm.Eval(op) 105 } 106 107 func readFileUTF8(fname string) (string, error) { 108 bytes, err := ioutil.ReadFile(fname) 109 if err != nil { 110 return "", err 111 } 112 if !utf8.Valid(bytes) { 113 return "", fmt.Errorf("%s: source is not valid UTF-8", fname) 114 } 115 return string(bytes), nil 116 } 117 118 func sleep(fm *Frame, t float64) error { 119 d := time.Duration(float64(time.Second) * t) 120 select { 121 case <-fm.Interrupts(): 122 return ErrInterrupted 123 case <-time.After(d): 124 return nil 125 } 126 } 127 128 func _time(fm *Frame, f Callable) error { 129 t0 := time.Now() 130 err := f.Call(fm, NoArgs, NoOpts) 131 t1 := time.Now() 132 133 dt := t1.Sub(t0) 134 fmt.Fprintln(fm.ports[1].File, dt) 135 136 return err 137 } 138 139 func _ifaddrs(fm *Frame) error { 140 addrs, err := net.InterfaceAddrs() 141 if err != nil { 142 return err 143 } 144 out := fm.ports[1].Chan 145 for _, addr := range addrs { 146 out <- addr.String() 147 } 148 return nil 149 }