github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/eval/builtin_fn_cmd.go (about)

     1  package eval
     2  
     3  import (
     4  	"os"
     5  	"os/exec"
     6  
     7  	"github.com/markusbkk/elvish/pkg/eval/errs"
     8  )
     9  
    10  // Command and process control.
    11  
    12  // TODO(xiaq): Document "fg".
    13  
    14  func init() {
    15  	addBuiltinFns(map[string]interface{}{
    16  		// Command resolution
    17  		"external":        external,
    18  		"has-external":    hasExternal,
    19  		"search-external": searchExternal,
    20  
    21  		// Process control
    22  		"fg":   fg,
    23  		"exec": execFn,
    24  		"exit": exit,
    25  	})
    26  }
    27  
    28  //elvdoc:fn external
    29  //
    30  // ```elvish
    31  // external $program
    32  // ```
    33  //
    34  // Construct a callable value for the external program `$program`. Example:
    35  //
    36  // ```elvish-transcript
    37  // ~> var x = (external man)
    38  // ~> $x ls # opens the manpage for ls
    39  // ```
    40  //
    41  // @cf has-external search-external
    42  
    43  func external(cmd string) Callable {
    44  	return NewExternalCmd(cmd)
    45  }
    46  
    47  //elvdoc:fn has-external
    48  //
    49  // ```elvish
    50  // has-external $command
    51  // ```
    52  //
    53  // Test whether `$command` names a valid external command. Examples (your output
    54  // might differ):
    55  //
    56  // ```elvish-transcript
    57  // ~> has-external cat
    58  // ▶ $true
    59  // ~> has-external lalala
    60  // ▶ $false
    61  // ```
    62  //
    63  // @cf external search-external
    64  
    65  func hasExternal(cmd string) bool {
    66  	_, err := exec.LookPath(cmd)
    67  	return err == nil
    68  }
    69  
    70  //elvdoc:fn search-external
    71  //
    72  // ```elvish
    73  // search-external $command
    74  // ```
    75  //
    76  // Output the full path of the external `$command`. Throws an exception when not
    77  // found. Example (your output might vary):
    78  //
    79  // ```elvish-transcript
    80  // ~> search-external cat
    81  // ▶ /bin/cat
    82  // ```
    83  //
    84  // @cf external has-external
    85  
    86  func searchExternal(cmd string) (string, error) {
    87  	return exec.LookPath(cmd)
    88  }
    89  
    90  //elvdoc:fn exit
    91  //
    92  // ```elvish
    93  // exit $status?
    94  // ```
    95  //
    96  // Exit the Elvish process with `$status` (defaulting to 0).
    97  
    98  func exit(fm *Frame, codes ...int) error {
    99  	code := 0
   100  	switch len(codes) {
   101  	case 0:
   102  	case 1:
   103  		code = codes[0]
   104  	default:
   105  		return errs.ArityMismatch{What: "arguments", ValidLow: 0, ValidHigh: 1, Actual: len(codes)}
   106  	}
   107  
   108  	preExit(fm)
   109  	os.Exit(code)
   110  	// Does not return
   111  	panic("os.Exit returned")
   112  }
   113  
   114  func preExit(fm *Frame) {
   115  	for _, hook := range fm.Evaler.BeforeExit {
   116  		hook()
   117  	}
   118  }