Skip to content

Adding lua function to use result of RunBackgroundShell #3692

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/micro/initlua.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ func luaImportMicroShell() *lua.LTable {
ulua.L.SetField(pkg, "ExecCommand", luar.New(ulua.L, shell.ExecCommand))
ulua.L.SetField(pkg, "RunCommand", luar.New(ulua.L, shell.RunCommand))
ulua.L.SetField(pkg, "RunBackgroundShell", luar.New(ulua.L, shell.RunBackgroundShell))
ulua.L.SetField(pkg, "ExecBackgroundCommand", luar.New(ulua.L, shell.ExecBackgroundCommand))
ulua.L.SetField(pkg, "RunBackgroundCommand", luar.New(ulua.L, shell.RunBackgroundCommand))
ulua.L.SetField(pkg, "RunInteractiveShell", luar.New(ulua.L, shell.RunInteractiveShell))
ulua.L.SetField(pkg, "JobStart", luar.New(ulua.L, shell.JobStart))
ulua.L.SetField(pkg, "JobSpawn", luar.New(ulua.L, shell.JobSpawn))
Expand Down
19 changes: 11 additions & 8 deletions internal/action/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -819,15 +819,18 @@ func (h *BufPane) UnbindCmd(args []string) {

// RunCmd runs a shell command in the background
func (h *BufPane) RunCmd(args []string) {
runf, err := shell.RunBackgroundShell(shellquote.Join(args...))
if err != nil {
InfoBar.Error(err)
} else {
go func() {
InfoBar.Message(runf())
screen.Redraw()
}()
if len(args) == 0 {
InfoBar.Error("No arguments")
return
}

shell.ExecBackgroundCommand(func(output string, runErr error) {
if runErr != nil {
output = fmt.Sprint(args[0], " exited with error: ", runErr)
}
InfoBar.Message(output)
screen.Redraw()
}, args[0], args[1:]...)
}

// QuitCmd closes the main view
Expand Down
7 changes: 6 additions & 1 deletion internal/shell/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"io"
"os/exec"
"runtime"
)

var Jobs chan JobFunction
Expand Down Expand Up @@ -54,7 +55,11 @@ func (f *CallbackFile) Write(data []byte) (int, error) {
// JobStart starts a shell command in the background with the given callbacks
// It returns an *exec.Cmd as the job id
func JobStart(cmd string, onStdout, onStderr, onExit func(string, []interface{}), userargs ...interface{}) *Job {
return JobSpawn("sh", []string{"-c", cmd}, onStdout, onStderr, onExit, userargs...)
if runtime.GOOS == "windows" {
return JobSpawn("cmd", []string{"/v:on", "/c", cmd}, onStdout, onStderr, onExit, userargs...)
} else {
return JobSpawn("sh", []string{"-c", cmd}, onStdout, onStderr, onExit, userargs...)
}
}

// JobSpawn starts a process with args in the background with the given callbacks
Expand Down
42 changes: 42 additions & 0 deletions internal/shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func RunCommand(input string) (string, error) {
return ExecCommand(inputCmd, args[1:]...)
}

// **Deprecated, don't use**
// RunBackgroundShell runs a shell command in the background
// It returns a function which will run the command and returns a string
// message result
Expand All @@ -68,6 +69,47 @@ func RunBackgroundShell(input string) (func() string, error) {
}, nil
}

// ExecBackgroundCommand executes a command in the background by accepting
// a optional callback function for the command output or error if any,
// the command name and a list of arguments.
func ExecBackgroundCommand(cb func(string, error), name string, args ...string) {
go func() {
output, runErr := ExecCommand(name, args[0:]...)
if cb != nil {
wrapperFunc := func(output string, args []interface{}) {
errVal, ok := args[0].(error)
if ok {
cb(output, errVal)
} else {
cb(output, nil)
}
}

var passArgs []interface{}
passArgs = append(passArgs, runErr)
jobFunc := JobFunction{wrapperFunc, output, passArgs}
Jobs <- jobFunc
}
}()
}

// RunBackgroundCommand runs a shell command in the background by accepting
// an input for running the command and an optional callback function for
// the command output or error if any.
// It returns an error if it fails to split the input command
func RunBackgroundCommand(input string, cb func(string, error)) error {
args, err := shellquote.Split(input)
if err != nil {
return err
}
if len(args) == 0 {
return errors.New("No arguments")
}

ExecBackgroundCommand(cb, args[0], args[1:]...)
return nil
}

// RunInteractiveShell runs a shellcommand interactively
func RunInteractiveShell(input string, wait bool, getOutput bool) (string, error) {
args, err := shellquote.Split(input)
Expand Down
24 changes: 18 additions & 6 deletions runtime/help/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,20 @@ The packages and their contents are listed below (in Go type signatures):
two arguments in the `ExecCommand` argument list (quoting arguments
will preserve spaces).

- `RunBackgroundShell(input string) (func() string, error)`: returns a
function that will run the given shell command and return its output.
- **Deprecated** `RunBackgroundShell(input string) (func() string, error)`:
returns a function that will run the given shell command and return
its output.

- `ExecBackgroundCommand(cb func(string, error), name string, args ...string)`:
executes a command in the background by accepting a optional callback
function for the command output or error if any, the command name and
a list of arguments.

- `RunBackgroundCommand(input string, cb func(string, error)) error`:
runs a shell command in the background by accepting an input for
running the command and an optional callback function for the
command output or error if any.
It returns an error if it fails to split the input command

- `RunInteractiveShell(input string, wait bool, getOutput bool)
(string, error)`:
Expand All @@ -263,10 +275,10 @@ The packages and their contents are listed below (in Go type signatures):
onExit func(string, []interface{}), userargs ...interface{})
*exec.Cmd`:
Starts a background job by running the shell on the given command
(using `sh -c`). Three callbacks can be provided which will be called
when the command generates stdout, stderr, or exits. The userargs will
be passed to the callbacks, along with the output as the first
argument of the callback. Returns the started command.
(using `sh -c` or `cmd /v:on /c`). Three callbacks can be provided which
will be called when the command generates stdout, stderr, or exits.
The userargs will be passed to the callbacks, along with the output
as the first argument of the callback. Returns the started command.

- `JobSpawn(cmd string, cmdArgs []string, onStdout, onStderr,
onExit func(string, []interface{}), userargs ...interface{})
Expand Down