add case
This commit is contained in:
parent
ff4c06dd0a
commit
cf86d63d24
74
flag.go
74
flag.go
|
@ -4,7 +4,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FVSet struct {
|
type FVSet struct {
|
||||||
|
@ -19,6 +21,56 @@ func (f *FVSet) Parse(args []string) error {
|
||||||
func isPtr(v interface{}) bool {
|
func isPtr(v interface{}) bool {
|
||||||
return reflect.TypeOf(v).Kind() == reflect.Ptr
|
return reflect.TypeOf(v).Kind() == reflect.Ptr
|
||||||
}
|
}
|
||||||
|
func (f *FVSet) Args() interface{} {
|
||||||
|
return f.flags.Args()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FVSet) Usage() {
|
||||||
|
f.flags.Usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
type FVSets struct {
|
||||||
|
flagSets []*FVSet
|
||||||
|
subcommands []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FVSets) Add(v interface{}) error {
|
||||||
|
fv, err := NewFVSet(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fv.flags.Usage = func() {
|
||||||
|
f.Usage()
|
||||||
|
}
|
||||||
|
f.flagSets = append(f.flagSets, fv)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (f *FVSets) Parse(args []string) error {
|
||||||
|
for _, v := range f.flagSets {
|
||||||
|
err := v.Parse(args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (f *FVSets) Usage() {
|
||||||
|
//for _, v := range f.flagSets {
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToKebabCase(input string) string {
|
||||||
|
// 将字符串中的大写字母前插入连字符,并转换为小写
|
||||||
|
re := regexp.MustCompile("([a-z])([A-Z])")
|
||||||
|
kebab := re.ReplaceAllString(input, "${1}-${2}")
|
||||||
|
kebab = strings.ToLower(kebab)
|
||||||
|
|
||||||
|
// 去除字符串开头和结尾的连字符
|
||||||
|
kebab = strings.Trim(kebab, "-")
|
||||||
|
|
||||||
|
return kebab
|
||||||
|
}
|
||||||
|
|
||||||
// NewFVSet 创建一个新的FVSet实例,用于处理命令行标志。
|
// NewFVSet 创建一个新的FVSet实例,用于处理命令行标志。
|
||||||
// 参数v是一个指向结构体的指针,该结构体的字段将被用作命令行标志。
|
// 参数v是一个指向结构体的指针,该结构体的字段将被用作命令行标志。
|
||||||
|
@ -51,23 +103,35 @@ func NewFVSet(v interface{}) (*FVSet, error) {
|
||||||
if flaName == "" {
|
if flaName == "" {
|
||||||
flaName = stField.Name
|
flaName = stField.Name
|
||||||
}
|
}
|
||||||
|
flaName = ToKebabCase(flaName)
|
||||||
|
flShort := stField.Tag.Get("flag_short")
|
||||||
defVal := stField.Tag.Get("flag_default")
|
defVal := stField.Tag.Get("flag_default")
|
||||||
usageStr := stField.Tag.Get("flag_usage")
|
usageStr := stField.Tag.Get("flag_usage")
|
||||||
if usageStr == "" {
|
if usageStr == "" {
|
||||||
usageStr = "Set " + flaName + "(default " + defVal + ")"
|
usageStr = "Set " + flaName + "(default " + defVal + ")"
|
||||||
}
|
}
|
||||||
|
addr := field.Addr()
|
||||||
if field.CanSet() {
|
if field.CanSet() {
|
||||||
switch expression := field.Interface().(type) {
|
switch field.Interface().(type) {
|
||||||
case string:
|
case string:
|
||||||
flags.StringVar(&expression, flaName, defVal, usageStr)
|
flags.StringVar(addr.Interface().(*string), flaName, defVal, usageStr)
|
||||||
|
if flShort != "" {
|
||||||
|
flags.StringVar(addr.Interface().(*string), flShort, defVal, usageStr)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case int:
|
case int:
|
||||||
v, _ := strconv.Atoi(defVal)
|
v, _ := strconv.Atoi(defVal)
|
||||||
flags.IntVar(&expression, flaName, v, usageStr)
|
flags.IntVar(addr.Interface().(*int), flaName, v, usageStr)
|
||||||
|
if flShort != "" {
|
||||||
|
|
||||||
|
flags.IntVar(addr.Interface().(*int), flShort, v, usageStr)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case bool:
|
case bool:
|
||||||
flags.BoolVar(&expression, flaName, false, usageStr)
|
flags.BoolVar(addr.Interface().(*bool), flaName, false, usageStr)
|
||||||
|
if flShort != "" {
|
||||||
|
flags.BoolVar(addr.Interface().(*bool), flShort, false, usageStr)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseSingle(t *testing.T) {
|
||||||
|
type targs struct {
|
||||||
|
Test string `flag_default:"test" flag_usage:"this is test"`
|
||||||
|
TestBool bool `flag_short:"b"`
|
||||||
|
TestInt int
|
||||||
|
}
|
||||||
|
sargs := &targs{}
|
||||||
|
v, _ := NewFVSet(sargs)
|
||||||
|
v.Usage()
|
||||||
|
err := Parse([]string{"--test", "test", "--test-bool", "--test-int", "1"}, v)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if sargs.Test != "test" {
|
||||||
|
t.Error("test failed")
|
||||||
|
}
|
||||||
|
if !sargs.TestBool {
|
||||||
|
t.Error("test failed")
|
||||||
|
}
|
||||||
|
if sargs.TestInt != 1 {
|
||||||
|
t.Error("test failed")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue