140 lines
2.9 KiB
Go
140 lines
2.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/eschao/config/util"
|
|
)
|
|
|
|
type anyValue struct {
|
|
any reflect.Value
|
|
}
|
|
|
|
func newAnyValue(v Value) *anyValue {
|
|
return anyValue{any: v}
|
|
}
|
|
|
|
func (this *anyValue) String() string {
|
|
return this.any.Kind().String()
|
|
}
|
|
|
|
func (this *anyValue) Set(v string) error {
|
|
kind := this.any.Kind()
|
|
switch kind {
|
|
case reflect.Bool:
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Command struct {
|
|
Name string
|
|
FlagSet *flag.FlagSet
|
|
Usage string
|
|
SubCommands map[string]*Command
|
|
}
|
|
|
|
func New(name string) *Command {
|
|
cmd := Command{
|
|
Name: name,
|
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
|
SubCommands: make(map[string]*Command),
|
|
}
|
|
return &cmd
|
|
}
|
|
|
|
func (this *Command) Init(i interface{}) error {
|
|
ptrRef := reflect.ValueOf(i)
|
|
|
|
if ptrRef.IsNil() || ptrRef.Kind() != reflect.Ptr {
|
|
return fmt.Errorf("Expect a structure pointer type instead of %s",
|
|
ptrRef.Kind().String())
|
|
}
|
|
|
|
valueOfStruct := ptrRef.Elem()
|
|
if valueOfStruct.Kind() != reflect.Struct {
|
|
return fmt.Errorf("Expect a structure type instead of %s",
|
|
valueOfStruct.Kind().String())
|
|
}
|
|
|
|
return this.parseValue(valueOfStruct)
|
|
}
|
|
|
|
func (this *Command) parseValue(v reflect.Value) error {
|
|
typeOfStruct := v.Type()
|
|
|
|
for i := 0; i < v.NumField(); i++ {
|
|
valueOfField := v.Field(i)
|
|
kindOfField := valueOfField.Kind()
|
|
structOfField := typeOfStruct.Field(i)
|
|
|
|
if kindOfField == reflect.Ptr {
|
|
if !valueOfField.IsNil() && valueOfField.CanSet() {
|
|
cmd := this.createCliFlagSet(structOfField.Tag)
|
|
if err := cmd.Init(valueOfField.Interface()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else if kindOfField == reflect.Struct {
|
|
cmd := this.createCliFlagSet(structOfField.Tag)
|
|
if err := cmd.parseValue(valueOfField); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
this.addFlag(valueOfField, structOfField)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (this *Command) addFlag(v reflect.Value, f reflect.StructField) {
|
|
cmdTag, ok := f.Tag.Lookup("cmd")
|
|
if !ok || cmdTag == "" {
|
|
return
|
|
}
|
|
|
|
firstSpace := strings.Index(cmdTag, " ")
|
|
name := cmdTag
|
|
usage := ""
|
|
if firstSpace > 0 {
|
|
name = cmdTag[0:firstSpace]
|
|
usage = cmdTag[firstSpace+1:]
|
|
}
|
|
|
|
//defValue, ok := f.Tag.Lookup("default")
|
|
vFlag := ValueFlag{Value: v}
|
|
this.FlagSet.Var(&vFlag, name, usage)
|
|
//fmt.Printf("[%s]: Added Flag: %s\n", this.Name, name)
|
|
}
|
|
|
|
func (this *Command) createCliFlagSet(tag reflect.StructTag) *Command {
|
|
cmdTag, ok := tag.Lookup("cmd")
|
|
if !ok || cmdTag == "" {
|
|
return this
|
|
}
|
|
|
|
cmd := Command{SubCommands: make(map[string]*Command)}
|
|
firstSpace := strings.Index(cmdTag, " ")
|
|
name := cmdTag
|
|
usage := ""
|
|
if firstSpace > 0 {
|
|
name = cmdTag[0:firstSpace]
|
|
usage = cmdTag[firstSpace+1:]
|
|
}
|
|
|
|
cmd.Name = name
|
|
cmd.FlagSet = flag.NewFlagSet(name, flag.ExitOnError)
|
|
cmd.Usage = usage
|
|
this.SubCommands[name] = &cmd
|
|
return &cmd
|
|
}
|
|
|
|
func (this *Command) Parse(i interface{}, args []string) error {
|
|
|
|
return nil
|
|
}
|