Skip to content

Commit 80e8a58

Browse files
committed
add NeedArgs feature for package gcmd
1 parent 26ef8c5 commit 80e8a58

4 files changed

+56
-1
lines changed

os/gcmd/gcmd_command.go

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type Command struct {
2626
HelpFunc Function // Custom help function
2727
Examples string // Usage examples.
2828
Additional string // Additional info about this command, which will be appended to the end of help info.
29+
NeedArgs bool // NeedArgs specifies this command needs arguments.
2930
Strict bool // Strict parsing options, which means it returns error if invalid option given.
3031
parent *Command // Parent command for internal usage.
3132
commands []Command // Sub commands of this command.

os/gcmd/gcmd_command_object.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
const (
2727
tagNameDc = `dc`
2828
tagNameAd = `ad`
29+
tagNameArgs = `args`
2930
tagNameRoot = `root`
3031
)
3132

@@ -113,6 +114,9 @@ func newCommandFromObjectMeta(object interface{}) (command Command, err error) {
113114
)
114115
return
115116
}
117+
if !command.NeedArgs {
118+
command.NeedArgs = gconv.Bool(metaData[tagNameArgs])
119+
}
116120
if command.Description == "" {
117121
command.Description = metaData[tagNameDc]
118122
}
@@ -199,7 +203,7 @@ func newCommandFromMethod(object interface{}, method reflect.Value) (command Com
199203

200204
// Create function that has value return.
201205
command.FuncWithValue = func(ctx context.Context, parser *Parser) (out interface{}, err error) {
202-
ctx = context.WithValue(ctx, CtxKeyParser, command)
206+
ctx = context.WithValue(ctx, CtxKeyParser, parser)
203207

204208
defer func() {
205209
if exception := recover(); exception != nil {

os/gcmd/gcmd_command_run.go

+6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ func (c *Command) searchCommand(args []string) *Command {
106106
return nil
107107
}
108108
for _, cmd := range c.commands {
109+
// If this command needs argument,
110+
// it then gives all its left arguments to it.
111+
if cmd.NeedArgs {
112+
return &cmd
113+
}
114+
// Recursively searching the command.
109115
if cmd.Name == args[0] {
110116
leftArgs := args[1:]
111117
if len(leftArgs) == 0 {

os/gcmd/gcmd_z_unit_feature_object_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,47 @@ func Test_Command_RootTag(t *testing.T) {
139139
t.Assert(value, `{"Content":"john"}`)
140140
})
141141
}
142+
143+
type TestObjectForNeedArgs struct {
144+
g.Meta `name:"root" root:"root"`
145+
}
146+
147+
type TestObjectForNeedArgsEnvInput struct {
148+
g.Meta `name:"env" usage:"root env" brief:"root env command" dc:"root env command description" ad:"root env command ad"`
149+
}
150+
type TestObjectForNeedArgsEnvOutput struct{}
151+
152+
type TestObjectForNeedArgsTestInput struct {
153+
g.Meta `name:"test" args:"true"`
154+
Name string `v:"required" short:"n" orphan:"false" brief:"name for test command"`
155+
}
156+
type TestObjectForNeedArgsTestOutput struct {
157+
Args []string
158+
}
159+
160+
func (TestObjectForNeedArgs) Env(ctx context.Context, in TestObjectForNeedArgsEnvInput) (out *TestObjectForNeedArgsEnvOutput, err error) {
161+
return
162+
}
163+
164+
func (TestObjectForNeedArgs) Test(ctx context.Context, in TestObjectForNeedArgsTestInput) (out *TestObjectForNeedArgsTestOutput, err error) {
165+
parser := gcmd.ParserFromCtx(ctx)
166+
out = &TestObjectForNeedArgsTestOutput{
167+
Args: parser.GetArgAll(),
168+
}
169+
return
170+
}
171+
172+
func Test_Command_NeedArgs(t *testing.T) {
173+
gtest.C(t, func(t *gtest.T) {
174+
var (
175+
ctx = gctx.New()
176+
)
177+
cmd, err := gcmd.NewFromObject(TestObjectForNeedArgs{})
178+
t.AssertNil(err)
179+
180+
os.Args = []string{"root", "test", "a", "b", "c", "-n=john"}
181+
value, err := cmd.RunWithValue(ctx)
182+
t.AssertNil(err)
183+
t.Assert(value, `{"Args":["root","test","a","b","c"]}`)
184+
})
185+
}

0 commit comments

Comments
 (0)