Something went wrong. Try again.
Fork of micro-editor/micro
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138package shell
import ( "bytes" "errors" "fmt" "io" "os" "os/exec" "os/signal"
shellquote "github.com/kballard/go-shellquote" "github.com/micro-editor/micro/v2/internal/screen" "github.com/micro-editor/micro/v2/internal/util")
// ExecCommand executes a command using exec// It returns any output/errorsfunc ExecCommand(name string, arg ...string) (string, error) { var err error cmd := exec.Command(name, arg...) outputBytes := &bytes.Buffer{} cmd.Stdout = outputBytes cmd.Stderr = outputBytes err = cmd.Start() if err != nil { return "", err } err = cmd.Wait() // wait for command to finish outstring := outputBytes.String() return outstring, err}
// RunCommand executes a shell command and returns the output/errorfunc RunCommand(input string) (string, error) { args, err := shellquote.Split(input) if err != nil { return "", err } if len(args) == 0 { return "", errors.New("No arguments") } inputCmd := args[0]
return ExecCommand(inputCmd, args[1:]...)}
// RunBackgroundShell runs a shell command in the background// It returns a function which will run the command and returns a string// message resultfunc RunBackgroundShell(input string) (func() string, error) { args, err := shellquote.Split(input) if err != nil { return nil, err } if len(args) == 0 { return nil, errors.New("No arguments") } inputCmd := args[0] return func() string { output, err := RunCommand(input)
str := output if err != nil { str = fmt.Sprint(inputCmd, " exited with error: ", err, ": ", output) } return str }, nil}
// RunInteractiveShell runs a shellcommand interactivelyfunc RunInteractiveShell(input string, wait bool, getOutput bool) (string, error) { args, err := shellquote.Split(input) if err != nil { return "", err } if len(args) == 0 { return "", errors.New("No arguments") } inputCmd := args[0]
// Shut down the screen because we're going to interact directly with the shell screenb := screen.TempFini()
args = args[1:]
// Set up everything for the command outputBytes := &bytes.Buffer{} cmd := exec.Command(inputCmd, args...) cmd.Stdin = os.Stdin if getOutput { cmd.Stdout = io.MultiWriter(os.Stdout, outputBytes) } else { cmd.Stdout = os.Stdout } cmd.Stderr = os.Stderr
// This is a trap for Ctrl-C so that it doesn't kill micro // micro is killed if the signal is ignored only on Windows, so it is // received c := make(chan os.Signal, 1) signal.Reset(os.Interrupt) signal.Notify(c, os.Interrupt) err = cmd.Start() if err == nil { err = cmd.Wait() if wait { // This is just so we don't return right away and let the user press enter to return screen.TermMessage("") } } else { screen.TermMessage(err) }
output := outputBytes.String()
// Start the screen back up screen.TempStart(screenb)
signal.Notify(util.Sigterm, os.Interrupt) signal.Stop(c)
return output, err}
// UserCommand runs the shell command// The openTerm argument specifies whether a terminal should be opened (for viewing output// or interacting with stdin)// func UserCommand(input string, openTerm bool, waitToFinish bool) string {// if !openTerm {// RunBackgroundShell(input)// return ""// } else {// output, _ := RunInteractiveShell(input, waitToFinish, false)// return output// }// }