argparse/argument.go
Jay b619f2f11e
Some checks failed
continuous-integration/drone/push Build is failing
add new slice type parser, add help flag
2020-02-12 14:55:03 +00:00

245 lines
4.3 KiB
Go

package argparse
import (
"errors"
"fmt"
"strconv"
"strings"
)
var (
ErrArgTooMany = errors.New("arg too manu")
ErrNoArg = errors.New("no arg")
)
func (a *arg) check(s string) (count int, err error) {
res := a.checkLongName(s)
if res > 0 {
return res, nil
}
return a.checkShortName(s)
}
func (a *arg) checkLongName(s string) int {
if a.lname != "" {
if len(s) > 2 && strings.HasPrefix(s, "--") && s[2] != '-' {
if s[2:] == a.lname {
return 1
}
}
}
return 0
}
func (a *arg) checkShortName(s string) (int, error) {
if a.sname != "" {
if len(s) > 1 && strings.HasPrefix(s, "-") && s[1] != '-' {
if s[1:] == a.sname {
return 1, nil
}
}
}
return 0, nil
}
func (a *arg) reduce(pos int, args *[]string) {
a.reduceLongName(pos, args)
a.reduceShortName(pos, args)
}
func (a *arg) reduceLongName(pos int, args *[]string) {
s := (*args)[pos]
if a.lname == "" {
return
}
if res := a.checkLongName(s); res == 0 {
return
}
for i := pos; i <= pos+a.size; i++ {
(*args)[i] = ""
}
}
func (a *arg) reduceShortName(pos int, args *[]string) {
s := (*args)[pos]
if a.sname == "" {
return
}
if res, err := a.checkShortName(s); res == 0 || err != nil {
return
}
for i := pos; i <= pos+a.size; i++ {
(*args)[i] = ""
}
}
func (a *arg) name() string {
if a.sname == "" {
return fmt.Sprintf("--%s", a.lname)
} else if a.lname == "" {
return fmt.Sprintf("-%s", a.sname)
} else {
return fmt.Sprintf("-%s | --%s", a.sname, a.lname)
}
}
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 {
if a.unique && a.parsed {
return fmt.Errorf("[%s] can only parsent once\n", a.name())
}
return a.parseType(args)
}
func (a *arg) parseType(args []string) error {
var err error
switch a.value.(type) {
case *string:
return a.parseString(args)
case *int:
return a.parseInt(args)
case *bool:
return a.parseBool(args)
case *float64:
return a.parseFloat(args)
case *[]string:
return a.parseStringSlice(args)
case *[]int:
return a.parseIntSlice(args)
case *[]float64:
return a.parseFloatSlice(args)
default:
err = fmt.Errorf("unsupport type [%t]", a.value)
}
return err
}
func (a *arg) parseString(args []string) error {
var err error
if len(args) > 1 {
return ErrArgTooMany
}
if len(args) == 0 {
return ErrNoArg
}
*((a.value).(*string)) = args[0]
a.parsed = true
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 {
var err error
if len(args) > 1 {
return ErrArgTooMany
}
if len(args) == 0 {
return ErrNoArg
}
if i, err := strconv.Atoi(args[0]); err == nil {
*((a.value).(*int)) = i
a.parsed = true
} else {
return fmt.Errorf("[%s] bad int value (%v)", a.name(), args[0])
}
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 {
*a.value.(*bool) = true
a.parsed = true
return nil
}
func (a *arg) parseFloat(args []string) (err error) {
if len(args) > 1 {
return ErrArgTooMany
}
if len(args) == 0 {
return ErrNoArg
}
if f, err := strconv.ParseFloat(args[0], 64); err == nil {
*a.value.(*float64) = f
a.parsed = true
} else {
return fmt.Errorf("[%s] bad float value (%v)", a.name(), args[0])
}
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
}