executor.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package cli
  2. import (
  3. "errors"
  4. "fmt"
  5. "git.nspix.com/golang/micro/helper/console"
  6. "git.nspix.com/golang/micro/helper/unsafestr"
  7. "sort"
  8. "strings"
  9. "sync"
  10. "sync/atomic"
  11. "time"
  12. )
  13. var (
  14. _seq int64
  15. )
  16. type Executor struct {
  17. name string
  18. parent *Executor
  19. usage string
  20. description string
  21. handleFunc HandleFunc
  22. children map[string]*Executor
  23. createdTime time.Time
  24. seq int64
  25. locker sync.RWMutex
  26. NotFoundHandle func(ctx *Context, cmd string) (*Response, error)
  27. }
  28. type (
  29. executors []*Executor
  30. )
  31. func (p executors) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  32. func (p executors) Len() int { return len(p) }
  33. func (p executors) Less(i, j int) bool { return p[i].seq < p[j].seq }
  34. func (exec *Executor) hasChildren(name string) bool {
  35. exec.locker.RLock()
  36. defer exec.locker.RUnlock()
  37. if name == "" {
  38. return len(exec.children) > 0
  39. }
  40. if _, ok := exec.children[name]; ok {
  41. return true
  42. }
  43. return false
  44. }
  45. func (exec *Executor) getDescription() string {
  46. if exec.description != "" {
  47. return exec.description
  48. }
  49. var p *Executor
  50. var text string
  51. p = exec
  52. for {
  53. if p.parent == nil {
  54. break
  55. }
  56. text = p.name + " " + text
  57. p = p.parent
  58. }
  59. return text
  60. }
  61. func (exec *Executor) Children(name string) (*Executor, error) {
  62. exec.locker.RLock()
  63. defer exec.locker.RUnlock()
  64. if cmd, ok := exec.children[name]; ok {
  65. return cmd, nil
  66. }
  67. return nil, errors.New("children not found")
  68. }
  69. func (exec *Executor) Completer(tokens ...string) []string {
  70. exec.locker.RLock()
  71. defer exec.locker.RUnlock()
  72. p := exec.children
  73. length := len(tokens)
  74. var token, prefix string
  75. result := make([]string, 0)
  76. if length > 0 {
  77. for i := 0; i < length; i++ {
  78. token = tokens[i]
  79. if i == length-1 {
  80. for k, e := range p {
  81. if token == k {
  82. if e.children != nil {
  83. for kk, _ := range e.children {
  84. result = append(result, prefix+token+" "+kk)
  85. }
  86. }
  87. } else if strings.HasPrefix(k, token) {
  88. result = append(result, prefix+k)
  89. }
  90. }
  91. } else {
  92. if next, ok := p[token]; !ok || next.children == nil {
  93. return []string{}
  94. } else {
  95. p = next.children
  96. }
  97. }
  98. prefix += token + " "
  99. }
  100. } else {
  101. for k, _ := range p {
  102. result = append(result, k)
  103. }
  104. }
  105. return result
  106. }
  107. func (exec *Executor) String() string {
  108. table := console.NewTable()
  109. var loop func(string, *Executor)
  110. loop = func(prefix string, e *Executor) {
  111. if e.children == nil {
  112. return
  113. }
  114. vs := make(executors, len(e.children))
  115. var i int
  116. for _, v := range e.children {
  117. vs[i] = v
  118. i++
  119. }
  120. sort.Sort(vs)
  121. for _, v := range vs {
  122. if prefix == "" {
  123. if v.handleFunc != nil {
  124. table.AddRow(v.name, v.getDescription())
  125. }
  126. } else {
  127. if v.handleFunc != nil {
  128. table.AddRow(prefix+" "+v.name, v.getDescription())
  129. }
  130. }
  131. if prefix == "" {
  132. loop(v.name, v)
  133. } else {
  134. loop(prefix+" "+v.name, v)
  135. }
  136. }
  137. }
  138. loop("", exec)
  139. buf, _ := table.Marshal()
  140. return unsafestr.BytesToString(buf)
  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(cb HandleFunc) *Executor {
  152. exec.handleFunc = cb
  153. return exec
  154. }
  155. func (exec *Executor) Do(ctx *Context, args ...string) (res *Response, 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.handleFunc == nil {
  171. if exec.NotFoundHandle != nil {
  172. res, err = exec.NotFoundHandle(ctx, ctx.CmdStr)
  173. } else {
  174. err = fmt.Errorf("%s not found", ctx.CmdStr)
  175. }
  176. return
  177. }
  178. ctx.Args = args
  179. if err = exec.handleFunc(ctx); err == nil {
  180. res = ctx.response
  181. } else {
  182. if err == ErrInvalidArgument {
  183. res = &Response{Code: 1000, Error: fmt.Sprint(ctx.Get("usage"))}
  184. err = nil
  185. }
  186. }
  187. return
  188. }
  189. func NewExecutor(args ...string) *Executor {
  190. var (
  191. name string
  192. usage string
  193. description string
  194. )
  195. if len(args) > 0 {
  196. name = args[0]
  197. }
  198. if len(args) > 2 {
  199. description = args[2]
  200. }
  201. if len(args) > 1 {
  202. usage = args[1]
  203. }
  204. return &Executor{
  205. name: name,
  206. usage: usage,
  207. createdTime: time.Now(),
  208. description: description,
  209. children: make(map[string]*Executor),
  210. seq: atomic.AddInt64(&_seq, 1),
  211. }
  212. }