elvish/pkg/eval/builtin_fn_cmd.go

130 lines
2.2 KiB
Go
Raw Normal View History

2017-12-17 13:20:03 +08:00
package eval
import (
"fmt"
"os"
"os/exec"
)
// Command and process control.
//elvdoc:fn external
//
// ```elvish
// external $program
// ```
//
// Construct a callable value for the external program `$program`. Example:
//
// ```elvish-transcript
// ~> x = (external man)
// ~> $x ls # opens the manpage for ls
// ```
//
// @cf has-external search-external
//elvdoc:fn has-external
//
// ```elvish
// has-external $command
// ```
//
// Test whether `$command` names a valid external command. Examples (your output
// might differ):
//
// ```elvish-transcript
// ~> has-external cat
// ▶ $true
// ~> has-external lalala
// ▶ $false
// ```
//
// @cf external search-external
//elvdoc:fn search-external
//
// ```elvish
// search-external $command
// ```
//
// Output the full path of the external `$command`. Throws an exception when not
// found. Example (your output might vary):
//
// ```elvish-transcript
// ~> search-external cat
// ▶ /bin/cat
// ```
//
// @cf external has-external
// TODO(xiaq): Document "fg".
//elvdoc:fn exec
//
// ```elvish
// exec $command?
// ```
//
// Replace the Elvish process with an external `$command`, defaulting to
// `elvish`. This decrements `$E:SHLVL` before starting the new process.
//elvdoc:fn exit
//
// ```elvish
// exit $status?
// ```
//
// Exit the Elvish process with `$status` (defaulting to 0).
2017-12-17 13:20:03 +08:00
func init() {
2018-02-07 03:39:40 +08:00
addBuiltinFns(map[string]interface{}{
2017-12-17 13:20:03 +08:00
// Command resolution
"external": external,
"has-external": hasExternal,
"search-external": searchExternal,
2017-12-17 13:20:03 +08:00
// Process control
"fg": fg,
"exec": execFn,
"exit": exit,
2017-12-17 13:20:03 +08:00
})
}
func external(cmd string) ExternalCmd {
return ExternalCmd{cmd}
2018-01-03 07:26:28 +08:00
}
func hasExternal(cmd string) bool {
_, err := exec.LookPath(cmd)
return err == nil
2017-12-17 13:20:03 +08:00
}
func searchExternal(cmd string) (string, error) {
return exec.LookPath(cmd)
2017-12-17 13:20:03 +08:00
}
func exit(fm *Frame, codes ...int) error {
code := 0
2017-12-17 13:20:03 +08:00
switch len(codes) {
case 0:
case 1:
code = codes[0]
2017-12-17 13:20:03 +08:00
default:
return ErrArgs
2017-12-17 13:20:03 +08:00
}
preExit(fm)
os.Exit(code)
// Does not return
panic("os.Exit returned")
2017-12-17 13:20:03 +08:00
}
func preExit(fm *Frame) {
if fm.DaemonClient != nil {
err := fm.DaemonClient.Close()
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
2017-12-17 13:20:03 +08:00
}
}