9 // Jobs are the way plugins can run processes in the background
10 // A job is simply a process that gets executed asynchronously
11 // There are callbacks for when the job exits, when the job creates stdout
12 // and when the job creates stderr
14 // These jobs run in a separate goroutine but the lua callbacks need to be
15 // executed in the main thread (where the Lua VM is running) so they are
16 // put into the jobs channel which gets read by the main loop
18 // JobFunction is a representation of a job (this data structure is what is loaded
19 // into the jobs channel)
20 type JobFunction struct {
21 function func(string, ...string)
26 // A CallbackFile is the data structure that makes it possible to catch stderr and stdout write events
27 type CallbackFile struct {
30 callback func(string, ...string)
34 func (f *CallbackFile) Write(data []byte) (int, error) {
35 // This is either stderr or stdout
36 // In either case we create a new job function callback and put it in the jobs channel
37 jobFunc := JobFunction{f.callback, string(data), f.args}
39 return f.Writer.Write(data)
42 // JobStart starts a shell command in the background with the given callbacks
43 // It returns an *exec.Cmd as the job id
44 func JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string) *exec.Cmd {
45 return JobSpawn("sh", []string{"-c", cmd}, onStdout, onStderr, onExit, userargs...)
48 // JobSpawn starts a process with args in the background with the given callbacks
49 // It returns an *exec.Cmd as the job id
50 func JobSpawn(cmdName string, cmdArgs []string, onStdout, onStderr, onExit string, userargs ...string) *exec.Cmd {
51 // Set up everything correctly if the functions have been provided
52 proc := exec.Command(cmdName, cmdArgs...)
53 var outbuf bytes.Buffer
55 proc.Stdout = &CallbackFile{&outbuf, LuaFunctionJob(onStdout), userargs}
60 proc.Stderr = &CallbackFile{&outbuf, LuaFunctionJob(onStderr), userargs}
66 // Run the process in the background and create the onExit callback
68 jobFunc := JobFunction{LuaFunctionJob(onExit), string(outbuf.Bytes()), userargs}
75 // JobStop kills a job
76 func JobStop(cmd *exec.Cmd) {
80 // JobSend sends the given data into the job's stdin stream
81 func JobSend(cmd *exec.Cmd, data string) {
82 stdin, err := cmd.StdinPipe()
87 stdin.Write([]byte(data))