update
This commit is contained in:
		
							parent
							
								
									8f6edca654
								
							
						
					
					
						commit
						26b2fecb36
					
				
							
								
								
									
										118
									
								
								cli/cli.go
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								cli/cli.go
									
									
									
									
									
								
							@ -1,118 +0,0 @@
 | 
			
		||||
package cli
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CliFlag struct {
 | 
			
		||||
	Name     string
 | 
			
		||||
	Usage    string
 | 
			
		||||
	DefValue *string
 | 
			
		||||
	CliFlags *[]CliFlag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ValueFlag struct {
 | 
			
		||||
	Value reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ValueFlag) String() string {
 | 
			
		||||
	return this.Value.Kind().String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ValueFlag) Set(v string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Parse(i interface{}, cliFlag *CliFlag) 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 parseValue(valueOfStruct, cliFlag)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseValue(v reflect.Value, cliParent *CliFlag) error {
 | 
			
		||||
	cliFlags := []CliFlag{}
 | 
			
		||||
	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() {
 | 
			
		||||
				cliFlag := createCliFlagFromTag(structOfField.Tag)
 | 
			
		||||
				if cliFlag != nil {
 | 
			
		||||
					cliFlags = append(cliFlags, *cliFlag)
 | 
			
		||||
				} else {
 | 
			
		||||
					cliFlag = cliParent
 | 
			
		||||
				}
 | 
			
		||||
				Parse(valueOfField.Interface(), cliFlag)
 | 
			
		||||
			} else {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		} else if kindOfField == reflect.Struct {
 | 
			
		||||
			cliFlag := createCliFlagFromTag(structOfField.Tag)
 | 
			
		||||
			if cliFlag != nil {
 | 
			
		||||
				cliFlags = append(cliFlags, *cliFlag)
 | 
			
		||||
			} else {
 | 
			
		||||
				cliFlag = cliParent
 | 
			
		||||
			}
 | 
			
		||||
			parseValue(valueOfField, cliFlag)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if cliFlag := installFlag(valueOfField, structOfField); cliFlag != nil {
 | 
			
		||||
			cliFlags = append(cliFlags, *cliFlag)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(cliFlags) > 0 {
 | 
			
		||||
		cliParent.CliFlags = &cliFlags
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func installFlag(v reflect.Value, f reflect.StructField) *CliFlag {
 | 
			
		||||
	cliFlag := createCliFlagFromTag(f.Tag)
 | 
			
		||||
	if cliFlag != nil {
 | 
			
		||||
		vFlag := ValueFlag{Value: v}
 | 
			
		||||
		flag.Var(&vFlag, cliFlag.Name, cliFlag.Usage)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Installed flag: %d", cliFlag.Name)
 | 
			
		||||
	return cliFlag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createCliFlagFromTag(tag reflect.StructTag) *CliFlag {
 | 
			
		||||
	cliTag, ok := tag.Lookup("cli")
 | 
			
		||||
	if !ok || cliTag == "" {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cliFlag := CliFlag{}
 | 
			
		||||
	firstSpace := strings.Index(cliTag, " ")
 | 
			
		||||
	cliFlag.Name = cliTag
 | 
			
		||||
	if firstSpace > 0 {
 | 
			
		||||
		cliFlag.Name = cliTag[0:firstSpace]
 | 
			
		||||
		cliFlag.Usage = cliTag[firstSpace+1:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defValue, ok := tag.Lookup("default")
 | 
			
		||||
	if !ok {
 | 
			
		||||
		cliFlag.DefValue = &defValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &cliFlag
 | 
			
		||||
}
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
package cli
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DBCli struct {
 | 
			
		||||
	Host     string `cli:"hostname database server hostname"`
 | 
			
		||||
	Port     string `cli:"port database server port"`
 | 
			
		||||
	User     string `cli:"user database username"`
 | 
			
		||||
	Password string `cli:"password database user password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MyCli struct {
 | 
			
		||||
	Server string `cli:"-server server URL"`
 | 
			
		||||
	DBCli  DBCli  `cli:"database database information"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCli(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	hostname := flag.String("hostanme", "127.0.0.1", "hostanme value")
 | 
			
		||||
	fmt.Printf("Hostname: %s", hostname)
 | 
			
		||||
 | 
			
		||||
	cli := DBCli{}
 | 
			
		||||
	root := CliFlag{}
 | 
			
		||||
	err := Parse(&cli, &root)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Can't parse cli. %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								cmd/.cli.go.swp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								cmd/.cli.go.swp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								cmd/.cli_test.go.swp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								cmd/.cli_test.go.swp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										139
									
								
								cmd/cmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								cmd/cmd.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,139 @@
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										120
									
								
								cmd/cmd_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								cmd/cmd_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,120 @@
 | 
			
		||||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dbConfig struct {
 | 
			
		||||
	Host     string    `cmd:"dbHost database server hostname"`
 | 
			
		||||
	Port     int       `cmd:"dbPort database server port"`
 | 
			
		||||
	User     string    `cmd:"dbUser database username"`
 | 
			
		||||
	Password string    `cmd:"dbPassword database user password"`
 | 
			
		||||
	Log      logConfig `cmd:"log database log configuration"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type loginConfig struct {
 | 
			
		||||
	User     string `cmd:"user login username"`
 | 
			
		||||
	Password string `cmd:"password login password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type logConfig struct {
 | 
			
		||||
	Path  string `cmd:"path log path"`
 | 
			
		||||
	Level string `cmd:"level log level {debug|warning|error}"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type serviceConfig struct {
 | 
			
		||||
	Host     string       `cmd:"hostname service hostname"`
 | 
			
		||||
	Port     int          `cmd:"port service port"`
 | 
			
		||||
	DBConfig dbConfig     `cmd:"database database configuration"`
 | 
			
		||||
	Login    *loginConfig `cmd:"login login user and password"`
 | 
			
		||||
	Log      logConfig    `cmd:"log service log configuration"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestServiceCommand(t *testing.T) {
 | 
			
		||||
	assert := assert.New(t)
 | 
			
		||||
	serviceConfig := serviceConfig{}
 | 
			
		||||
	cmd := New("Service")
 | 
			
		||||
	err := cmd.Init(&serviceConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Can't init service command. %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// assert service cmd
 | 
			
		||||
	assert.NotNil(cmd.FlagSet)
 | 
			
		||||
	assert.NotNil(cmd.FlagSet.Lookup("hostname"),
 | 
			
		||||
		"service cmd should have {hostname} parameter")
 | 
			
		||||
	assert.NotNil(cmd.FlagSet.Lookup("port"),
 | 
			
		||||
		"service cmd should have {port} parameter")
 | 
			
		||||
	assert.Equal(2, len(cmd.SubCommands),
 | 
			
		||||
		"service cmd should have 2 sub cmds")
 | 
			
		||||
	assert.Nil(cmd.SubCommands["login"],
 | 
			
		||||
		"service cmd shouldn't have {login} sub cmd")
 | 
			
		||||
 | 
			
		||||
	// assert database sub cmd
 | 
			
		||||
	dbCmd := cmd.SubCommands["database"]
 | 
			
		||||
	assert.NotNil(dbCmd, "service cmd should have {database} sub cmd")
 | 
			
		||||
	assert.NotNil(dbCmd.FlagSet.Lookup("dbHost"),
 | 
			
		||||
		"database cmd should have {dbHost} parameter")
 | 
			
		||||
	assert.NotNil(dbCmd.FlagSet.Lookup("dbPort"),
 | 
			
		||||
		"database cmd should have {dbPort} parameter")
 | 
			
		||||
	assert.NotNil(dbCmd.FlagSet.Lookup("dbUser"),
 | 
			
		||||
		"database cmd should have {dbUser} parameter")
 | 
			
		||||
	assert.NotNil(dbCmd.FlagSet.Lookup("dbPassword"),
 | 
			
		||||
		"database cmd should have {dbPassword} parameter")
 | 
			
		||||
 | 
			
		||||
	// assert database log sub cmd
 | 
			
		||||
	dbLogCmd := dbCmd.SubCommands["log"]
 | 
			
		||||
	assert.NotNil(dbCmd, "database cmd should have {log} sub cmd")
 | 
			
		||||
	assert.NotNil(dbLogCmd.FlagSet.Lookup("path"),
 | 
			
		||||
		"database log cmd should have {path} parameter")
 | 
			
		||||
	assert.NotNil(dbLogCmd.FlagSet.Lookup("level"),
 | 
			
		||||
		"database log cmd should have {level} parameter")
 | 
			
		||||
	assert.Equal(0, len(dbLogCmd.SubCommands),
 | 
			
		||||
		"database log cmd shouldn't have sub cmd")
 | 
			
		||||
 | 
			
		||||
	// assert log cmd
 | 
			
		||||
	logCmd := cmd.SubCommands["log"]
 | 
			
		||||
	assert.NotNil(logCmd, "service cmd should have {log} sub cmd")
 | 
			
		||||
	assert.NotNil(logCmd.FlagSet.Lookup("path"),
 | 
			
		||||
		"log cmd should have {path} parameter")
 | 
			
		||||
	assert.NotNil(logCmd.FlagSet.Lookup("level"),
 | 
			
		||||
		"log cmd should have {level} parameter")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoginSubCommand(t *testing.T) {
 | 
			
		||||
	assert := assert.New(t)
 | 
			
		||||
	serviceConfig := serviceConfig{Login: &loginConfig{}}
 | 
			
		||||
	cmd := New("Service")
 | 
			
		||||
	err := cmd.Init(&serviceConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Can't init service command. %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// assert login sub command
 | 
			
		||||
	loginCmd := cmd.SubCommands["login"]
 | 
			
		||||
	assert.NotNil(loginCmd, "service cmd should have {login} sub cmd")
 | 
			
		||||
	assert.NotNil(loginCmd.FlagSet.Lookup("user"),
 | 
			
		||||
		"login cmd should have {user} parameter")
 | 
			
		||||
	assert.NotNil(loginCmd.FlagSet.Lookup("password"),
 | 
			
		||||
		"login cmd should have {password} parameter")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoginCommand(t *testing.T) {
 | 
			
		||||
	loginConfig := loginConfig{}
 | 
			
		||||
	cmd := New("Login")
 | 
			
		||||
	if err := cmd.Init(&loginConfig); err != nil {
 | 
			
		||||
		t.Errorf("Can't init login command. %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args := []string{"-user", "test", "-password", "pass", "log", "database"}
 | 
			
		||||
	if err := cmd.FlagSet.Parse(args); err != nil {
 | 
			
		||||
		t.Errorf("Can't parse login command. %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uknArgs := cmd.FlagSet.Args()
 | 
			
		||||
	for i, arg := range uknArgs {
 | 
			
		||||
		t.Logf("arg[%d]=%s", i, arg)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										106
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								main.go
									
									
									
									
									
								
							@ -1,10 +1,114 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	//"github.com/eschao/Config/cli"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DBCli struct {
 | 
			
		||||
	Host     string `cli:"hostname database server hostname"`
 | 
			
		||||
	Port     string `cli:"port database server port"`
 | 
			
		||||
	User     string `cli:"user database username"`
 | 
			
		||||
	Password string `cli:"password database user password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	cli := DBCli{}
 | 
			
		||||
 | 
			
		||||
	countCommand := flag.NewFlagSet("count", flag.ExitOnError)
 | 
			
		||||
	listCommand := flag.NewFlagSet("list", flag.ExitOnError)
 | 
			
		||||
 | 
			
		||||
	// Count subcommand flag pointers
 | 
			
		||||
	// Adding a new choice for --metric of 'substring' and a new --substring flag
 | 
			
		||||
	countTextPtr := countCommand.String("text", "", "Text to parse. (Required)")
 | 
			
		||||
	countMetricPtr := countCommand.String("metric", "chars", "Metric {chars|words|lines|substring}. (Required)")
 | 
			
		||||
	countSubstringPtr := countCommand.String("substring", "", "The substring to be counted. Required for --metric=substring")
 | 
			
		||||
	countUniquePtr := countCommand.Bool("unique", false, "Measure unique values of a metric.")
 | 
			
		||||
 | 
			
		||||
	// List subcommand flag pointers
 | 
			
		||||
	listTextPtr := listCommand.String("text", "", "Text to parse. (Required)")
 | 
			
		||||
	listMetricPtr := listCommand.String("metric", "chars", "Metric <chars|words|lines>. (Required)")
 | 
			
		||||
	listUniquePtr := listCommand.Bool("unique", false, "Measure unique values of a metric.")
 | 
			
		||||
 | 
			
		||||
	// Verify that a subcommand has been provided
 | 
			
		||||
	// os.Arg[0] is the main command
 | 
			
		||||
	// os.Arg[1] will be the subcommand
 | 
			
		||||
	if len(os.Args) < 2 {
 | 
			
		||||
		//fmt.Println("list or count subcommand is required")
 | 
			
		||||
		flag.PrintDefaults()
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Switch on the subcommand
 | 
			
		||||
	// Parse the flags for appropriate FlagSet
 | 
			
		||||
	// FlagSet.Parse() requires a set of arguments to parse as input
 | 
			
		||||
	// os.Args[2:] will be all arguments starting after the subcommand at os.Args[1]
 | 
			
		||||
	switch os.Args[1] {
 | 
			
		||||
	case "list":
 | 
			
		||||
		listCommand.Parse(os.Args[2:])
 | 
			
		||||
	case "count":
 | 
			
		||||
		countCommand.Parse(os.Args[2:])
 | 
			
		||||
	default:
 | 
			
		||||
		flag.PrintDefaults()
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check which subcommand was Parsed using the FlagSet.Parsed() function. Handle each case accordingly.
 | 
			
		||||
	// FlagSet.Parse() will evaluate to false if no flags were parsed (i.e. the user did not provide any flags)
 | 
			
		||||
	if listCommand.Parsed() {
 | 
			
		||||
		// Required Flags
 | 
			
		||||
		if *listTextPtr == "" {
 | 
			
		||||
			listCommand.PrintDefaults()
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		//Choice flag
 | 
			
		||||
		metricChoices := map[string]bool{"chars": true, "words": true, "lines": true}
 | 
			
		||||
		if _, validChoice := metricChoices[*listMetricPtr]; !validChoice {
 | 
			
		||||
			listCommand.PrintDefaults()
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		// Print
 | 
			
		||||
		fmt.Printf("textPtr: %s, metricPtr: %s, uniquePtr: %t\n", *listTextPtr, *listMetricPtr, *listUniquePtr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if countCommand.Parsed() {
 | 
			
		||||
		// Required Flags
 | 
			
		||||
		if *countTextPtr == "" {
 | 
			
		||||
			countCommand.PrintDefaults()
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		// If the metric flag is substring, the substring flag is required
 | 
			
		||||
		if *countMetricPtr == "substring" && *countSubstringPtr == "" {
 | 
			
		||||
			countCommand.PrintDefaults()
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		//If the metric flag is not substring, the substring flag must not be used
 | 
			
		||||
		if *countMetricPtr != "substring" && *countSubstringPtr != "" {
 | 
			
		||||
			fmt.Println("--substring may only be used with --metric=substring.")
 | 
			
		||||
			countCommand.PrintDefaults()
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		//Choice flag
 | 
			
		||||
		metricChoices := map[string]bool{"chars": true, "words": true, "lines": true, "substring": true}
 | 
			
		||||
		if _, validChoice := metricChoices[*listMetricPtr]; !validChoice {
 | 
			
		||||
			countCommand.PrintDefaults()
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		//Print
 | 
			
		||||
		fmt.Printf("textPtr: %s, metricPtr: %s, substringPtr: %v, uniquePtr: %t\n", *countTextPtr, *countMetricPtr, *countSubstringPtr, *countUniquePtr)
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
		config := DBCli{}
 | 
			
		||||
		root := cli.CliFlag{}
 | 
			
		||||
		err := cli.Parse(&config, &root)
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Printf("Can't parse cli. %s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		flag.Parse()
 | 
			
		||||
 | 
			
		||||
		fmt.Printf("Host=%s\n", config.Host)
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								util/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								util/util.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
package util
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func SetValueWithBool(v reflect.Value, boolValue string) error {
 | 
			
		||||
	value, err := strconv.ParseBool(boolValue)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.SetBool(value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetValueWithFloatX(v reflect.Value, floatValue string, bitSize int) error {
 | 
			
		||||
	value, err := strconv.ParseFloat(floatValue, bitSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.SetFloat(value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetValueWithIntX(v reflect.Value, intValue string, bitSize int) error {
 | 
			
		||||
	value, err := strconv.ParseInt(envValue, 10, bitSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.SetInt(value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetValueWithUintX(v reflect.Value, envValue string, bitSize int) error {
 | 
			
		||||
	value, err := strconv.ParseUint(envValue, 10, bitSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.SetUint(value)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
func setFieldValueWithSlice(name string, v reflect.Value, envValue string,
 | 
			
		||||
	separator string) error {
 | 
			
		||||
	data := strings.Split(envValue, separator)
 | 
			
		||||
	size := len(data)
 | 
			
		||||
	if size > 0 {
 | 
			
		||||
		slice := reflect.MakeSlice(v.Type(), size, size)
 | 
			
		||||
		for i := 0; i < size; i++ {
 | 
			
		||||
			ele := slice.Index(i)
 | 
			
		||||
			kind := ele.Kind()
 | 
			
		||||
			switch kind {
 | 
			
		||||
			case reflect.Bool:
 | 
			
		||||
				if err := setFieldValueWithBool(name, ele, data[i]); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.String:
 | 
			
		||||
				ele.SetString(data[i])
 | 
			
		||||
			case reflect.Uint8:
 | 
			
		||||
				if err := setFieldValueWithUintX(name, ele, data[i], 8); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Uint16:
 | 
			
		||||
				if err := setFieldValueWithUintX(name, ele, data[i], 16); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Uint, reflect.Uint32:
 | 
			
		||||
				if err := setFieldValueWithUintX(name, ele, data[i], 32); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Uint64:
 | 
			
		||||
				if err := setFieldValueWithUintX(name, ele, data[i], 64); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Int8:
 | 
			
		||||
				if err := setFieldValueWithIntX(name, ele, data[i], 8); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Int16:
 | 
			
		||||
				if err := setFieldValueWithIntX(name, ele, data[i], 16); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Int, reflect.Int32:
 | 
			
		||||
				if err := setFieldValueWithIntX(name, ele, data[i], 32); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Int64:
 | 
			
		||||
				if err := setFieldValueWithIntX(name, ele, data[i], 64); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Float32:
 | 
			
		||||
				if err := setFieldValueWithFloatX(name, ele, data[i], 32); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			case reflect.Float64:
 | 
			
		||||
				if err := setFieldValueWithFloatX(name, ele, data[i], 64); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			default:
 | 
			
		||||
				return fmt.Errorf("%s: can't support type: %s", name, kind.String())
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		v.Set(slice)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}*/
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user