argparse/argparse.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(&copyArg)
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)
}