From 0422b4a1469e708197a280a8cb071a921af19bcf Mon Sep 17 00:00:00 2001 From: bth Date: Sun, 18 Jan 2026 14:48:58 -0800 Subject: [PATCH] flags : Help string using reflection iteration over fields --- flags/flags.go | 21 +++++++++++++++++++++ next/next.go | 13 +++++++++---- tag/tag.go | 22 +++++++++++++--------- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/flags/flags.go b/flags/flags.go index 8bc1846..466fd71 100644 --- a/flags/flags.go +++ b/flags/flags.go @@ -2,6 +2,7 @@ package flags import ( "fmt" + "reflect" "strings" ) @@ -34,3 +35,23 @@ func MissingValueArg(args []string, i int) bool { func HelpMissingVal(flag string) { 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")) + } + } +} diff --git a/next/next.go b/next/next.go index 1e27154..f2e6c89 100644 --- a/next/next.go +++ b/next/next.go @@ -8,14 +8,16 @@ import ( ) type options struct { - descriptor flags.Arg - tags flags.Arg + Descriptor flags.Arg + Tags flags.Arg + Help flags.Flag[bool] } func InitOpts() options { return options{ flags.Arg{"", "midfix file descriptor"}, 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 { switch { case i == 0 && !flags.HasDashPrefix(arg): - opts.descriptor.Val = arg + opts.Descriptor.Val = arg case i == 1 && !flags.HasDashPrefix(arg): - opts.tags.Val = arg + opts.Tags.Val = arg case i >= 2: fmt.Println("um next : too many args") os.Exit(1) + case arg == opts.Help.Long || arg == opts.Help.Short: + flags.Help("next", opts) + return opts } } return opts diff --git a/tag/tag.go b/tag/tag.go index db7413f..8ae9e78 100644 --- a/tag/tag.go +++ b/tag/tag.go @@ -7,9 +7,10 @@ import ( ) type options struct { - query flags.Arg - date flags.Flag[string] - invert flags.Flag[bool] + Query flags.Arg + Date flags.Flag[string] + Invert flags.Flag[bool] + Help flags.Flag[bool] } func InitOpts() options { @@ -17,6 +18,7 @@ func InitOpts() options { flags.Arg{"", "tag query"}, flags.Flag[string]{"--date", "-d", "", "date range"}, 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 } if !flags.HasDashPrefix(args[0]) { - opts.query.Val = args[0] + opts.Query.Val = args[0] } for i, arg := range args { switch arg { - case opts.invert.Long, opts.invert.Short: - opts.invert.Val = true - case opts.date.Long, opts.date.Short: + case opts.Invert.Long, opts.Invert.Short: + opts.Invert.Val = true + case opts.Date.Long, opts.Date.Short: if flags.MissingValueArg(args, i) { flags.HelpMissingVal(arg) 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 } func Tag(args []string) { - fmt.Printf("args: %#v\n", args) opts := ParseArgs(args) fmt.Println(opts) }