60 lines
1.3 KiB
Go
60 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
// parseArgs parses the provided args using a flag.FlagSet that is
|
|
// dynamically build using reflection for the provided type. The type fields
|
|
// that have a "flag" tag are used to build the flags. The flag tag should
|
|
// include either a ('-'). Example usage:
|
|
//
|
|
// func main() {
|
|
// var flags struct {
|
|
// Modelfile string `flag:"f,path to the Modelfile"`
|
|
// }
|
|
//
|
|
// fs := readFlags(os.Args[1:], &flags)
|
|
// fs.Parse(os.Args[1:])
|
|
// }
|
|
func readFlags(name string, args []string, v any) *flag.FlagSet {
|
|
fs := flag.NewFlagSet(name, flag.ExitOnError)
|
|
defer fs.Parse(args)
|
|
if v == nil {
|
|
return fs
|
|
}
|
|
|
|
for i := 0; i < reflect.ValueOf(v).NumField(); i++ {
|
|
f := reflect.ValueOf(v).Field(i)
|
|
if !f.CanSet() {
|
|
continue
|
|
}
|
|
|
|
tag := f.Type().Field(i).Tag.Get("flag")
|
|
if tag == "" {
|
|
continue
|
|
}
|
|
var name, usage string
|
|
if i := strings.Index(tag, ","); i != -1 {
|
|
name = tag[:i]
|
|
usage = tag[i+1:]
|
|
} else {
|
|
name = tag
|
|
}
|
|
|
|
// TODO(bmizerany): add more types as needed
|
|
switch f.Kind() {
|
|
case reflect.String:
|
|
fs.StringVar(f.Addr().Interface().(*string), name, "", usage)
|
|
case reflect.Bool:
|
|
fs.BoolVar(f.Addr().Interface().(*bool), name, false, usage)
|
|
default:
|
|
panic(fmt.Sprintf("unsupported type %v", f.Kind()))
|
|
}
|
|
}
|
|
return fs
|
|
}
|