lua/run3/run3.go
Rama main · réplica de lectura del repositorio original.
// Package run3 runs a command and returns its stdout, stderr and exit error.
package run3
import (
"bytes"
"os/exec"
"strings"
"github.com/xyproto/algernon/lua/convert"
lua "github.com/xyproto/gopher-lua"
)
// ShellHelper executes the given shell command in the specified working directory.
// It converts stdout and stderr into slices of strings (one entry per line) and then
// uses convert.Strings2table to return two Lua tables. The exit code is also returned.
// If the command is empty, both output tables are empty and exit code 1 is returned.
func ShellHelper(L *lua.LState, command, workingDir string) int {
if command == "" { // no command given
L.Push(L.NewTable()) // stdout: empty table
L.Push(L.NewTable()) // stderr: empty table
L.Push(lua.LNumber(1)) // exit code 1
return 3
}
cmd := exec.Command("sh", "-c", command)
if workingDir != "" {
cmd.Dir = workingDir
}
// Set up buffers for stdout and stderr.
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
// Run command.
err := cmd.Run()
exitCode := 0
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
exitCode = exitErr.ExitCode()
} else {
exitCode = 1 // fallback if no exit code is available
}
}
// Normalize Windows CRLF to LF and split output into lines.
outStr := strings.ReplaceAll(stdout.String(), "\r\n", "\n")
errStr := strings.ReplaceAll(stderr.String(), "\r\n", "\n")
outLines := strings.Split(outStr, "\n")
errLines := strings.Split(errStr, "\n")
// Remove the final empty element if present (as io.popen:lines would not yield an empty last line).
if len(outLines) > 0 && outLines[len(outLines)-1] == "" {
outLines = outLines[:len(outLines)-1]
}
if len(errLines) > 0 && errLines[len(errLines)-1] == "" {
errLines = errLines[:len(errLines)-1]
}
// Use the convert.Strings2table helper to convert slices to Lua tables.
L.Push(convert.Strings2table(L, outLines))
L.Push(convert.Strings2table(L, errLines))
L.Push(lua.LNumber(exitCode))
return 3
}