add new slice type parser, add help flag
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
c1f8fa376a
commit
b619f2f11e
108
argparse.go
108
argparse.go
@ -3,22 +3,30 @@ package argparse
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
args []*arg
|
args []*arg
|
||||||
|
showHelp bool
|
||||||
parsed bool
|
parsed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Option struct {
|
||||||
|
Require bool
|
||||||
|
}
|
||||||
|
|
||||||
type arg struct {
|
type arg struct {
|
||||||
sname string
|
sname string
|
||||||
lname string
|
lname string
|
||||||
// value number count
|
// value item count
|
||||||
size int
|
size int
|
||||||
value interface{}
|
value interface{}
|
||||||
unique bool
|
unique bool
|
||||||
parsed bool
|
parsed bool
|
||||||
|
opts *Option
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *Parser {
|
func New() *Parser {
|
||||||
@ -29,7 +37,7 @@ func New() *Parser {
|
|||||||
|
|
||||||
func (p *Parser) addArg(a *arg) error {
|
func (p *Parser) addArg(a *arg) error {
|
||||||
for _, v := range p.args {
|
for _, v := range p.args {
|
||||||
if (v.sname == a.sname || v.lname == a.lname) && (a.unique || v.unique) {
|
if v.sname == a.sname || v.lname == a.lname {
|
||||||
return errors.New("option name dup")
|
return errors.New("option name dup")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,11 +46,14 @@ func (p *Parser) addArg(a *arg) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) typeVar(i interface{}, short, long string, size int, unique bool) {
|
func (p *Parser) typeVar(i interface{}, short, long string, size int, unique bool, opts *Option) {
|
||||||
t := reflect.ValueOf(i)
|
t := reflect.ValueOf(i)
|
||||||
if t.Kind() != reflect.Ptr {
|
if t.Kind() != reflect.Ptr {
|
||||||
panic(errors.New("var type not ptr"))
|
panic(errors.New("var type not ptr"))
|
||||||
}
|
}
|
||||||
|
if short == "" && long == "" {
|
||||||
|
panic(errors.New("short name and long name is empty"))
|
||||||
|
}
|
||||||
|
|
||||||
a := &arg{
|
a := &arg{
|
||||||
sname: short,
|
sname: short,
|
||||||
@ -50,6 +61,7 @@ func (p *Parser) typeVar(i interface{}, short, long string, size int, unique boo
|
|||||||
value: i,
|
value: i,
|
||||||
size: size,
|
size: size,
|
||||||
unique: unique,
|
unique: unique,
|
||||||
|
opts: opts,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p.addArg(a); err != nil {
|
if err := p.addArg(a); err != nil {
|
||||||
@ -57,6 +69,24 @@ func (p *Parser) typeVar(i interface{}, short, long string, size int, unique boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Parser) Help(short, long string) {
|
||||||
|
p.typeVar(&p.showHelp, short, long, 0, true, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) printHelp() {
|
||||||
|
sb := &strings.Builder{}
|
||||||
|
sb.WriteString("Usage:\n")
|
||||||
|
for _, v := range p.args {
|
||||||
|
if _, err := sb.WriteString(fmt.Sprintf("\t%s\t%s\n", v.name(), v.getType())); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(sb.String())
|
||||||
|
// if flag.Lookup("test.v") == nil {
|
||||||
|
os.Exit(2)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Parser) Parse(a []string) error {
|
func (p *Parser) Parse(a []string) error {
|
||||||
copyArg := make([]string, len(a))
|
copyArg := make([]string, len(a))
|
||||||
copy(copyArg, a)
|
copy(copyArg, a)
|
||||||
@ -84,6 +114,10 @@ func (p *Parser) parse(args *[]string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.parsed = true
|
p.parsed = true
|
||||||
|
|
||||||
|
if p.showHelp == true {
|
||||||
|
p.printHelp()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,52 +151,88 @@ func (p *Parser) parseArguemtns(args *[]string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if oarg.opts != nil && oarg.opts.Require && !oarg.parsed {
|
||||||
|
return fmt.Errorf("[%s] is required", oarg.name())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) String(short, long string) *string {
|
func (p *Parser) String(short, long string, opts *Option) *string {
|
||||||
var result string
|
var result string
|
||||||
|
|
||||||
p.typeVar(&result, short, long, 1, true)
|
p.typeVar(&result, short, long, 1, true, opts)
|
||||||
|
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
func (p *Parser) StringVar(i *string, short, long string) {
|
func (p *Parser) StringVar(i *string, short, long string, opts *Option) {
|
||||||
p.typeVar(i, short, long, 1, true)
|
p.typeVar(i, short, long, 1, true, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Int(short, long string) *int {
|
func (p *Parser) Int(short, long string, opts *Option) *int {
|
||||||
var result int
|
var result int
|
||||||
|
|
||||||
p.typeVar(&result, short, long, 1, true)
|
p.typeVar(&result, short, long, 1, true, opts)
|
||||||
|
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
func (p *Parser) IntVar(i *int, short, long string) {
|
func (p *Parser) IntVar(i *int, short, long string, opts *Option) {
|
||||||
p.typeVar(i, short, long, 1, true)
|
p.typeVar(i, short, long, 1, true, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Bool(short, long string) *bool {
|
func (p *Parser) Bool(short, long string, opts *Option) *bool {
|
||||||
var result bool
|
var result bool
|
||||||
|
|
||||||
p.typeVar(&result, short, long, 0, true)
|
p.typeVar(&result, short, long, 0, true, opts)
|
||||||
|
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
func (p *Parser) BoolVar(i *bool, short, long string) {
|
func (p *Parser) BoolVar(i *bool, short, long string, opts *Option) {
|
||||||
p.typeVar(i, short, long, 0, true)
|
p.typeVar(i, short, long, 0, true, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Float(short, long string) *float64 {
|
func (p *Parser) Float(short, long string, opts *Option) *float64 {
|
||||||
var result float64
|
var result float64
|
||||||
|
|
||||||
p.typeVar(&result, short, long, 1, true)
|
p.typeVar(&result, short, long, 1, true, opts)
|
||||||
|
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
func (p *Parser) FloatVar(i *float64, short, long string) {
|
func (p *Parser) FloatVar(i *float64, short, long string, opts *Option) {
|
||||||
p.typeVar(i, short, long, 1, true)
|
p.typeVar(i, short, long, 1, true, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) StringSlice(short, long string, opts *Option) *[]string {
|
||||||
|
var result []string
|
||||||
|
|
||||||
|
p.typeVar(&result, short, long, 1, false, opts)
|
||||||
|
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
func (p *Parser) StringSliceVar(i *[]string, short, long string, opts *Option) {
|
||||||
|
p.typeVar(i, short, long, 1, false, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) IntSlice(short, long string, opts *Option) *[]int {
|
||||||
|
var result []int
|
||||||
|
|
||||||
|
p.typeVar(&result, short, long, 1, false, opts)
|
||||||
|
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
func (p *Parser) IntSliceVar(i *[]int, short, long string, opts *Option) {
|
||||||
|
p.typeVar(i, short, long, 1, false, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) FloatSlice(short, long string, opts *Option) *[]float64 {
|
||||||
|
var result []float64
|
||||||
|
|
||||||
|
p.typeVar(&result, short, long, 1, false, opts)
|
||||||
|
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
func (p *Parser) FloatSliceVar(i *[]float64, short, long string, opts *Option) {
|
||||||
|
p.typeVar(i, short, long, 1, false, opts)
|
||||||
}
|
}
|
||||||
|
285
argparse_test.go
285
argparse_test.go
@ -99,7 +99,7 @@ func TestParser_typeVar(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
p.typeVar(tt.args.i, tt.args.short, tt.args.long, tt.args.size, tt.args.unique)
|
p.typeVar(tt.args.i, tt.args.short, tt.args.long, tt.args.size, tt.args.unique, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ func TestParser_String(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
if got := p.String(tt.args.short, tt.args.long); got == nil {
|
if got := p.String(tt.args.short, tt.args.long, nil); got == nil {
|
||||||
t.Errorf("Parser.String() = %v", got)
|
t.Errorf("Parser.String() = %v", got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -316,7 +316,7 @@ func TestParser_StringVar(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
p.StringVar(tt.args.i, tt.args.short, tt.args.long)
|
p.StringVar(tt.args.i, tt.args.short, tt.args.long, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,7 +350,7 @@ func TestParser_Int(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
if got := p.Int(tt.args.short, tt.args.long); got == nil {
|
if got := p.Int(tt.args.short, tt.args.long, nil); got == nil {
|
||||||
t.Errorf("Parser.Int() = %v", got)
|
t.Errorf("Parser.Int() = %v", got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -389,7 +389,7 @@ func TestParser_IntVar(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
p.IntVar(tt.args.i, tt.args.short, tt.args.long)
|
p.IntVar(tt.args.i, tt.args.short, tt.args.long, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ func TestParser_Bool(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
if got := p.Bool(tt.args.short, tt.args.long); got == nil {
|
if got := p.Bool(tt.args.short, tt.args.long, nil); got == nil {
|
||||||
t.Errorf("Parser.Bool() = %v", got)
|
t.Errorf("Parser.Bool() = %v", got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -462,7 +462,7 @@ func TestParser_BoolVar(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
p.BoolVar(tt.args.i, tt.args.short, tt.args.long)
|
p.BoolVar(tt.args.i, tt.args.short, tt.args.long, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,7 +496,7 @@ func TestParser_Float(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
if got := p.Float(tt.args.short, tt.args.long); got == nil {
|
if got := p.Float(tt.args.short, tt.args.long, nil); got == nil {
|
||||||
t.Errorf("Parser.Float() = %v", got)
|
t.Errorf("Parser.Float() = %v", got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -535,7 +535,274 @@ func TestParser_FloatVar(t *testing.T) {
|
|||||||
args: tt.fields.args,
|
args: tt.fields.args,
|
||||||
parsed: tt.fields.parsed,
|
parsed: tt.fields.parsed,
|
||||||
}
|
}
|
||||||
p.FloatVar(tt.args.i, tt.args.short, tt.args.long)
|
p.FloatVar(tt.args.i, tt.args.short, tt.args.long, nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_StringSlice(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add string slice to parser",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
short: "d",
|
||||||
|
long: "",
|
||||||
|
opts: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
if got := p.StringSlice(tt.args.short, tt.args.long, tt.args.opts); got == nil {
|
||||||
|
t.Errorf("Parser.StringSlice() = %v", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_StringSliceVar(t *testing.T) {
|
||||||
|
var s []string
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
i *[]string
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add string slice to parser (ptr)",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
i: &s,
|
||||||
|
short: "d",
|
||||||
|
long: "",
|
||||||
|
opts: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
p.StringSliceVar(tt.args.i, tt.args.short, tt.args.long, tt.args.opts)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_IntSlice(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add int slice to parser",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
short: "i",
|
||||||
|
long: "",
|
||||||
|
opts: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
if got := p.IntSlice(tt.args.short, tt.args.long, tt.args.opts); got == nil {
|
||||||
|
t.Errorf("Parser.IntSlice() = %v", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_IntSliceVar(t *testing.T) {
|
||||||
|
var i []int
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
i *[]int
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add int slice to parser (ptr)",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
i: &i,
|
||||||
|
short: "i",
|
||||||
|
long: "",
|
||||||
|
opts: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
p.IntSliceVar(tt.args.i, tt.args.short, tt.args.long, tt.args.opts)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_FloatSliceVar(t *testing.T) {
|
||||||
|
var f []float64
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
i *[]float64
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add float slice to parser (ptr)",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
i: &f,
|
||||||
|
short: "f",
|
||||||
|
long: "",
|
||||||
|
opts: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
p.FloatSliceVar(tt.args.i, tt.args.short, tt.args.long, tt.args.opts)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_FloatSlice(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add float slice to parser",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
short: "f",
|
||||||
|
long: "",
|
||||||
|
opts: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
if got := p.FloatSlice(tt.args.short, tt.args.long, tt.args.opts); got == nil {
|
||||||
|
t.Errorf("Parser.FloatSlice() = %v", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParser_Help(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
args []*arg
|
||||||
|
showHelp bool
|
||||||
|
parsed bool
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
short string
|
||||||
|
long string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test add help flag to parser",
|
||||||
|
fields: fields{},
|
||||||
|
args: args{
|
||||||
|
short: "h",
|
||||||
|
long: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := &Parser{
|
||||||
|
args: tt.fields.args,
|
||||||
|
showHelp: tt.fields.showHelp,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
}
|
||||||
|
p.Help(tt.args.short, tt.args.long)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
74
argument.go
74
argument.go
@ -87,6 +87,27 @@ func (a *arg) name() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *arg) getType() string {
|
||||||
|
switch a.value.(type) {
|
||||||
|
case *string:
|
||||||
|
return "string"
|
||||||
|
case *int:
|
||||||
|
return "int"
|
||||||
|
case *bool:
|
||||||
|
return "bool"
|
||||||
|
case *float64:
|
||||||
|
return "float"
|
||||||
|
case *[]string:
|
||||||
|
return "[]string"
|
||||||
|
case *[]int:
|
||||||
|
return "[]int"
|
||||||
|
case *[]float64:
|
||||||
|
return "[]float"
|
||||||
|
default:
|
||||||
|
return "not support"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *arg) parse(args []string) error {
|
func (a *arg) parse(args []string) error {
|
||||||
if a.unique && a.parsed {
|
if a.unique && a.parsed {
|
||||||
return fmt.Errorf("[%s] can only parsent once\n", a.name())
|
return fmt.Errorf("[%s] can only parsent once\n", a.name())
|
||||||
@ -106,8 +127,11 @@ func (a *arg) parseType(args []string) error {
|
|||||||
case *float64:
|
case *float64:
|
||||||
return a.parseFloat(args)
|
return a.parseFloat(args)
|
||||||
case *[]string:
|
case *[]string:
|
||||||
|
return a.parseStringSlice(args)
|
||||||
case *[]int:
|
case *[]int:
|
||||||
|
return a.parseIntSlice(args)
|
||||||
case *[]float64:
|
case *[]float64:
|
||||||
|
return a.parseFloatSlice(args)
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unsupport type [%t]", a.value)
|
err = fmt.Errorf("unsupport type [%t]", a.value)
|
||||||
}
|
}
|
||||||
@ -130,6 +154,17 @@ func (a *arg) parseString(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *arg) parseStringSlice(args []string) (err error) {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return ErrNoArg
|
||||||
|
}
|
||||||
|
|
||||||
|
*((a.value).(*[]string)) = append(*((a.value).(*[]string)), args...)
|
||||||
|
a.parsed = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (a *arg) parseInt(args []string) error {
|
func (a *arg) parseInt(args []string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -144,12 +179,30 @@ func (a *arg) parseInt(args []string) error {
|
|||||||
*((a.value).(*int)) = i
|
*((a.value).(*int)) = i
|
||||||
a.parsed = true
|
a.parsed = true
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("[%s] bad int value", a.name())
|
return fmt.Errorf("[%s] bad int value (%v)", a.name(), args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *arg) parseIntSlice(args []string) (err error) {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return ErrNoArg
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range args {
|
||||||
|
if i, err := strconv.Atoi(v); err == nil {
|
||||||
|
*((a.value).(*[]int)) = append(*((a.value).(*[]int)), i)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("[%s] bad int value (%v)", a.name(), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.parsed = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (a *arg) parseBool(args []string) error {
|
func (a *arg) parseBool(args []string) error {
|
||||||
*a.value.(*bool) = true
|
*a.value.(*bool) = true
|
||||||
a.parsed = true
|
a.parsed = true
|
||||||
@ -168,7 +221,24 @@ func (a *arg) parseFloat(args []string) (err error) {
|
|||||||
*a.value.(*float64) = f
|
*a.value.(*float64) = f
|
||||||
a.parsed = true
|
a.parsed = true
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("[%s] bad float value", a.name())
|
return fmt.Errorf("[%s] bad float value (%v)", a.name(), args[0])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *arg) parseFloatSlice(args []string) (err error) {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return ErrNoArg
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range args {
|
||||||
|
if f, err := strconv.ParseFloat(v, 64); err == nil {
|
||||||
|
*((a.value).(*[]float64)) = append(*((a.value).(*[]float64)), f)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("[%s] bad float value (%v)", a.name(), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.parsed = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
217
argument_test.go
217
argument_test.go
@ -1,6 +1,8 @@
|
|||||||
package argparse
|
package argparse
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func Test_arg_check(t *testing.T) {
|
func Test_arg_check(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
@ -698,3 +700,216 @@ func Test_arg_parseFloat(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_arg_parseStringSlice(t *testing.T) {
|
||||||
|
var s []string
|
||||||
|
type fields struct {
|
||||||
|
sname string
|
||||||
|
lname string
|
||||||
|
size int
|
||||||
|
value interface{}
|
||||||
|
unique bool
|
||||||
|
parsed bool
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test argument parseStringSlice",
|
||||||
|
fields: fields{
|
||||||
|
size: 1,
|
||||||
|
value: &s,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
args: []string{
|
||||||
|
"a", "b", "c",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
a := &arg{
|
||||||
|
sname: tt.fields.sname,
|
||||||
|
lname: tt.fields.lname,
|
||||||
|
size: tt.fields.size,
|
||||||
|
value: tt.fields.value,
|
||||||
|
unique: tt.fields.unique,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
opts: tt.fields.opts,
|
||||||
|
}
|
||||||
|
if err := a.parseStringSlice(tt.args.args); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("arg.parseStringSlice() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_arg_parseIntSlice(t *testing.T) {
|
||||||
|
var i []int
|
||||||
|
type fields struct {
|
||||||
|
sname string
|
||||||
|
lname string
|
||||||
|
size int
|
||||||
|
value interface{}
|
||||||
|
unique bool
|
||||||
|
parsed bool
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test argument parseIntSlice",
|
||||||
|
fields: fields{
|
||||||
|
value: &i,
|
||||||
|
size: 1,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
args: []string{"1", "2", "3"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
a := &arg{
|
||||||
|
sname: tt.fields.sname,
|
||||||
|
lname: tt.fields.lname,
|
||||||
|
size: tt.fields.size,
|
||||||
|
value: tt.fields.value,
|
||||||
|
unique: tt.fields.unique,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
opts: tt.fields.opts,
|
||||||
|
}
|
||||||
|
if err := a.parseIntSlice(tt.args.args); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("arg.parseIntSlice() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_arg_parseFloatSlice(t *testing.T) {
|
||||||
|
var f []float64
|
||||||
|
type fields struct {
|
||||||
|
sname string
|
||||||
|
lname string
|
||||||
|
size int
|
||||||
|
value interface{}
|
||||||
|
unique bool
|
||||||
|
parsed bool
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test argument parseFloatSlice",
|
||||||
|
fields: fields{
|
||||||
|
value: &f,
|
||||||
|
size: 1,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
args: []string{"1.2", "2.3", "3.5"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
a := &arg{
|
||||||
|
sname: tt.fields.sname,
|
||||||
|
lname: tt.fields.lname,
|
||||||
|
size: tt.fields.size,
|
||||||
|
value: tt.fields.value,
|
||||||
|
unique: tt.fields.unique,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
opts: tt.fields.opts,
|
||||||
|
}
|
||||||
|
if err := a.parseFloatSlice(tt.args.args); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("arg.parseFloatSlice() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_arg_getType(t *testing.T) {
|
||||||
|
var s string
|
||||||
|
var b bool
|
||||||
|
var i int
|
||||||
|
var f float64
|
||||||
|
type fields struct {
|
||||||
|
sname string
|
||||||
|
lname string
|
||||||
|
size int
|
||||||
|
value interface{}
|
||||||
|
unique bool
|
||||||
|
parsed bool
|
||||||
|
opts *Option
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test get argument type 1",
|
||||||
|
fields: fields{value: &s},
|
||||||
|
want: "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test get argument type 2",
|
||||||
|
fields: fields{value: &b},
|
||||||
|
want: "bool",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test get argument type 3",
|
||||||
|
fields: fields{value: &i},
|
||||||
|
want: "int",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test get argument type 4",
|
||||||
|
fields: fields{value: &f},
|
||||||
|
want: "float",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
a := &arg{
|
||||||
|
sname: tt.fields.sname,
|
||||||
|
lname: tt.fields.lname,
|
||||||
|
size: tt.fields.size,
|
||||||
|
value: tt.fields.value,
|
||||||
|
unique: tt.fields.unique,
|
||||||
|
parsed: tt.fields.parsed,
|
||||||
|
opts: tt.fields.opts,
|
||||||
|
}
|
||||||
|
if got := a.getType(); got != tt.want {
|
||||||
|
t.Errorf("arg.getType() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"git.trj.tw/golang/argparse"
|
"git.trj.tw/golang/argparse"
|
||||||
)
|
)
|
||||||
@ -14,6 +15,9 @@ func main() {
|
|||||||
"--port", "3000",
|
"--port", "3000",
|
||||||
"--float", "1.23",
|
"--float", "1.23",
|
||||||
"-n", "name!!",
|
"-n", "name!!",
|
||||||
|
"-i", "item1",
|
||||||
|
"-i", "item2",
|
||||||
|
"-h",
|
||||||
}
|
}
|
||||||
|
|
||||||
p := argparse.New()
|
p := argparse.New()
|
||||||
@ -23,15 +27,33 @@ func main() {
|
|||||||
var port int
|
var port int
|
||||||
var floatVal float64
|
var floatVal float64
|
||||||
var name *string
|
var name *string
|
||||||
|
var sarr []string
|
||||||
|
var missReq int
|
||||||
|
_ = missReq
|
||||||
|
|
||||||
p.BoolVar(&versionFlag, "v", "version")
|
p.BoolVar(&versionFlag, "v", "version", nil)
|
||||||
p.StringVar(&configPath, "f", "config")
|
p.StringVar(&configPath, "f", "config", nil)
|
||||||
p.IntVar(&port, "p", "port")
|
p.IntVar(&port, "p", "port", nil)
|
||||||
p.FloatVar(&floatVal, "ff", "float")
|
p.FloatVar(&floatVal, "ff", "float", nil)
|
||||||
|
p.StringSliceVar(&sarr, "i", "item", nil)
|
||||||
|
// uncomment to test required arg missing
|
||||||
|
// p.IntVar(&missReq, "m", "miss", &argparse.Option{Require: true})
|
||||||
|
p.Help("h", "help")
|
||||||
|
|
||||||
name = p.String("n", "name")
|
name = p.String("n", "name", nil)
|
||||||
|
|
||||||
p.Parse(opts)
|
err := p.Parse(opts)
|
||||||
|
if err != nil {
|
||||||
fmt.Printf("Config: %s\nVersionFlag: %v\nPort: %d\nFloatVal: %f\nName: %s\n", configPath, versionFlag, port, floatVal, *name)
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(
|
||||||
|
"Config: %s\nVersionFlag: %v\nPort: %d\nFloatVal: %f\nName: %s\nItems: %v\n",
|
||||||
|
configPath,
|
||||||
|
versionFlag,
|
||||||
|
port,
|
||||||
|
floatVal,
|
||||||
|
*name,
|
||||||
|
sarr,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user