Skip to content

Commit

Permalink
fix issue #3147 (#3161)
Browse files Browse the repository at this point in the history
  • Loading branch information
gqcn committed Nov 22, 2023
1 parent b1754f8 commit ea5d52c
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 98 deletions.
2 changes: 2 additions & 0 deletions cmd/gf/internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
_, err = Version.Index(ctx, cVersionInput{})
return
}

answer := "n"
// No argument or option, do installation checks.
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
Expand All @@ -71,6 +72,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
gcmd.Scan("press `Enter` to exit...")
return
}

// Print help content.
gcmd.CommandFromCtx(ctx).Print()
return
Expand Down
2 changes: 2 additions & 0 deletions os/gcmd/gcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const (
helpOptionNameShort = "h"
maxLineChars = 120
tracingInstrumentName = "github.com/gogf/gf/v2/os/gcmd.Command"
tagNameName = "name"
tagNameShort = "short"
)

// Init does custom initialization.
Expand Down
11 changes: 5 additions & 6 deletions os/gcmd/gcmd_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ type FuncWithValue func(ctx context.Context, parser *Parser) (out interface{}, e

// Argument is the command value that are used by certain command.
type Argument struct {
Name string // Option name.
FieldName string // Option field name.
Short string // Option short.
Brief string // Brief info about this Option, which is used in help info.
IsArg bool // IsArg marks this argument taking value from command line argument instead of option.
Orphan bool // Whether this Option having or having no value bound to it.
Name string // Option name.
Short string // Option short.
Brief string // Brief info about this Option, which is used in help info.
IsArg bool // IsArg marks this argument taking value from command line argument instead of option.
Orphan bool // Whether this Option having or having no value bound to it.
}

var (
Expand Down
18 changes: 13 additions & 5 deletions os/gcmd/gcmd_command_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,6 @@ func newArgumentsFromInput(object interface{}) (args []Argument, err error) {
}
if arg.Name == "" {
arg.Name = field.Name()
} else if arg.Name != field.Name() {
arg.FieldName = field.Name()
nameSet.Add(arg.FieldName)
}
if arg.Name == helpOptionName {
return nil, gerror.Newf(
Expand Down Expand Up @@ -411,14 +408,25 @@ func mergeDefaultStructValue(data map[string]interface{}, pointer interface{}) e
foundValue interface{}
)
for _, field := range tagFields {
var (
nameValue = field.Tag(tagNameName)
shortValue = field.Tag(tagNameShort)
)
// If it already has value, it then ignores the default value.
if value, ok := data[nameValue]; ok {
data[field.Name()] = value
continue
}
if value, ok := data[shortValue]; ok {
data[field.Name()] = value
continue
}
foundKey, foundValue = gutil.MapPossibleItemByKey(data, field.Name())
if foundKey == "" {
data[field.Name()] = field.TagValue
} else {
if utils.IsEmpty(foundValue) {
data[foundKey] = field.TagValue
} else {
data[field.Name()] = foundValue
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions os/gcmd/gcmd_command_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,10 @@ func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error)
if arg.IsArg {
continue
}
optionKey = arg.Name
if arg.FieldName != "" {
optionKey += fmt.Sprintf(`,%s`, arg.FieldName)
}
if arg.Short != "" {
optionKey += fmt.Sprintf(`,%s`, arg.Short)
optionKey = fmt.Sprintf(`%s,%s`, arg.Name, arg.Short)
} else {
optionKey = arg.Name
}
supportedOptions[optionKey] = !arg.Orphan
}
Expand Down
25 changes: 17 additions & 8 deletions os/gcmd/gcmd_z_unit_feature_object1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ type TestCmdObjectEnvInput struct {
type TestCmdObjectEnvOutput struct{}

type TestCmdObjectTestInput struct {
g.Meta `name:"test" usage:"root test" brief:"root test command" dc:"root test command description" ad:"root test command ad"`
Name string `name:"yourname" v:"required" short:"n" orphan:"false" brief:"name for test command" d:"tom"`
g.Meta `name:"test" usage:"root test" brief:"root test command" dc:"root test command description" ad:"root test command ad"`
Name string `name:"yourname" v:"required" short:"n" orphan:"false" brief:"name for test command" d:"tom"`
Version bool `name:"version" short:"v" orphan:"true" brief:"show version"`
}

type TestCmdObjectTestOutput struct {
Content string
Name string
Version bool
}

func (TestCmdObject) Env(ctx context.Context, in TestCmdObjectEnvInput) (out *TestCmdObjectEnvOutput, err error) {
Expand All @@ -44,7 +46,8 @@ func (TestCmdObject) Env(ctx context.Context, in TestCmdObjectEnvInput) (out *Te

func (TestCmdObject) Test(ctx context.Context, in TestCmdObjectTestInput) (out *TestCmdObjectTestOutput, err error) {
out = &TestCmdObjectTestOutput{
Content: in.Name,
Name: in.Name,
Version: in.Version,
}
return
}
Expand Down Expand Up @@ -93,19 +96,25 @@ func Test_Command_NewFromObject_RunWithValue(t *testing.T) {
os.Args = []string{"root", "test", "-n=john"}
value, err := cmd.RunWithValueError(ctx)
t.AssertNil(err)
t.Assert(value, `{"Content":"john"}`)
t.Assert(value, `{"Name":"john","Version":false}`)

// test name tag name
os.Args = []string{"root", "test", "-yourname=hailaz"}
value1, err1 := cmd.RunWithValueError(ctx)
t.AssertNil(err1)
t.Assert(value1, `{"Content":"hailaz"}`)
t.Assert(value1, `{"Name":"hailaz","Version":false}`)

// test default tag value
os.Args = []string{"root", "test"}
value2, err2 := cmd.RunWithValueError(ctx)
t.AssertNil(err2)
t.Assert(value2, `{"Content":"tom"}`)
t.Assert(value2, `{"Name":"tom","Version":false}`)

// test name tag and orphan tag true
os.Args = []string{"root", "test", "-v"}
value3, err3 := cmd.RunWithValueError(ctx)
t.AssertNil(err3)
t.Assert(value3, `{"Name":"tom","Version":true}`)
})
}

Expand All @@ -123,7 +132,7 @@ func Test_Command_AddObject(t *testing.T) {
os.Args = []string{"start", "root", "test", "-n=john"}
value, err := command.RunWithValueError(ctx)
t.AssertNil(err)
t.Assert(value, `{"Content":"john"}`)
t.Assert(value, `{"Name":"john","Version":false}`)
})
}

Expand Down
6 changes: 3 additions & 3 deletions util/gconv/gconv_maptomaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]st
//
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
// sense only if the item of `params` is type struct.
func doMapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
func doMapToMaps(params interface{}, pointer interface{}, paramKeyToAttrMap ...map[string]string) (err error) {
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
switch r := params.(type) {
case []byte:
Expand Down Expand Up @@ -124,13 +124,13 @@ func doMapToMaps(params interface{}, pointer interface{}, mapping ...map[string]
var item reflect.Value
if pointerElemType.Kind() == reflect.Ptr {
item = reflect.New(pointerElemType.Elem())
if err = MapToMap(paramsRv.Index(i).Interface(), item, mapping...); err != nil {
if err = MapToMap(paramsRv.Index(i).Interface(), item, paramKeyToAttrMap...); err != nil {
return err
}
pointerSlice.Index(i).Set(item)
} else {
item = reflect.New(pointerElemType)
if err = MapToMap(paramsRv.Index(i).Interface(), item, mapping...); err != nil {
if err = MapToMap(paramsRv.Index(i).Interface(), item, paramKeyToAttrMap...); err != nil {
return err
}
pointerSlice.Index(i).Set(item.Elem())
Expand Down
10 changes: 5 additions & 5 deletions util/gconv/gconv_scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
// It calls function `doMapToMaps` internally if `pointer` is type of *[]map/*[]*map for converting.
// It calls function `doStruct` internally if `pointer` is type of *struct/**struct for converting.
// It calls function `doStructs` internally if `pointer` is type of *[]struct/*[]*struct for converting.
func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
func Scan(params interface{}, pointer interface{}, paramKeyToAttrMap ...map[string]string) (err error) {
var (
pointerType reflect.Type
pointerKind reflect.Kind
Expand Down Expand Up @@ -82,12 +82,12 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
pointerElemKind = pointerElem.Kind()
keyToAttributeNameMapping map[string]string
)
if len(mapping) > 0 {
keyToAttributeNameMapping = mapping[0]
if len(paramKeyToAttrMap) > 0 {
keyToAttributeNameMapping = paramKeyToAttrMap[0]
}
switch pointerElemKind {
case reflect.Map:
return doMapToMap(params, pointer, mapping...)
return doMapToMap(params, pointer, paramKeyToAttrMap...)

case reflect.Array, reflect.Slice:
var (
Expand All @@ -99,7 +99,7 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
sliceElemKind = sliceElem.Kind()
}
if sliceElemKind == reflect.Map {
return doMapToMaps(params, pointer, mapping...)
return doMapToMaps(params, pointer, paramKeyToAttrMap...)
}
return doStructs(params, pointer, keyToAttributeNameMapping, "")

Expand Down
Loading

0 comments on commit ea5d52c

Please sign in to comment.