flags : better method separation
This commit is contained in:
parent
a243d3c125
commit
012110a369
2 changed files with 45 additions and 27 deletions
|
|
@ -12,8 +12,10 @@ const INTERNAL_ERR_PREFIX = "um internal err: ParseArgs"
|
||||||
|
|
||||||
// interface as func parameter
|
// interface as func parameter
|
||||||
type Flag interface {
|
type Flag interface {
|
||||||
SetValid(args []string, i int) (int, bool)
|
Set(string)
|
||||||
Match(arg string, i, j int) bool
|
Valid([]string, int) bool
|
||||||
|
MaybeIncrement(int) int
|
||||||
|
Match(string, int, int) bool
|
||||||
IsSet() bool
|
IsSet() bool
|
||||||
IsHelp() bool
|
IsHelp() bool
|
||||||
}
|
}
|
||||||
|
|
@ -37,9 +39,12 @@ type Bool struct {
|
||||||
Help string
|
Help string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Arg) SetValid(args []string, i int) (int, bool) {
|
func (f *Arg) Set(arg string) {
|
||||||
f.Val = args[i]
|
f.Val = arg
|
||||||
return i, true
|
}
|
||||||
|
|
||||||
|
func (f *Arg) Valid(args []string, i int) bool {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Arg) Match(arg string, i, j int) bool {
|
func (f *Arg) Match(arg string, i, j int) bool {
|
||||||
|
|
@ -54,10 +59,20 @@ func (f *Arg) IsHelp() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *String) SetValid(args []string, i int) (int, bool) {
|
func (f *Arg) MaybeIncrement(i int) int {
|
||||||
i, val, ok := validateIncrementFetch(args, i)
|
return i
|
||||||
f.Val = val
|
}
|
||||||
return i, ok
|
|
||||||
|
func (f *String) Set(arg string) {
|
||||||
|
f.Val = arg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *String) Valid(args []string, i int) bool {
|
||||||
|
return !missingValue(args, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *String) MaybeIncrement(i int) int {
|
||||||
|
return i + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *String) Match(arg string, _, _ int) bool {
|
func (f *String) Match(arg string, _, _ int) bool {
|
||||||
|
|
@ -72,15 +87,22 @@ func (f *String) IsHelp() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Bool) SetValid(_ []string, i int) (int, bool) {
|
func (f *Bool) Set(arg string) {
|
||||||
f.Val = true
|
f.Val = true
|
||||||
return i, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Bool) Match(arg string, _, _ int) bool {
|
func (f *Bool) Match(arg string, _, _ int) bool {
|
||||||
return arg == f.Long || arg == f.Short
|
return arg == f.Long || arg == f.Short
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Bool) Valid(args []string, i int) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Bool) MaybeIncrement(i int) int {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Bool) IsSet() bool {
|
func (f *Bool) IsSet() bool {
|
||||||
return f.Val
|
return f.Val
|
||||||
}
|
}
|
||||||
|
|
@ -98,16 +120,6 @@ func missingValue(args []string, i int) bool {
|
||||||
return i+1 == len(args) || hasDashPrefix(args[i+1])
|
return i+1 == len(args) || hasDashPrefix(args[i+1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. validate a Flag[string] by looking ahead in args, if missing, return false
|
|
||||||
// 2. increment the i to skip that value and return
|
|
||||||
// 3. fetch that value and return
|
|
||||||
func validateIncrementFetch(args []string, i int) (int, string, bool) {
|
|
||||||
if missingValue(args, i) {
|
|
||||||
return 0, "", false
|
|
||||||
}
|
|
||||||
return i + 1, args[i+1], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand incoming opts struct into a []Flag
|
// expand incoming opts struct into a []Flag
|
||||||
//
|
//
|
||||||
// WARN: incoming opts must be a pointer!
|
// WARN: incoming opts must be a pointer!
|
||||||
|
|
@ -130,11 +142,13 @@ func expandOpts(opts any) []Flag {
|
||||||
log.Fatalf("%s needs a struct: %s", INTERNAL_ERR_PREFIX, field.Kind())
|
log.Fatalf("%s needs a struct: %s", INTERNAL_ERR_PREFIX, field.Kind())
|
||||||
}
|
}
|
||||||
if !field.CanAddr() {
|
if !field.CanAddr() {
|
||||||
log.Fatalf("%s needs an addressable type: ", INTERNAL_ERR_PREFIX, field.Type())
|
log.Fatalf("%s needs an addressable type: %s", INTERNAL_ERR_PREFIX, field.Type())
|
||||||
}
|
}
|
||||||
// NOTE: Addr() gets the underlying address:
|
// NOTE: Addr() gets the underlying address:
|
||||||
if f, ok := field.Addr().Interface().(Flag); ok {
|
if f, ok := field.Addr().Interface().(Flag); ok {
|
||||||
flags = append(flags, f)
|
flags = append(flags, f)
|
||||||
|
} else {
|
||||||
|
log.Fatalf("%s needs a []Flag interface: %s", INTERNAL_ERR_PREFIX, field.Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flags
|
return flags
|
||||||
|
|
@ -151,12 +165,11 @@ argloop:
|
||||||
if f.IsHelp() {
|
if f.IsHelp() {
|
||||||
Help(sub, summary, opts)
|
Help(sub, summary, opts)
|
||||||
}
|
}
|
||||||
ok := false
|
if !f.Valid(args, i) {
|
||||||
i, ok = f.SetValid(args, i)
|
HelpMissingAssignment(sub, arg)
|
||||||
if !ok {
|
|
||||||
log.Printf("um %s: %s needs a value assignment\n", sub, args[i])
|
|
||||||
log.Fatal("try: um [cmd] --help")
|
|
||||||
}
|
}
|
||||||
|
i = f.MaybeIncrement(i)
|
||||||
|
f.Set(args[i])
|
||||||
continue argloop
|
continue argloop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,11 @@ func HelpInvalidArg(sub cmd.Subcommand, arg string) {
|
||||||
log.Printf("um %s: invalid argument: %s", sub, arg)
|
log.Printf("um %s: invalid argument: %s", sub, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HelpMissingAssignment(sub cmd.Subcommand, arg string) {
|
||||||
|
log.Printf("um %s: %s needs a value assignment\n", sub, arg)
|
||||||
|
log.Fatal("try: um [cmd] --help")
|
||||||
|
}
|
||||||
|
|
||||||
// print out help string by reflecting over fields of provided opts struct
|
// print out help string by reflecting over fields of provided opts struct
|
||||||
// and os.Exit(0)
|
// and os.Exit(0)
|
||||||
func Help(sub cmd.Subcommand, summary string, opts any) {
|
func Help(sub cmd.Subcommand, summary string, opts any) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue