Source File
builtin_fn_misc.go
Belonging Package
src.elv.sh/pkg/eval
package eval// Misc builtin functions.import ()// Builtins that have not been put into their own groups go here.func () {addBuiltinFns(map[string]interface{}{"nop": nop,"kind-of": kindOf,"constantly": constantly,"resolve": resolve,"eval": eval,"use-mod": useMod,"deprecate": deprecate,// Time"sleep": sleep,"time": timeCmd,"-ifaddrs": _ifaddrs,})// For rand and randint.rand.Seed(time.Now().UTC().UnixNano())}//elvdoc:fn nop//// ```elvish// nop &any-opt= $value...// ```//// Accepts arbitrary arguments and options and does exactly nothing.//// Examples://// ```elvish-transcript// ~> nop// ~> nop a b c// ~> nop &k=v// ```//// Etymology: Various languages, in particular NOP in// [assembly languages](https://en.wikipedia.org/wiki/NOP).func ( RawOptions, ...interface{}) {// Do nothing}//elvdoc:fn kind-of//// ```elvish// kind-of $value...// ```//// Output the kinds of `$value`s. Example://// ```elvish-transcript// ~> kind-of lorem [] [&]// ▶ string// ▶ list// ▶ map// ```//// The terminology and definition of "kind" is subject to change.func ( *Frame, ...interface{}) {:= .OutputChan()for , := range {<- vals.Kind()}}//elvdoc:fn constantly//// ```elvish// constantly $value...// ```//// Output a function that takes no arguments and outputs `$value`s when called.// Examples://// ```elvish-transcript// ~> f=(constantly lorem ipsum)// ~> $f// ▶ lorem// ▶ ipsum// ```//// The above example is actually equivalent to simply `f = []{ put lorem ipsum }`;// it is most useful when the argument is **not** a literal value, e.g.//// ```elvish-transcript// ~> f = (constantly (uname))// ~> $f// ▶ Darwin// ~> $f// ▶ Darwin// ```//// The above code only calls `uname` once, while if you do `f = []{ put (uname) }`,// every time you invoke `$f`, `uname` will be called.//// Etymology: [Clojure](https://clojuredocs.org/clojure.core/constantly).func ( ...interface{}) Callable {// TODO(xiaq): Repr of this function is not right.return NewGoFn("created by constantly",func( *Frame) {:= .OutputChan()for , := range {<-}},)}//elvdoc:fn resolve//// ```elvish// resolve $command// ```//// Output what `$command` resolves to in symbolic form. Command resolution is// described in the [language reference](language.html#ordinary-command).//// Example://// ```elvish-transcript// ~> resolve echo// ▶ <builtin echo>// ~> fn f { }// ~> resolve f// ▶ <closure 0xc4201c24d0>// ~> resolve cat// ▶ <external cat>// ```func ( *Frame, string) string {, := resolveCmdHeadInternally(, , nil)switch {case != nil:return "special"case != nil:return "$" + + FnSuffixdefault:return "(external " + parse.Quote() + ")"}}//elvdoc:fn eval//// ```elvish// eval $code &ns=$nil &on-end=$nil// ```//// Evaluates `$code`, which should be a string. The evaluation happens in a// new, restricted namespace, whose initial set of variables can be specified by// the `&ns` option. After evaluation completes, the new namespace is passed to// the callback specified by `&on-end` if it is not nil.//// The namespace specified by `&ns` is never modified; it will not be affected// by the creation or deletion of variables by `$code`. However, the values of// the variables may be mutated by `$code`.//// If the `&ns` option is `$nil` (the default), a temporary namespace built by// amalgamating the local and upvalue scopes of the caller is used.//// If `$code` fails to parse or compile, the parse error or compilation error is// raised as an exception.//// Basic examples that do not modify the namespace or any variable://// ```elvish-transcript// ~> eval 'put x'// ▶ x// ~> x = foo// ~> eval 'put $x'// ▶ foo// ~> ns = (ns [&x=bar])// ~> eval &ns=$ns 'put $x'// ▶ bar// ```//// Examples that modify existing variables://// ```elvish-transcript// ~> y = foo// ~> eval 'y = bar'// ~> put $y// ▶ bar// ```//// Examples that creates new variables and uses the callback to access it://// ```elvish-transcript// ~> eval 'z = lorem'// ~> put $z// compilation error: variable $z not found// [ttz 2], line 1: put $z// ~> saved-ns = $nil// ~> eval &on-end=[ns]{ saved-ns = $ns } 'z = lorem'// ~> put $saved-ns[z]// ▶ lorem// ```type evalOpts struct {Ns *NsOnEnd Callable}func (*evalOpts) () {}func ( *Frame, evalOpts, string) error {:= parse.Source{Name: fmt.Sprintf("[eval %d]", nextEvalCount()), Code: }:= .Nsif == nil {= CombineNs(.up, .local)}// The stacktrace already contains the line that calls "eval", so we pass// nil as the second argument., := .Eval(, nil, )if .OnEnd != nil {:= .fork("on-end callback of eval"):= .OnEnd.Call(, []interface{}{}, NoOpts)if == nil {return}}return}// Used to generate unique names for each source passed to eval.var (evalCount intevalCountMutex sync.Mutex)func () int {evalCountMutex.Lock()defer evalCountMutex.Unlock()evalCount++return evalCount}//elvdoc:fn use-mod//// ```elvish// use-mod $use-spec// ```//// Imports a module, and outputs the namespace for the module.//// Most code should use the [use](language.html#importing-modules-with-use)// special command instead.//// Examples://// ```elvish-transcript// ~> echo 'x = value' > a.elv// ~> put (use-mod ./a)[x]// ▶ value// ```func ( *Frame, string) (*Ns, error) {return use(, , nil)}func ( string) (string, error) {, := ioutil.ReadFile()if != nil {return "",}if !utf8.Valid() {return "", fmt.Errorf("%s: source is not valid UTF-8", )}return string(), nil}//elvdoc:fn deprecate//// ```elvish// deprecate $msg// ```//// Shows the given deprecation message to stderr. If called from a function// or module, also shows the call site of the function or import site of the// module. Does nothing if the combination of the call site and the message has// been shown before.//// ```elvish-transcript// ~> deprecate msg// deprecation: msg// ~> fn f { deprecate msg }// ~> f// deprecation: msg// [tty 19], line 1: f// ~> exec// ~> deprecate msg// deprecation: msg// ~> fn f { deprecate msg }// ~> f// deprecation: msg// [tty 3], line 1: f// ~> f # a different call site; shows deprecate message// deprecation: msg// [tty 4], line 1: f// ~> fn g { f }// ~> g// deprecation: msg// [tty 5], line 1: fn g { f }// ~> g # same call site, no more deprecation message// ```func ( *Frame, string) {var *diag.Contextif .traceback.Next != nil {= .traceback.Next.Head}.Deprecate(, , 0)}// TimeAfter is used by the sleep command to obtain a channel that is delivered// a value after the specified time.//// It is a variable to allow for unit tests to efficiently test the behavior of// the `sleep` command, both by eliminating an actual sleep and verifying the// duration was properly parsed.var TimeAfter = func( *Frame, time.Duration) <-chan time.Time {return time.After()}//elvdoc:fn sleep//// ```elvish// sleep $duration// ```//// Pauses for at least the specified duration. The actual pause duration depends// on the system.//// This only affects the current Elvish context. It does not affect any other// contexts that might be executing in parallel as a consequence of a command// such as [`peach`](#peach).//// A duration can be a simple [number](../language.html#number) (with optional// fractional value) without an explicit unit suffix, with an implicit unit of// seconds.//// A duration can also be a string written as a sequence of decimal numbers,// each with optional fraction, plus a unit suffix. For example, "300ms",// "1.5h" or "1h45m7s". Valid time units are "ns", "us" (or "µs"), "ms", "s",// "m", "h".//// Passing a negative duration causes an exception; this is different from the// typical BSD or GNU `sleep` command that silently exits with a success status// without pausing when given a negative duration.//// See the [Go documentation](https://golang.org/pkg/time/#ParseDuration) for// more information about how durations are parsed.//// Examples://// ```elvish-transcript// ~> sleep 0.1 # sleeps 0.1 seconds// ~> sleep 100ms # sleeps 0.1 seconds// ~> sleep 1.5m # sleeps 1.5 minutes// ~> sleep 1m30s # sleeps 1.5 minutes// ~> sleep -1// Exception: sleep duration must be >= zero// [tty 8], line 1: sleep -1// ```func ( *Frame, interface{}) error {var time.Durationswitch duration := .(type) {case float64:= time.Duration(float64(time.Second) * )case string:, := strconv.ParseFloat(, 64)if == nil { // it's a simple number assumed to have units == seconds= time.Duration(float64(time.Second) * )} else {, = time.ParseDuration()if != nil {return errors.New("invalid sleep duration")}}default:return errors.New("invalid sleep duration")}if < 0 {return fmt.Errorf("sleep duration must be >= zero")}select {case <-.Interrupts():return ErrInterruptedcase <-TimeAfter(, ):return nil}}//elvdoc:fn time//// ```elvish// time &on-end=$nil $callable// ```//// Runs the callable, and call `$on-end` with the duration it took, as a// number in seconds. If `$on-end` is `$nil` (the default), prints the// duration in human-readable form.//// If `$callable` throws an exception, the exception is propagated after the// on-end or default printing is done.//// If `$on-end` throws an exception, it is propagated, unless `$callable` has// already thrown an exception.//// Example://// ```elvish-transcript// ~> time { sleep 1 }// 1.006060647s// ~> time { sleep 0.01 }// 1.288977ms// ~> t = ''// ~> time &on-end=[x]{ t = $x } { sleep 1 }// ~> put $t// ▶ (float64 1.000925004)// ~> time &on-end=[x]{ t = $x } { sleep 0.01 }// ~> put $t// ▶ (float64 0.011030208)// ```type timeOpt struct{ OnEnd Callable }func ( *timeOpt) () {}func ( *Frame, timeOpt, Callable) error {:= time.Now():= .Call(, NoArgs, NoOpts):= time.Now():= .Sub()if .OnEnd != nil {:= .fork("on-end callback of time"):= .OnEnd.Call(, []interface{}{.Seconds()}, NoOpts)if == nil {=}} else {fmt.Fprintln(.OutputFile(), )}return}//elvdoc:fn -ifaddrs//// ```elvish// -ifaddrs// ```//// Output all IP addresses of the current host.//// This should be part of a networking module instead of the builtin module.func ( *Frame) error {, := net.InterfaceAddrs()if != nil {return}:= .OutputChan()for , := range {<- .String()}return nil}
The pages are generated with Golds v0.2.8-preview. (GOOS=darwin GOARCH=arm64)