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