55 "flag"
66 "io"
77 "os"
8+ "strconv"
89 "strings"
910)
1011
@@ -17,6 +18,15 @@ type Group struct {
1718 Title string
1819}
1920
21+ // flagMeta stores metadata about a flag that has both long and short forms.
22+ type flagMeta struct {
23+ longName string
24+ shortName string
25+ usage string
26+ value flag.Value // the underlying flag.Value
27+ defValue string // default value as string
28+ }
29+
2030// Command represents a CLI command with subcommands, flags, and an action.
2131type Command struct {
2232 // Use is the one-line usage message. Recommended syntax: "cmd [flags] [arg...]"
@@ -102,6 +112,9 @@ type Command struct {
102112 // NEW fields for flag parsing results
103113 parsedFlags * flag.FlagSet // combined set used for parsing
104114 leftoverArgs []string // arguments after flag parsing
115+
116+ // flagMetaMap maps each flag name (both long and short) to its metadata.
117+ flagMetaMap map [string ]* flagMeta
105118}
106119
107120// NewCommand creates a new command with the given name and description.
@@ -114,6 +127,7 @@ func NewCommand(use, short, long string) *Command {
114127 inReader : os .Stdin ,
115128 outWriter : os .Stdout ,
116129 errWriter : os .Stderr ,
130+ flagMetaMap : make (map [string ]* flagMeta ),
117131 }
118132 cmd .localFlags = flag .NewFlagSet (use , flag .ContinueOnError )
119133 cmd .persistentFlags = flag .NewFlagSet (use , flag .ContinueOnError )
@@ -232,3 +246,71 @@ func (c *Command) persistentFlagSets() []*flag.FlagSet {
232246 }
233247 return sets
234248}
249+
250+ // ---------- Combined Flag Methods ----------
251+
252+ // IntVarP defines an integer flag with both long and short names.
253+ // It sets the variable p to the value given on the command line.
254+ func (c * Command ) IntVarP (p * int , long , short string , value int , usage string ) {
255+ // Register long flag (visible)
256+ c .localFlags .IntVar (p , long , value , usage )
257+ // Register short flag (hidden by skipping in help)
258+ c .localFlags .IntVar (p , short , value , usage )
259+ // Store metadata for help merging
260+ meta := & flagMeta {
261+ longName : long ,
262+ shortName : short ,
263+ usage : usage ,
264+ value : c .localFlags .Lookup (long ).Value ,
265+ defValue : flagValueToString (value ),
266+ }
267+ c .flagMetaMap [long ] = meta
268+ c .flagMetaMap [short ] = meta
269+ }
270+
271+ // StringVarP defines a string flag with both long and short names.
272+ func (c * Command ) StringVarP (p * string , long , short string , value string , usage string ) {
273+ c .localFlags .StringVar (p , long , value , usage )
274+ c .localFlags .StringVar (p , short , value , usage )
275+ meta := & flagMeta {
276+ longName : long ,
277+ shortName : short ,
278+ usage : usage ,
279+ value : c .localFlags .Lookup (long ).Value ,
280+ defValue : value ,
281+ }
282+ c .flagMetaMap [long ] = meta
283+ c .flagMetaMap [short ] = meta
284+ }
285+
286+ // BoolVarP defines a boolean flag with both long and short names.
287+ func (c * Command ) BoolVarP (p * bool , long , short string , value bool , usage string ) {
288+ c .localFlags .BoolVar (p , long , value , usage )
289+ c .localFlags .BoolVar (p , short , value , usage )
290+ meta := & flagMeta {
291+ longName : long ,
292+ shortName : short ,
293+ usage : usage ,
294+ value : c .localFlags .Lookup (long ).Value ,
295+ defValue : flagValueToString (value ),
296+ }
297+ c .flagMetaMap [long ] = meta
298+ c .flagMetaMap [short ] = meta
299+ }
300+
301+ // helper to convert a flag's default value to a string representation
302+ func flagValueToString (v interface {}) string {
303+ switch val := v .(type ) {
304+ case int :
305+ return strconv .Itoa (val )
306+ case bool :
307+ if val {
308+ return "true"
309+ }
310+ return "false"
311+ case string :
312+ return val
313+ default :
314+ return ""
315+ }
316+ }
0 commit comments