-
Notifications
You must be signed in to change notification settings - Fork 0
/
sh.go
108 lines (102 loc) · 3.1 KB
/
sh.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package builtin_libs
import (
"io"
"os/exec"
. "github.com/zgg-lang/zgg-go/runtime"
)
var (
shModuleClass ValueType
shClassSession ValueType
shClassCommand ValueType
)
func libSh(c *Context) ValueObject {
rv := NewObjectAndInit(shModuleClass, c)
return rv
}
func init() {
var shCommand ValueType
shCommand = NewClassBuilder("Command").
Constructor(func(c *Context, this ValueObject, args []Value) {
this.SetMember("__cmds", args[0], c)
}).
Method("__str__", func(c *Context, this ValueObject, args []Value) Value {
cmds := this.GetMember("__cmds", c).ToGoValue().([]*exec.Cmd)
numCmd := len(cmds)
if numCmd == 0 {
return NewStr("")
}
var inCmd = cmds[0]
closers := make([]io.Closer, 0, numCmd)
defer func() {
for _, c := range closers {
c.Close()
}
}()
for i := 1; i < numCmd; i++ {
pipe, _ := inCmd.StdoutPipe()
closers = append(closers, pipe)
cmds[i].Stdin = pipe
inCmd = cmds[i]
}
for _, cmd := range cmds[:numCmd-1] {
if err := cmd.Start(); err != nil {
c.OnRuntimeError("start command %s error %s", cmd, err)
}
}
outs, err := cmds[numCmd-1].CombinedOutput()
if err != nil {
c.OnRuntimeError("wait cmd %s error %s", cmds[numCmd-1], err)
}
return NewStr(string(outs))
}).
Method("__bitOr__", func(c *Context, this ValueObject, args []Value) Value {
other := c.MustObject(args[0])
cmds := append([]*exec.Cmd{}, this.GetMember("__cmds", c).ToGoValue().([]*exec.Cmd)...)
cmds = append(cmds, other.GetMember("__cmds", c).ToGoValue().([]*exec.Cmd)...)
return NewObjectAndInit(shCommand, c, NewGoValue(cmds))
}).
Build()
shModuleClass = NewClassBuilder("sh").
Method("__getAttr__", func(c *Context, this ValueObject, args []Value) Value {
name := args[0].ToString(c)
return NewNativeFunction("", func(c *Context, this Value, args []Value) Value {
cmdArgs := make([]string, len(args))
for i := range cmdArgs {
cmdArgs[i] = args[i].ToString(c)
}
// cmd := exec.Command(name, cmdArgs...)
// bs, err := cmd.CombinedOutput()
// if err != nil {
// c.OnRuntimeError("sh command %s error %s", name, err)
// }
// return NewStr(string(bs))
cmd := exec.Command(name, cmdArgs...)
return NewObjectAndInit(shCommand, c, NewGoValue([]*exec.Cmd{cmd}))
})
}).
Build()
shClassSession = NewClassBuilder("Session").
Constructor(func(c *Context, this ValueObject, args []Value) {
}).
Method("__getAttr__", func(c *Context, this ValueObject, args []Value) Value {
var cmd ValueStr
EnsureFuncParams(c, "__getAttr__", args, ArgRuleRequired{"name", TypeStr, &cmd})
return NewObjectAndInit(shClassCommand, c, cmd, this)
}).
Build()
shClassCommand = NewClassBuilder("Command").
Constructor(func(c *Context, this ValueObject, args []Value) {
var (
cmd ValueStr
session ValueObject
)
EnsureFuncParams(c, "Command.__init__", args,
ArgRuleRequired{"cmdName", TypeStr, &cmd},
ArgRuleRequired{"session", TypeObject, &session},
)
}).
Method("__call__", func(c *Context, this ValueObject, args []Value) Value {
return nil
}).
Build()
}