...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package command
17
18 import (
19 "fmt"
20 "os/exec"
21 "reflect"
22 "strings"
23 )
24
25
26
27
28
29 const ExecTag = "exec"
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 const SubCommandTag = "sub_command"
45
46
47
48
49
50
51
52
53
54
55
56
57 const ParaTag = "para"
58
59
60
61
62
63
64
65
66
67 type Exec struct {
68 active bool
69 }
70
71 func NewExec() Exec {
72 return Exec{active: true}
73 }
74
75 func ToCommand(i interface{}) (*exec.Cmd, error) {
76 path, args, err := Marshal(i)
77 if err != nil {
78 return nil, err
79 }
80 return exec.Command(path, args...), nil
81 }
82
83 func Marshal(i interface{}) (string, []string, error) {
84 value := reflect.ValueOf(i)
85 return marshal(value)
86 }
87
88 func marshal(value reflect.Value) (string, []string, error) {
89
90 if path, ok := SearchKey(value); ok {
91
92
93 if path == "" {
94 return "", nil, nil
95 }
96 args := make([]string, 0)
97 for i := 0; i < value.NumField(); i++ {
98 if _, ok := value.Type().Field(i).Tag.Lookup(SubCommandTag); ok {
99 subPath, subArgs, err := marshal(value.Field(i))
100 if err != nil {
101 return "", nil, err
102 }
103 if subPath != "" {
104 args = append(args, subPath)
105 }
106 args = append(args, subArgs...)
107 }
108 if paraName, ok := value.Type().Field(i).Tag.Lookup(ParaTag); ok {
109 if value.Type().Field(i).Type.Name() == "string" {
110 if value.Field(i).String() != "" {
111 if paraName != "" {
112 args = append(args, paraName)
113 }
114 args = append(args, value.Field(i).String())
115 }
116 } else if value.Field(i).Kind() == reflect.Slice {
117 if slicePara, ok := value.Field(i).Interface().([]string); ok {
118 if strings.Join(slicePara, "") != "" {
119 if paraName != "" {
120 args = append(args, paraName)
121 }
122 args = append(args, slicePara...)
123 }
124 } else {
125 return "", nil, fmt.Errorf("invalid parameter slice type %s :parameter slice must be string slice", value.Field(i).String())
126 }
127 } else {
128 return "", nil, fmt.Errorf("invalid parameter type %s : parameter must be string or string slice", value.Type().Field(i).Type.Name())
129 }
130 }
131 }
132 return path, args, nil
133 }
134 return "", nil, nil
135 }
136
137 func SearchKey(value reflect.Value) (string, bool) {
138 for i := 0; i < value.NumField(); i++ {
139 if path, ok := value.Type().Field(i).Tag.Lookup(ExecTag); ok {
140 if value.Field(i).Field(0).Bool() {
141 return path, ok
142 }
143 }
144 }
145 return "", false
146 }
147