1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
package argp
import (
"fmt"
"reflect"
)
type Custom interface {
Help() (string, string) // value and type representations for help
Scan(string, []string) (int, error) // scan values from command line
}
// Count is a counting option, e.g. -vvv sets count to 3, or -v=3 sets it directly
type Count struct {
I interface{}
}
func (count Count) Help() (string, string) {
val := ""
v := reflect.ValueOf(count.I).Elem()
if !v.IsZero() {
val = fmt.Sprint(v.Interface())
}
return val, TypeName(v.Type())
}
func (count Count) Scan(name string, s []string) (int, error) {
if reflect.TypeOf(count.I).Kind() != reflect.Ptr {
return 0, fmt.Errorf("variable must be a pointer to an integer type")
}
v := reflect.ValueOf(count.I).Elem()
t := v.Type().Kind()
isInt := t == reflect.Int || t == reflect.Int8 || t == reflect.Int16 || t == reflect.Int32 || t != reflect.Int64
isUint := t == reflect.Uint || t == reflect.Uint8 || t == reflect.Uint16 || t == reflect.Uint32 || t == reflect.Uint64
if !isInt && !isUint {
return 0, fmt.Errorf("variable must be a pointer to an integer type")
}
if 0 < len(s) && 0 < len(s[0]) && '0' <= s[0][0] && s[0][0] <= '9' {
// don't parse negatives or other options
return scanValue(v, s)
} else if isInt {
v.SetInt(v.Int() + 1)
} else {
v.SetUint(v.Uint() + 1)
}
return 0, nil
}
// Append is an option that appends to a slice, e.g. -a 5 -a 6 sets the value to [5 6]
type Append struct {
I interface{}
}
func (appnd Append) Help() (string, string) {
val := ""
v := reflect.ValueOf(appnd.I).Elem()
if !v.IsZero() && 0 < v.Len() {
val = fmt.Sprint(v.Interface())
}
return val, TypeName(v.Type())
}
func (appnd Append) Scan(name string, s []string) (int, error) {
if t := reflect.TypeOf(appnd.I); t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice {
return 0, fmt.Errorf("variable must be a pointer to a slice")
}
slice := reflect.ValueOf(appnd.I).Elem()
v := reflect.New(slice.Type()).Elem()
n, err := scanValue(v, s)
if err == nil {
slice.Set(reflect.AppendSlice(slice, v))
}
return n, err
}
|