| @@ -8,6 +8,10 @@ import ( | |||||
| myreflect "gitlink.org.cn/cloudream/common/utils/reflect" | myreflect "gitlink.org.cn/cloudream/common/utils/reflect" | ||||
| ) | ) | ||||
| type ExecuteOption struct { | |||||
| ReplaceEmptyArrayWithNil bool // 如果最后一个参数是空数组,则调用命令的时候传递nil参数 | |||||
| } | |||||
| type command struct { | type command struct { | ||||
| fn reflect.Value | fn reflect.Value | ||||
| fnType reflect.Type | fnType reflect.Type | ||||
| @@ -139,7 +143,7 @@ func (t *anyCommandTrie) checkFnArgs(typ reflect.Type) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func (t *anyCommandTrie) Execute(ctx any, cmdWords ...string) ([]reflect.Value, error) { | |||||
| func (t *anyCommandTrie) Execute(ctx any, cmdWords []string, opt ExecuteOption) ([]reflect.Value, error) { | |||||
| var cmd *command | var cmd *command | ||||
| var argWords []string | var argWords []string | ||||
| @@ -171,7 +175,7 @@ func (t *anyCommandTrie) Execute(ctx any, cmdWords ...string) ([]reflect.Value, | |||||
| } | } | ||||
| // 解析最后一个参数 | // 解析最后一个参数 | ||||
| callArgs, err = t.parseLastArg(cmd, argWords, callArgs) | |||||
| callArgs, err = t.parseLastArg(cmd, argWords, opt, callArgs) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -219,7 +223,7 @@ func (t *anyCommandTrie) parseFrontArgs(cmd *command, argWords []string, callArg | |||||
| return callArgs, nil | return callArgs, nil | ||||
| } | } | ||||
| func (t *anyCommandTrie) parseLastArg(cmd *command, argWords []string, callArgs []reflect.Value) ([]reflect.Value, error) { | |||||
| func (t *anyCommandTrie) parseLastArg(cmd *command, argWords []string, opt ExecuteOption, callArgs []reflect.Value) ([]reflect.Value, error) { | |||||
| if len(cmd.staticArgTypes) > 0 { | if len(cmd.staticArgTypes) > 0 { | ||||
| lastArgType := cmd.staticArgTypes[len(cmd.staticArgTypes)-1] | lastArgType := cmd.staticArgTypes[len(cmd.staticArgTypes)-1] | ||||
| lastArgWords := argWords[len(cmd.staticArgTypes)-1:] | lastArgWords := argWords[len(cmd.staticArgTypes)-1:] | ||||
| @@ -241,6 +245,10 @@ func (t *anyCommandTrie) parseLastArg(cmd *command, argWords []string, callArgs | |||||
| lastArg.Index(i).Set(eleVal) | lastArg.Index(i).Set(eleVal) | ||||
| } | } | ||||
| if opt.ReplaceEmptyArrayWithNil && lastArg.Len() == 0 { | |||||
| lastArg = reflect.Zero(lastArgType) | |||||
| } | |||||
| } else { | } else { | ||||
| if len(lastArgWords) == 0 { | if len(lastArgWords) == 0 { | ||||
| return nil, fmt.Errorf("no enough arguments for command") | return nil, fmt.Errorf("no enough arguments for command") | ||||
| @@ -325,8 +333,13 @@ func (t *CommandTrie[TCtx, TRet]) MustAdd(fn any, prefixWords ...string) { | |||||
| } | } | ||||
| } | } | ||||
| func (t *CommandTrie[TCtx, TRet]) Execute(ctx TCtx, cmdWords ...string) (TRet, error) { | |||||
| retValues, err := t.anyTrie.Execute(ctx, cmdWords...) | |||||
| func (t *CommandTrie[TCtx, TRet]) Execute(ctx TCtx, cmdWords []string, opts ...ExecuteOption) (TRet, error) { | |||||
| opt := ExecuteOption{} | |||||
| if len(opts) > 0 { | |||||
| opt = opts[0] | |||||
| } | |||||
| retValues, err := t.anyTrie.Execute(ctx, cmdWords, opt) | |||||
| if err != nil { | if err != nil { | ||||
| var defRet TRet | var defRet TRet | ||||
| return defRet, err | return defRet, err | ||||
| @@ -361,8 +374,13 @@ func (t *VoidCommandTrie[TCtx]) MustAdd(fn any, prefixWords ...string) { | |||||
| } | } | ||||
| } | } | ||||
| func (t *VoidCommandTrie[TCtx]) Execute(ctx TCtx, cmdWords ...string) error { | |||||
| _, err := t.anyTrie.Execute(ctx, cmdWords...) | |||||
| func (t *VoidCommandTrie[TCtx]) Execute(ctx TCtx, cmdWords []string, opts ...ExecuteOption) error { | |||||
| opt := ExecuteOption{} | |||||
| if len(opts) > 0 { | |||||
| opt = opts[0] | |||||
| } | |||||
| _, err := t.anyTrie.Execute(ctx, cmdWords, opt) | |||||
| return err | return err | ||||
| } | } | ||||
| @@ -387,8 +405,13 @@ func (t *StaticCommandTrie[TRet]) MustAdd(fn any, prefixWords ...string) { | |||||
| } | } | ||||
| } | } | ||||
| func (t *StaticCommandTrie[TRet]) Execute(cmdWords ...string) (TRet, error) { | |||||
| retValues, err := t.anyTrie.Execute(nil, cmdWords...) | |||||
| func (t *StaticCommandTrie[TRet]) Execute(cmdWords []string, opts ...ExecuteOption) (TRet, error) { | |||||
| opt := ExecuteOption{} | |||||
| if len(opts) > 0 { | |||||
| opt = opts[0] | |||||
| } | |||||
| retValues, err := t.anyTrie.Execute(nil, cmdWords, opt) | |||||
| if err != nil { | if err != nil { | ||||
| var defRet TRet | var defRet TRet | ||||
| return defRet, err | return defRet, err | ||||
| @@ -17,7 +17,7 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a") | }, "a") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| err = trie.Execute(0, "a") | |||||
| err = trie.Execute(0, []string{"a"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(ret, ShouldEqual, "ok") | So(ret, ShouldEqual, "ok") | ||||
| @@ -40,7 +40,7 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "b") | }, "a", "b") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| err = trie.Execute(0, "a", "b", "1", "2", "true", "3") | |||||
| err = trie.Execute(0, []string{"a", "b", "1", "2", "true", "3"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| @@ -62,7 +62,7 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "b") | }, "a", "b") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| err = trie.Execute(0, "a", "b", "1", "2", "3", "4") | |||||
| err = trie.Execute(0, []string{"a", "b", "1", "2", "3", "4"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| @@ -82,7 +82,7 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "b") | }, "a", "b") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| err = trie.Execute(0, "a", "b", "1") | |||||
| err = trie.Execute(0, []string{"a", "b", "1"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| @@ -102,7 +102,7 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "b") | }, "a", "b") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| ret, err := trie.Execute(0, "a", "b", "1") | |||||
| ret, err := trie.Execute(0, []string{"a", "b", "1"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| @@ -128,13 +128,13 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "c") | }, "a", "c") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| ret, err := trie.Execute(0, "a", "b", "1") | |||||
| ret, err := trie.Execute(0, []string{"a", "b", "1"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| So(argArr, ShouldResemble, []int64{}) | So(argArr, ShouldResemble, []int64{}) | ||||
| So(ret, ShouldEqual, 123) | So(ret, ShouldEqual, 123) | ||||
| ret2, err := trie.Execute(0, "a", "c", "1") | |||||
| ret2, err := trie.Execute(0, []string{"a", "c", "1"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(ret2, ShouldEqual, "123") | So(ret2, ShouldEqual, "123") | ||||
| }) | }) | ||||
| @@ -152,7 +152,7 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "b") | }, "a", "b") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| ret, err := trie.Execute("a", "b", "1") | |||||
| ret, err := trie.Execute([]string{"a", "b", "1"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| @@ -173,11 +173,29 @@ func Test_CommandTrie(t *testing.T) { | |||||
| }, "a", "b") | }, "a", "b") | ||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| ret, err := trie.Execute("a", "b") | |||||
| ret, err := trie.Execute([]string{"a", "b"}) | |||||
| So(err, ShouldBeNil) | So(err, ShouldBeNil) | ||||
| So(argI, ShouldEqual, 1) | So(argI, ShouldEqual, 1) | ||||
| So(argArr, ShouldResemble, []int64{}) | So(argArr, ShouldResemble, []int64{}) | ||||
| So(ret, ShouldEqual, 123) | So(ret, ShouldEqual, 123) | ||||
| }) | }) | ||||
| Convey("空数组参数变成nil", t, func() { | |||||
| trie := NewStaticCommandTrie[int]() | |||||
| var argStrs []string | |||||
| err := trie.Add(func(strs []string) int { | |||||
| argStrs = strs | |||||
| return 123 | |||||
| }, "a", "b") | |||||
| So(err, ShouldBeNil) | |||||
| ret, err := trie.Execute([]string{"a", "b"}, ExecuteOption{ReplaceEmptyArrayWithNil: true}) | |||||
| So(err, ShouldBeNil) | |||||
| So(argStrs, ShouldBeNil) | |||||
| So(ret, ShouldEqual, 123) | |||||
| }) | |||||
| } | } | ||||