169 lines
2.8 KiB
Go
169 lines
2.8 KiB
Go
package argparse
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
type Parser struct {
|
|
args []*arg
|
|
parsed bool
|
|
}
|
|
|
|
type arg struct {
|
|
sname string
|
|
lname string
|
|
// value number count
|
|
size int
|
|
value interface{}
|
|
unique bool
|
|
parsed bool
|
|
}
|
|
|
|
func New() *Parser {
|
|
return &Parser{
|
|
args: make([]*arg, 0),
|
|
}
|
|
}
|
|
|
|
func (p *Parser) addArg(a *arg) error {
|
|
for _, v := range p.args {
|
|
if (v.sname == a.sname || v.lname == a.lname) && (a.unique || v.unique) {
|
|
return errors.New("option name dup")
|
|
}
|
|
}
|
|
p.args = append(p.args, a)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Parser) typeVar(i interface{}, short, long string, size int, unique bool) {
|
|
t := reflect.ValueOf(i)
|
|
if t.Kind() != reflect.Ptr {
|
|
panic(errors.New("var type not ptr"))
|
|
}
|
|
|
|
a := &arg{
|
|
sname: short,
|
|
lname: long,
|
|
value: i,
|
|
size: size,
|
|
unique: unique,
|
|
}
|
|
|
|
if err := p.addArg(a); err != nil {
|
|
panic(fmt.Errorf("unable to add String: %s\n", err))
|
|
}
|
|
}
|
|
|
|
func (p *Parser) Parse(a []string) error {
|
|
copyArg := make([]string, len(a))
|
|
copy(copyArg, a)
|
|
|
|
err := p.parse(©Arg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// in loop func
|
|
func (p *Parser) parse(args *[]string) error {
|
|
if p.parsed {
|
|
return nil
|
|
}
|
|
if len(*args) < 1 {
|
|
return nil
|
|
}
|
|
|
|
err := p.parseArguemtns(args)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
p.parsed = true
|
|
return nil
|
|
}
|
|
|
|
func (p *Parser) parseArguemtns(args *[]string) error {
|
|
n := len(p.args)
|
|
|
|
for i := 0; i < n; i++ {
|
|
nn := len(*args)
|
|
oarg := p.args[i]
|
|
|
|
for j := 0; j < nn; j++ {
|
|
s := (*args)[j]
|
|
if s == "" {
|
|
continue
|
|
}
|
|
ct, err := oarg.check(s)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if ct > 0 {
|
|
valpos := j + 1
|
|
if len(*args) < valpos+oarg.size {
|
|
return fmt.Errorf("no enough arguments for %s", oarg.name())
|
|
}
|
|
err := oarg.parse((*args)[valpos : valpos+oarg.size])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
oarg.reduce(j, args)
|
|
continue
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Parser) String(short, long string) *string {
|
|
var result string
|
|
|
|
p.typeVar(&result, short, long, 1, true)
|
|
|
|
return &result
|
|
}
|
|
func (p *Parser) StringVar(i *string, short, long string) {
|
|
p.typeVar(i, short, long, 1, true)
|
|
}
|
|
|
|
func (p *Parser) Int(short, long string) *int {
|
|
var result int
|
|
|
|
p.typeVar(&result, short, long, 1, true)
|
|
|
|
return &result
|
|
}
|
|
func (p *Parser) IntVar(i *int, short, long string) {
|
|
p.typeVar(i, short, long, 1, true)
|
|
}
|
|
|
|
func (p *Parser) Bool(short, long string) *bool {
|
|
var result bool
|
|
|
|
p.typeVar(&result, short, long, 0, true)
|
|
|
|
return &result
|
|
}
|
|
func (p *Parser) BoolVar(i *bool, short, long string) {
|
|
p.typeVar(i, short, long, 0, true)
|
|
}
|
|
|
|
func (p *Parser) Float(short, long string) *float64 {
|
|
var result float64
|
|
|
|
p.typeVar(&result, short, long, 1, true)
|
|
|
|
return &result
|
|
}
|
|
func (p *Parser) FloatVar(i *float64, short, long string) {
|
|
p.typeVar(i, short, long, 1, true)
|
|
}
|