mirror of
https://gitee.com/johng/gf
synced 2026-07-04 13:02:36 +08:00
improve package gcmd, adding CaseSensitive option for options parsing, default is CaseInsensitive
This commit is contained in:
@ -28,6 +28,7 @@ type Command struct {
|
||||
Examples string // Usage examples.
|
||||
Additional string // Additional info about this command, which will be appended to the end of help info.
|
||||
Strict bool // Strict parsing options, which means it returns error if invalid option given.
|
||||
CaseSensitive bool // CaseSensitive parsing options, which means it parses input options in case-sensitive way.
|
||||
Config string // Config node name, which also retrieves the values from config component along with command line.
|
||||
parent *Command // Parent command for internal usage.
|
||||
commands []*Command // Sub commands of this command.
|
||||
|
||||
@ -146,7 +146,10 @@ func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error)
|
||||
}
|
||||
supportedOptions[optionKey] = !arg.Orphan
|
||||
}
|
||||
parser, err := Parse(supportedOptions, c.Strict)
|
||||
parser, err := Parse(supportedOptions, ParserOption{
|
||||
CaseSensitive: c.CaseSensitive,
|
||||
Strict: c.Strict,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -21,9 +21,15 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
// ParserOption manages the parsing options.
|
||||
type ParserOption struct {
|
||||
CaseSensitive bool // Marks options parsing in case-sensitive way.
|
||||
Strict bool // Whether stops parsing and returns error if invalid option passed.
|
||||
}
|
||||
|
||||
// Parser for arguments.
|
||||
type Parser struct {
|
||||
strict bool // Whether stops parsing and returns error if invalid option passed.
|
||||
option ParserOption // Parse option.
|
||||
parsedArgs []string // As name described.
|
||||
parsedOptions map[string]string // As name described.
|
||||
passedOptions map[string]bool // User passed supported options, like: map[string]bool{"name,n":true}
|
||||
@ -47,7 +53,7 @@ func ParserFromCtx(ctx context.Context) *Parser {
|
||||
// the value item of `supportedOptions` indicates whether corresponding option name needs argument or not.
|
||||
//
|
||||
// The optional parameter `strict` specifies whether stops parsing and returns error if invalid option passed.
|
||||
func Parse(supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
func Parse(supportedOptions map[string]bool, option ...ParserOption) (*Parser, error) {
|
||||
if supportedOptions == nil {
|
||||
command.Init(os.Args...)
|
||||
return &Parser{
|
||||
@ -55,7 +61,7 @@ func Parse(supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
parsedOptions: GetOptAll(),
|
||||
}, nil
|
||||
}
|
||||
return ParseArgs(os.Args, supportedOptions, strict...)
|
||||
return ParseArgs(os.Args, supportedOptions, option...)
|
||||
}
|
||||
|
||||
// ParseArgs creates and returns a new Parser with given arguments and supported options.
|
||||
@ -64,7 +70,7 @@ func Parse(supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
// the value item of `supportedOptions` indicates whether corresponding option name needs argument or not.
|
||||
//
|
||||
// The optional parameter `strict` specifies whether stops parsing and returns error if invalid option passed.
|
||||
func ParseArgs(args []string, supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
func ParseArgs(args []string, supportedOptions map[string]bool, option ...ParserOption) (*Parser, error) {
|
||||
if supportedOptions == nil {
|
||||
command.Init(args...)
|
||||
return &Parser{
|
||||
@ -72,12 +78,12 @@ func ParseArgs(args []string, supportedOptions map[string]bool, strict ...bool)
|
||||
parsedOptions: GetOptAll(),
|
||||
}, nil
|
||||
}
|
||||
strictParsing := false
|
||||
if len(strict) > 0 {
|
||||
strictParsing = strict[0]
|
||||
var parserOption ParserOption
|
||||
if len(option) > 0 {
|
||||
parserOption = option[0]
|
||||
}
|
||||
parser := &Parser{
|
||||
strict: strictParsing,
|
||||
option: parserOption,
|
||||
parsedArgs: make([]string, 0),
|
||||
parsedOptions: make(map[string]string),
|
||||
passedOptions: supportedOptions,
|
||||
@ -118,7 +124,7 @@ func ParseArgs(args []string, supportedOptions map[string]bool, strict ...bool)
|
||||
}
|
||||
i++
|
||||
continue
|
||||
} else if parser.strict {
|
||||
} else if parser.option.Strict {
|
||||
return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `invalid option '%s'`, args[i])
|
||||
}
|
||||
}
|
||||
@ -159,8 +165,18 @@ func (p *Parser) parseOption(argument string) string {
|
||||
}
|
||||
|
||||
func (p *Parser) isOptionValid(name string) bool {
|
||||
_, ok := p.supportedOptions[name]
|
||||
return ok
|
||||
// Case-Sensitive.
|
||||
if p.option.CaseSensitive {
|
||||
_, ok := p.supportedOptions[name]
|
||||
return ok
|
||||
}
|
||||
// Case-InSensitive.
|
||||
for optionName, _ := range p.supportedOptions {
|
||||
if gstr.Equal(optionName, name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) isOptionNeedArgument(name string) bool {
|
||||
|
||||
50
os/gcmd/gcmd_z_unit_feature_object3_test.go
Normal file
50
os/gcmd/gcmd_z_unit_feature_object3_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcmd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
type TestParamsCase struct {
|
||||
g.Meta `name:"root" root:"root"`
|
||||
}
|
||||
|
||||
type TestParamsCaseRootInput struct {
|
||||
g.Meta `name:"root"`
|
||||
Name string
|
||||
}
|
||||
type TestParamsCaseRootOutput struct {
|
||||
Content string
|
||||
}
|
||||
|
||||
func (c *TestParamsCase) Root(ctx context.Context, in TestParamsCaseRootInput) (out *TestParamsCaseRootOutput, err error) {
|
||||
out = &TestParamsCaseRootOutput{
|
||||
Content: in.Name,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Test_Command_ParamsCase(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var ctx = gctx.New()
|
||||
cmd, err := gcmd.NewFromObject(TestParamsCase{})
|
||||
t.AssertNil(err)
|
||||
|
||||
os.Args = []string{"root", "-name=john"}
|
||||
value, err := cmd.RunWithValueError(ctx)
|
||||
t.AssertNil(err)
|
||||
t.Assert(value, `{"Content":"john"}`)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user