executor.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. middleware []Middleware
  23. children map[string]*Executor
  24. createdTime time.Time
  25. seq int64
  26. locker sync.RWMutex
  27. params []string //params (eg: /show/user/:uid => :uid)
  28. NotFoundHandle HandleFunc
  29. }
  30. type (
  31. executors []*Executor
  32. )
  33. func (p executors) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  34. func (p executors) Len() int { return len(p) }
  35. func (p executors) Less(i, j int) bool { return p[i].seq < p[j].seq }
  36. func (exec *Executor) hasChildren(name string) bool {
  37. exec.locker.RLock()
  38. defer exec.locker.RUnlock()
  39. if name == "" {
  40. return len(exec.children) > 0
  41. }
  42. if _, ok := exec.children[name]; ok {
  43. return true
  44. }
  45. return false
  46. }
  47. func (exec *Executor) getDescription() string {
  48. if exec.description != "" {
  49. return exec.description
  50. }
  51. var p *Executor
  52. var text string
  53. p = exec
  54. for {
  55. if p.parent == nil {
  56. break
  57. }
  58. text = p.name + " " + text
  59. p = p.parent
  60. }
  61. return text
  62. }
  63. func (exec *Executor) Children(name string) (*Executor, error) {
  64. exec.locker.RLock()
  65. defer exec.locker.RUnlock()
  66. if cmd, ok := exec.children[name]; ok {
  67. return cmd, nil
  68. }
  69. return nil, errors.New("children not found")
  70. }
  71. func (exec *Executor) Completer(tokens ...string) []string {
  72. exec.locker.RLock()
  73. defer exec.locker.RUnlock()
  74. p := exec.children
  75. length := len(tokens)
  76. var token, prefix string
  77. result := make([]string, 0)
  78. if length > 0 {
  79. for i := 0; i < length; i++ {
  80. token = tokens[i]
  81. if i == length-1 {
  82. for k, e := range p {
  83. if token == k {
  84. if e.children != nil {
  85. for kk, _ := range e.children {
  86. result = append(result, prefix+token+" "+kk)
  87. }
  88. }
  89. } else if strings.HasPrefix(k, token) {
  90. result = append(result, prefix+k)
  91. }
  92. }
  93. } else {
  94. if next, ok := p[token]; !ok || next.children == nil {
  95. return []string{}
  96. } else {
  97. p = next.children
  98. }
  99. }
  100. prefix += token + " "
  101. }
  102. } else {
  103. for k, _ := range p {
  104. result = append(result, k)
  105. }
  106. }
  107. return result
  108. }
  109. func (exec *Executor) String() string {
  110. table := console.NewTable()
  111. var loop func(string, *Executor)
  112. loop = func(prefix string, e *Executor) {
  113. if e.children == nil {
  114. return
  115. }
  116. vs := make(executors, len(e.children))
  117. var i int
  118. for _, v := range e.children {
  119. vs[i] = v
  120. i++
  121. }
  122. sort.Sort(vs)
  123. for _, v := range vs {
  124. if prefix == "" {
  125. if v.handleFunc != nil {
  126. table.AddRow(v.name, v.getDescription())
  127. }
  128. } else {
  129. if v.handleFunc != nil {
  130. table.AddRow(prefix+" "+v.name, v.getDescription())
  131. }
  132. }
  133. if prefix == "" {
  134. loop(v.name, v)
  135. } else {
  136. loop(prefix+" "+v.name, v)
  137. }
  138. }
  139. }
  140. loop("", exec)
  141. buf, _ := table.Marshal()
  142. return unsafestr.BytesToString(buf)
  143. }
  144. func (exec *Executor) Append(child ...*Executor) *Executor {
  145. exec.locker.Lock()
  146. defer exec.locker.Unlock()
  147. for _, v := range child {
  148. v.parent = exec
  149. exec.children[v.name] = v
  150. }
  151. return exec
  152. }
  153. func (exec *Executor) WithHandle(cb HandleFunc) *Executor {
  154. exec.handleFunc = cb
  155. return exec
  156. }
  157. func (exec *Executor) Do(ctx *Context, args ...string) (res *Response, err error) {
  158. var (
  159. root interface{}
  160. )
  161. if root = ctx.Get("ROOT"); root == nil {
  162. ctx.Set("ROOT", exec)
  163. }
  164. ctx.Set("arguments", args)
  165. if len(args) > 0 && exec.hasChildren(args[0]) {
  166. if len(args) > 1 {
  167. return exec.children[args[0]].Do(ctx, args[1:]...)
  168. } else {
  169. return exec.children[args[0]].Do(ctx)
  170. }
  171. }
  172. if exec.handleFunc == nil {
  173. if exec.NotFoundHandle != nil {
  174. if err = exec.NotFoundHandle(ctx); err == nil {
  175. res = ctx.response
  176. }
  177. } else {
  178. err = fmt.Errorf("%s not found", ctx.CmdStr)
  179. }
  180. return
  181. }
  182. if len(exec.params) > 0 && len(args) < len(exec.params) {
  183. s := ""
  184. for _, v := range exec.params {
  185. s += "{" + v + "} "
  186. }
  187. res = &Response{Code: 1000, Error: fmt.Sprintf("Usage: %s %s", ctx.CmdStr, s)}
  188. err = nil
  189. } else {
  190. ctx.Args = args
  191. ctx.params = exec.params
  192. h := exec.handleFunc
  193. if len(exec.middleware) > 0 {
  194. for i := len(exec.middleware) - 1; i >= 0; i-- {
  195. h = exec.middleware[i](h)
  196. }
  197. }
  198. if err = h(ctx); err == nil {
  199. res = ctx.response
  200. } else {
  201. if err == ErrInvalidArgument {
  202. res = &Response{Code: 1000, Error: fmt.Sprint(ctx.Get("usage"))}
  203. err = nil
  204. }
  205. }
  206. }
  207. return
  208. }
  209. func NewExecutor(args ...string) *Executor {
  210. var (
  211. name string
  212. usage string
  213. description string
  214. )
  215. if len(args) > 0 {
  216. name = args[0]
  217. }
  218. if len(args) > 1 {
  219. usage = args[1]
  220. }
  221. if len(args) > 2 {
  222. description = args[2]
  223. }
  224. return &Executor{
  225. name: name,
  226. usage: usage,
  227. createdTime: time.Now(),
  228. description: description,
  229. children: make(map[string]*Executor),
  230. seq: atomic.AddInt64(&_seq, 1),
  231. }
  232. }