executor.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. package cli
  2. import (
  3. "errors"
  4. "fmt"
  5. "git.nspix.com/golang/micro/utils/console"
  6. "reflect"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "sync/atomic"
  12. "time"
  13. )
  14. var (
  15. _seq int64
  16. ErrInvalidHandle = errors.New("invalid handle kind")
  17. ErrInvalidHandleResponse = errors.New("invalid handle response")
  18. errInterface = reflect.TypeOf((*error)(nil)).Elem()
  19. stringSliceKind = reflect.TypeOf([]string{}).Kind()
  20. )
  21. type Executor struct {
  22. name string
  23. parent *Executor
  24. usage string
  25. description string
  26. handle interface{}
  27. children map[string]*Executor
  28. createdTime time.Time
  29. seq int64
  30. locker sync.RWMutex
  31. NotFoundHandle func(ctx *Context, cmd string) ([]byte, error)
  32. }
  33. type (
  34. executors []*Executor
  35. )
  36. func (p executors) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  37. func (p executors) Len() int { return len(p) }
  38. func (p executors) Less(i, j int) bool { return p[i].seq < p[j].seq }
  39. func (exec *Executor) hasChildren(name string) bool {
  40. exec.locker.RLock()
  41. defer exec.locker.RUnlock()
  42. if name == "" {
  43. return len(exec.children) > 0
  44. }
  45. if _, ok := exec.children[name]; ok {
  46. return true
  47. }
  48. return false
  49. }
  50. func (exec *Executor) getDescription() string {
  51. if exec.description != "" {
  52. return exec.description
  53. }
  54. var p *Executor
  55. var text string
  56. p = exec
  57. for {
  58. if p.parent == nil {
  59. break
  60. }
  61. text = p.name + " " + text
  62. p = p.parent
  63. }
  64. return text
  65. }
  66. func (exec *Executor) Children(name string) (*Executor, error) {
  67. exec.locker.RLock()
  68. defer exec.locker.RUnlock()
  69. if cmd, ok := exec.children[name]; ok {
  70. return cmd, nil
  71. }
  72. return nil, errors.New("children not found")
  73. }
  74. func (exec *Executor) Completer(tokens ...string) []string {
  75. exec.locker.RLock()
  76. defer exec.locker.RUnlock()
  77. p := exec.children
  78. length := len(tokens)
  79. var token, prefix string
  80. result := make([]string, 0)
  81. if length > 0 {
  82. for i := 0; i < length; i++ {
  83. token = tokens[i]
  84. if i == length-1 {
  85. for k, e := range p {
  86. if token == k {
  87. if e.children != nil {
  88. for kk, _ := range e.children {
  89. result = append(result, prefix+token+" "+kk)
  90. }
  91. }
  92. } else if strings.HasPrefix(k, token) {
  93. result = append(result, prefix+k)
  94. }
  95. }
  96. } else {
  97. if next, ok := p[token]; !ok || next.children == nil {
  98. return []string{}
  99. } else {
  100. p = next.children
  101. }
  102. }
  103. prefix += token + " "
  104. }
  105. } else {
  106. for k, _ := range p {
  107. result = append(result, k)
  108. }
  109. }
  110. return result
  111. }
  112. func (exec *Executor) String() string {
  113. values := make([][]interface{}, 0)
  114. var loop func(string, *Executor)
  115. loop = func(prefix string, e *Executor) {
  116. if e.children == nil {
  117. return
  118. }
  119. vs := make(executors, len(e.children))
  120. var i int
  121. for _, v := range e.children {
  122. vs[i] = v
  123. i++
  124. }
  125. sort.Sort(vs)
  126. for _, v := range vs {
  127. if prefix == "" {
  128. values = append(values, []interface{}{v.name, v.getDescription()})
  129. } else {
  130. values = append(values, []interface{}{prefix + " " + v.name, v.getDescription()})
  131. }
  132. if prefix == "" {
  133. loop(v.name, v)
  134. } else {
  135. loop(prefix+" "+v.name, v)
  136. }
  137. }
  138. }
  139. loop("", exec)
  140. return string(console.Pretty(values, nil))
  141. }
  142. func (exec *Executor) Append(child ...*Executor) *Executor {
  143. exec.locker.Lock()
  144. defer exec.locker.Unlock()
  145. for _, v := range child {
  146. v.parent = exec
  147. exec.children[v.name] = v
  148. }
  149. return exec
  150. }
  151. func (exec *Executor) WithHandle(v interface{}) *Executor {
  152. exec.handle = v
  153. return exec
  154. }
  155. func (exec *Executor) Do(ctx *Context, args ...string) (b []byte, err error) {
  156. var (
  157. root interface{}
  158. )
  159. if root = ctx.Get("ROOT"); root == nil {
  160. ctx.Set("ROOT", exec)
  161. }
  162. ctx.Set("arguments", args)
  163. if len(args) > 0 && exec.hasChildren(args[0]) {
  164. if len(args) > 1 {
  165. return exec.children[args[0]].Do(ctx, args[1:]...)
  166. } else {
  167. return exec.children[args[0]].Do(ctx)
  168. }
  169. }
  170. if exec.handle == nil {
  171. if exec.NotFoundHandle != nil {
  172. b, err = exec.NotFoundHandle(ctx, ctx.CmdStr)
  173. } else {
  174. err = fmt.Errorf("%s not found", ctx.CmdStr)
  175. }
  176. return
  177. }
  178. refVal := reflect.ValueOf(exec.handle)
  179. refType := refVal.Type()
  180. if refType.Kind() != reflect.Func {
  181. err = ErrInvalidHandle
  182. return
  183. }
  184. //checking args
  185. if refType.NumIn() > 0 && len(args)+1 < refType.NumIn() {
  186. var usage string
  187. if exec.usage == "" {
  188. usage = "Usage: " + ctx.CmdStr + " ["
  189. for i := 1; i < refType.NumIn(); i++ {
  190. usage += " " + refType.In(i).String()
  191. }
  192. usage += " ]"
  193. } else {
  194. usage = "Usage: " + exec.usage
  195. }
  196. err = errors.New(usage)
  197. return
  198. }
  199. arguments := make([]reflect.Value, refType.NumIn())
  200. for i := 0; i < refType.NumIn(); i++ {
  201. if i == 0 {
  202. arguments[i] = reflect.ValueOf(ctx)
  203. continue
  204. }
  205. switch refType.In(i).Kind() {
  206. case reflect.String:
  207. arguments[i] = reflect.ValueOf(args[i-1])
  208. case reflect.Int:
  209. n, _ := strconv.ParseInt(args[i-1], 10, 64)
  210. arguments[i] = reflect.ValueOf(int(n))
  211. case reflect.Int32:
  212. n, _ := strconv.ParseInt(args[i-1], 10, 32)
  213. arguments[i] = reflect.ValueOf(int32(n))
  214. case reflect.Int64:
  215. n, _ := strconv.ParseInt(args[i-1], 10, 64)
  216. arguments[i] = reflect.ValueOf(n)
  217. case reflect.Float32:
  218. n, _ := strconv.ParseFloat(args[i-1], 32)
  219. arguments[i] = reflect.ValueOf(float32(n))
  220. case reflect.Float64:
  221. n, _ := strconv.ParseFloat(args[i-1], 64)
  222. arguments[i] = reflect.ValueOf(n)
  223. case stringSliceKind:
  224. arguments[i] = reflect.ValueOf(args[i-1:])
  225. default:
  226. err = fmt.Errorf("unsupported argument %d kind %s", i-1, refType.In(i).Kind().String())
  227. return
  228. }
  229. }
  230. values := refVal.Call(arguments)
  231. for _, v := range values {
  232. if v.Type().Implements(errInterface) {
  233. err = v.Interface().(error)
  234. } else if v.Kind() == reflect.Slice {
  235. b = v.Bytes()
  236. }
  237. }
  238. return
  239. }
  240. func NewExecutor(args ...string) *Executor {
  241. var (
  242. name string
  243. usage string
  244. description string
  245. )
  246. if len(args) > 0 {
  247. name = args[0]
  248. }
  249. if len(args) > 1 {
  250. usage = args[1]
  251. }
  252. if len(args) > 2 {
  253. description = args[2]
  254. }
  255. return &Executor{
  256. name: name,
  257. usage: usage,
  258. createdTime: time.Now(),
  259. description: description,
  260. children: make(map[string]*Executor),
  261. seq: atomic.AddInt64(&_seq, 1),
  262. }
  263. }