|
@@ -6,7 +6,6 @@ import (
|
|
|
"git.nspix.com/golang/micro/utils/console"
|
|
|
"reflect"
|
|
|
"sort"
|
|
|
- "strconv"
|
|
|
"strings"
|
|
|
"sync"
|
|
|
"sync/atomic"
|
|
@@ -28,12 +27,12 @@ type Executor struct {
|
|
|
parent *Executor
|
|
|
usage string
|
|
|
description string
|
|
|
- handle interface{}
|
|
|
+ handleFunc HandleFunc
|
|
|
children map[string]*Executor
|
|
|
createdTime time.Time
|
|
|
seq int64
|
|
|
locker sync.RWMutex
|
|
|
- NotFoundHandle func(ctx *Context, cmd string) ([]byte, error)
|
|
|
+ NotFoundHandle func(ctx *Context, cmd string) (*Response, error)
|
|
|
}
|
|
|
|
|
|
type (
|
|
@@ -137,9 +136,13 @@ func (exec *Executor) String() string {
|
|
|
sort.Sort(vs)
|
|
|
for _, v := range vs {
|
|
|
if prefix == "" {
|
|
|
- values = append(values, []interface{}{v.name, v.getDescription()})
|
|
|
+ if v.handleFunc != nil {
|
|
|
+ values = append(values, []interface{}{v.name, v.getDescription()})
|
|
|
+ }
|
|
|
} else {
|
|
|
- values = append(values, []interface{}{prefix + " " + v.name, v.getDescription()})
|
|
|
+ if v.handleFunc != nil {
|
|
|
+ values = append(values, []interface{}{prefix + " " + v.name, v.getDescription()})
|
|
|
+ }
|
|
|
}
|
|
|
if prefix == "" {
|
|
|
loop(v.name, v)
|
|
@@ -162,12 +165,12 @@ func (exec *Executor) Append(child ...*Executor) *Executor {
|
|
|
return exec
|
|
|
}
|
|
|
|
|
|
-func (exec *Executor) WithHandle(v interface{}) *Executor {
|
|
|
- exec.handle = v
|
|
|
+func (exec *Executor) WithHandle(cb HandleFunc) *Executor {
|
|
|
+ exec.handleFunc = cb
|
|
|
return exec
|
|
|
}
|
|
|
|
|
|
-func (exec *Executor) Do(ctx *Context, args ...string) (b []byte, err error) {
|
|
|
+func (exec *Executor) Do(ctx *Context, args ...string) (res *Response, err error) {
|
|
|
var (
|
|
|
root interface{}
|
|
|
)
|
|
@@ -182,72 +185,21 @@ func (exec *Executor) Do(ctx *Context, args ...string) (b []byte, err error) {
|
|
|
return exec.children[args[0]].Do(ctx)
|
|
|
}
|
|
|
}
|
|
|
- if exec.handle == nil {
|
|
|
+ if exec.handleFunc == nil {
|
|
|
if exec.NotFoundHandle != nil {
|
|
|
- b, err = exec.NotFoundHandle(ctx, ctx.CmdStr)
|
|
|
+ res, err = exec.NotFoundHandle(ctx, ctx.CmdStr)
|
|
|
} else {
|
|
|
err = fmt.Errorf("%s not found", ctx.CmdStr)
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
- refVal := reflect.ValueOf(exec.handle)
|
|
|
- refType := refVal.Type()
|
|
|
- if refType.Kind() != reflect.Func {
|
|
|
- err = ErrInvalidHandle
|
|
|
- return
|
|
|
- }
|
|
|
- //checking args
|
|
|
- if refType.NumIn() > 0 && len(args)+1 < refType.NumIn() {
|
|
|
- var usage string
|
|
|
- if exec.usage == "" {
|
|
|
- usage = "Usage: " + ctx.CmdStr + " ["
|
|
|
- for i := 1; i < refType.NumIn(); i++ {
|
|
|
- usage += " " + refType.In(i).String()
|
|
|
- }
|
|
|
- usage += " ]"
|
|
|
- } else {
|
|
|
- usage = "Usage: " + exec.usage
|
|
|
- }
|
|
|
- err = errors.New(usage)
|
|
|
- return
|
|
|
- }
|
|
|
- arguments := make([]reflect.Value, refType.NumIn())
|
|
|
- for i := 0; i < refType.NumIn(); i++ {
|
|
|
- if i == 0 {
|
|
|
- arguments[i] = reflect.ValueOf(ctx)
|
|
|
- continue
|
|
|
- }
|
|
|
- switch refType.In(i).Kind() {
|
|
|
- case reflect.String:
|
|
|
- arguments[i] = reflect.ValueOf(args[i-1])
|
|
|
- case reflect.Int:
|
|
|
- n, _ := strconv.ParseInt(args[i-1], 10, 64)
|
|
|
- arguments[i] = reflect.ValueOf(int(n))
|
|
|
- case reflect.Int32:
|
|
|
- n, _ := strconv.ParseInt(args[i-1], 10, 32)
|
|
|
- arguments[i] = reflect.ValueOf(int32(n))
|
|
|
- case reflect.Int64:
|
|
|
- n, _ := strconv.ParseInt(args[i-1], 10, 64)
|
|
|
- arguments[i] = reflect.ValueOf(n)
|
|
|
- case reflect.Float32:
|
|
|
- n, _ := strconv.ParseFloat(args[i-1], 32)
|
|
|
- arguments[i] = reflect.ValueOf(float32(n))
|
|
|
- case reflect.Float64:
|
|
|
- n, _ := strconv.ParseFloat(args[i-1], 64)
|
|
|
- arguments[i] = reflect.ValueOf(n)
|
|
|
- case stringSliceKind:
|
|
|
- arguments[i] = reflect.ValueOf(args[i-1:])
|
|
|
- default:
|
|
|
- err = fmt.Errorf("unsupported argument %d kind %s", i-1, refType.In(i).Kind().String())
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
- values := refVal.Call(arguments)
|
|
|
- for _, v := range values {
|
|
|
- if v.Type().Implements(errInterface) {
|
|
|
- err = v.Interface().(error)
|
|
|
- } else if v.Kind() == reflect.Slice {
|
|
|
- b = v.Bytes()
|
|
|
+ ctx.Args = args
|
|
|
+ if err = exec.handleFunc(ctx); err == nil {
|
|
|
+ res = ctx.response
|
|
|
+ } else {
|
|
|
+ if err == ErrInvalidArgument {
|
|
|
+ res = &Response{Code: 1000, Error: fmt.Sprint(ctx.Get("usage"))}
|
|
|
+ err = nil
|
|
|
}
|
|
|
}
|
|
|
return
|