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