flags : Help string using reflection iteration over fields

This commit is contained in:
bth 2026-01-18 14:48:58 -08:00
commit 0422b4a146
3 changed files with 43 additions and 13 deletions

View file

@ -2,6 +2,7 @@ package flags
import ( import (
"fmt" "fmt"
"reflect"
"strings" "strings"
) )
@ -34,3 +35,23 @@ func MissingValueArg(args []string, i int) bool {
func HelpMissingVal(flag string) { func HelpMissingVal(flag string) {
fmt.Printf("%s needs a value assignment\n", flag) fmt.Printf("%s needs a value assignment\n", flag)
} }
// print out help string by reflecting over fields of provided opts struct
func Help(subcmd string, opts any) {
v := reflect.ValueOf(opts)
t := v.Type()
fmt.Printf("um %s usage:\n", subcmd)
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
switch value.Interface().(type) {
case Arg:
fmt.Printf("%-12v string\t: %v\n", "["+strings.ToLower(field.Name)+"]", value.FieldByName("Help"))
case Flag[string]:
fmt.Printf("%-12v | %v string\t: %v\n", value.FieldByName("Long"), value.FieldByName("Short"), value.FieldByName("Help"))
case Flag[bool]:
fmt.Printf("%-12v | %v bool\t: %v\n", value.FieldByName("Long"), value.FieldByName("Short"), value.FieldByName("Help"))
}
}
}

View file

@ -8,14 +8,16 @@ import (
) )
type options struct { type options struct {
descriptor flags.Arg Descriptor flags.Arg
tags flags.Arg Tags flags.Arg
Help flags.Flag[bool]
} }
func InitOpts() options { func InitOpts() options {
return options{ return options{
flags.Arg{"", "midfix file descriptor"}, flags.Arg{"", "midfix file descriptor"},
flags.Arg{"", "tags to add to new file"}, flags.Arg{"", "tags to add to new file"},
flags.Flag[bool]{"--help", "-h", false, "show help"},
} }
} }
@ -24,12 +26,15 @@ func ParseArgs(args []string) options {
for i, arg := range args { for i, arg := range args {
switch { switch {
case i == 0 && !flags.HasDashPrefix(arg): case i == 0 && !flags.HasDashPrefix(arg):
opts.descriptor.Val = arg opts.Descriptor.Val = arg
case i == 1 && !flags.HasDashPrefix(arg): case i == 1 && !flags.HasDashPrefix(arg):
opts.tags.Val = arg opts.Tags.Val = arg
case i >= 2: case i >= 2:
fmt.Println("um next : too many args") fmt.Println("um next : too many args")
os.Exit(1) os.Exit(1)
case arg == opts.Help.Long || arg == opts.Help.Short:
flags.Help("next", opts)
return opts
} }
} }
return opts return opts

View file

@ -7,9 +7,10 @@ import (
) )
type options struct { type options struct {
query flags.Arg Query flags.Arg
date flags.Flag[string] Date flags.Flag[string]
invert flags.Flag[bool] Invert flags.Flag[bool]
Help flags.Flag[bool]
} }
func InitOpts() options { func InitOpts() options {
@ -17,6 +18,7 @@ func InitOpts() options {
flags.Arg{"", "tag query"}, flags.Arg{"", "tag query"},
flags.Flag[string]{"--date", "-d", "", "date range"}, flags.Flag[string]{"--date", "-d", "", "date range"},
flags.Flag[bool]{"--invert", "-i", false, "invert match"}, flags.Flag[bool]{"--invert", "-i", false, "invert match"},
flags.Flag[bool]{"--help", "-h", false, "show help"},
} }
} }
@ -26,25 +28,27 @@ func ParseArgs(args []string) options {
return opts return opts
} }
if !flags.HasDashPrefix(args[0]) { if !flags.HasDashPrefix(args[0]) {
opts.query.Val = args[0] opts.Query.Val = args[0]
} }
for i, arg := range args { for i, arg := range args {
switch arg { switch arg {
case opts.invert.Long, opts.invert.Short: case opts.Invert.Long, opts.Invert.Short:
opts.invert.Val = true opts.Invert.Val = true
case opts.date.Long, opts.date.Short: case opts.Date.Long, opts.Date.Short:
if flags.MissingValueArg(args, i) { if flags.MissingValueArg(args, i) {
flags.HelpMissingVal(arg) flags.HelpMissingVal(arg)
break break
} }
opts.date.Val = args[i+1] opts.Date.Val = args[i+1]
case opts.Help.Long, opts.Help.Short:
flags.Help("tag", opts)
return opts
} }
} }
return opts return opts
} }
func Tag(args []string) { func Tag(args []string) {
fmt.Printf("args: %#v\n", args)
opts := ParseArgs(args) opts := ParseArgs(args)
fmt.Println(opts) fmt.Println(opts)
} }