Skip to content

Commit 7a3fd89

Browse files
committed
refactor: gflag - rename struct FlagMeta to Option
- update args help build logic - update opts help build logic
1 parent 7322987 commit 7a3fd89

File tree

4 files changed

+88
-27
lines changed

4 files changed

+88
-27
lines changed

gflag/args.go

+30
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package gflag
22

33
import (
4+
"fmt"
45
"strings"
56

67
"github.com/gookit/gcli/v3/helper"
78
"github.com/gookit/goutil/errorx"
9+
"github.com/gookit/goutil/mathutil"
810
"github.com/gookit/goutil/structs"
911
"github.com/gookit/goutil/strutil"
1012
)
@@ -34,6 +36,8 @@ type Arguments struct {
3436
// "arg1": 1,
3537
// }
3638
argsIndexes map[string]int
39+
// arg name max width
40+
argWidth int
3741
// validate the args number is right
3842
validateNum bool
3943
// mark exists array argument
@@ -134,6 +138,7 @@ func (ags *Arguments) BindArg(arg *Argument) *Argument {
134138
// - The (array) argument of multiple values can only be defined at the end
135139
func (ags *Arguments) AddArgument(arg *Argument) *Argument {
136140
if ags.argsIndexes == nil {
141+
ags.argWidth = 12 // default width
137142
ags.argsIndexes = make(map[string]int)
138143
}
139144

@@ -154,6 +159,7 @@ func (ags *Arguments) AddArgument(arg *Argument) *Argument {
154159
// add argument index record
155160
arg.index = len(ags.args)
156161
ags.argsIndexes[name] = arg.index
162+
ags.argWidth = mathutil.MaxInt(ags.argWidth, len(name))
157163

158164
// add argument
159165
ags.args = append(ags.args, arg)
@@ -212,6 +218,30 @@ func (ags *Arguments) ArgByIndex(i int) *Argument {
212218
return ags.args[i]
213219
}
214220

221+
// String build args help string
222+
func (ags *Arguments) String() string {
223+
return ags.BuildArgsHelp()
224+
}
225+
226+
// BuildArgsHelp string
227+
func (ags *Arguments) BuildArgsHelp() string {
228+
if len(ags.args) < 1 {
229+
return ""
230+
}
231+
232+
var sb strings.Builder
233+
for _, arg := range ags.args {
234+
sb.WriteString(fmt.Sprintf(
235+
"<info>%s</> %s%s\n",
236+
strutil.PadRight(arg.HelpName(), " ", ags.argWidth),
237+
getRequiredMark(arg.Required),
238+
strutil.UpperFirst(arg.Desc),
239+
))
240+
}
241+
242+
return sb.String()
243+
}
244+
215245
/*************************************************************
216246
* Argument definition
217247
*************************************************************/

gflag/flags.go

+35-14
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type Flags struct {
3737
// all option names of the command. {name: length} // TODO delete, move len to meta.
3838
names map[string]int
3939
// metadata for all options
40-
metas map[string]*FlagMeta // TODO support option category
40+
metas map[string]*Option // TODO support option category
4141
// short names map for options. format: {short: name}
4242
// eg. {"n": "name", "o": "opt"}
4343
shorts map[string]string
@@ -556,7 +556,7 @@ func (fs *Flags) VarOpt(p flag.Value, name, shorts, desc string) {
556556
}
557557

558558
// binding option and shorts
559-
func (fs *Flags) varOpt(p flag.Value, meta *FlagMeta) {
559+
func (fs *Flags) varOpt(p flag.Value, meta *Option) {
560560
name := fs.checkFlagInfo(meta)
561561

562562
// binding option to flag.FlagSet
@@ -576,11 +576,11 @@ func (fs *Flags) Required(names ...string) {
576576
}
577577

578578
// check flag option name and short-names
579-
func (fs *Flags) checkFlagInfo(meta *FlagMeta) string {
579+
func (fs *Flags) checkFlagInfo(meta *Option) string {
580580
// NOTICE: must init some required fields
581581
if fs.names == nil {
582582
fs.names = map[string]int{}
583-
fs.metas = map[string]*FlagMeta{}
583+
fs.metas = map[string]*Option{}
584584
fs.InitFlagSet("flags-" + meta.Name)
585585
}
586586

@@ -652,6 +652,11 @@ func (fs *Flags) PrintHelpPanel() {
652652
color.Fprint(fs.out, fs.String())
653653
}
654654

655+
// String for all flag options
656+
func (fs *Flags) String() string {
657+
return fs.BuildHelp()
658+
}
659+
655660
// BuildHelp string for all flag options
656661
func (fs *Flags) BuildHelp() string {
657662
if fs.buf == nil {
@@ -660,18 +665,33 @@ func (fs *Flags) BuildHelp() string {
660665

661666
// repeat call the method
662667
if fs.buf.Len() < 1 {
663-
fs.FSet().VisitAll(fs.formatOneFlag)
668+
fs.buf.WriteString("Options:\n")
669+
fs.buf.WriteString(fs.BuildOptsHelp())
670+
fs.buf.WriteByte('\n')
671+
672+
if fs.HasArgs() {
673+
fs.buf.WriteString("Arguments:\n")
674+
fs.buf.WriteString(fs.BuildArgsHelp())
675+
fs.buf.WriteByte('\n')
676+
}
664677
}
665678

666679
return fs.buf.String()
667680
}
668681

669-
// String for all flag options
670-
func (fs *Flags) String() string {
671-
return fs.BuildHelp()
682+
// BuildOptsHelp string.
683+
func (fs *Flags) BuildOptsHelp() string {
684+
var sb strings.Builder
685+
686+
fs.FSet().VisitAll(func(f *flag.Flag) {
687+
sb.WriteString(fs.formatOneFlag(f))
688+
sb.WriteByte('\n')
689+
})
690+
691+
return sb.String()
672692
}
673693

674-
func (fs *Flags) formatOneFlag(f *flag.Flag) {
694+
func (fs *Flags) formatOneFlag(f *flag.Flag) (s string) {
675695
// Skip render:
676696
// - meta is not exists(Has ensured that it is not a short name)
677697
// - it is hidden flag option
@@ -681,7 +701,7 @@ func (fs *Flags) formatOneFlag(f *flag.Flag) {
681701
return
682702
}
683703

684-
var s, fullName string
704+
var fullName string
685705
name := f.Name
686706
// eg: "-V, --version" length is: 13
687707
nameLen := fs.names[name]
@@ -730,7 +750,7 @@ func (fs *Flags) formatOneFlag(f *flag.Flag) {
730750

731751
// flag is required
732752
if meta.Required {
733-
s += "<red>*</>"
753+
s = "<red>*</>" + s
734754
}
735755

736756
s += strings.Replace(strutil.UpperFirst(desc), "\n", nlIndent, -1)
@@ -744,9 +764,7 @@ func (fs *Flags) formatOneFlag(f *flag.Flag) {
744764
}
745765
}
746766

747-
// save to buffer
748-
fs.buf.WriteString(s)
749-
fs.buf.WriteByte('\n')
767+
return s
750768
}
751769

752770
/***********************************************************************
@@ -814,6 +832,9 @@ func (fs *Flags) FlagMeta(name string) *FlagMeta { return fs.metas[name] }
814832
// Metas get all flag metas
815833
func (fs *Flags) Metas() map[string]*FlagMeta { return fs.metas }
816834

835+
// Opts get all flag options
836+
func (fs *Flags) Opts() map[string]*Option { return fs.metas }
837+
817838
// Hidden there are given option names
818839
// func (gf *Flags) Hidden(names ...string) {
819840
// for _, name := range names {

gflag/opts.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ import (
1616
* flag options metadata
1717
***********************************************************************/
1818

19-
// FlagMeta for an flag(option/argument)
20-
type FlagMeta struct {
19+
// FlagMeta alias of flag Option
20+
type FlagMeta = Option
21+
22+
// Option define for a flag option
23+
type Option struct {
2124
// go flag value
2225
flag *flag.Flag
2326
// Name of flag and description
@@ -42,8 +45,8 @@ type FlagMeta struct {
4245
}
4346

4447
// newFlagMeta quick create an FlagMeta
45-
func newFlagMeta(name, desc string, defVal any, shortcut string) *FlagMeta {
46-
return &FlagMeta{
48+
func newFlagMeta(name, desc string, defVal any, shortcut string) *Option {
49+
return &Option{
4750
Name: name,
4851
Desc: desc,
4952
// other info
@@ -52,7 +55,7 @@ func newFlagMeta(name, desc string, defVal any, shortcut string) *FlagMeta {
5255
}
5356
}
5457

55-
func (m *FlagMeta) initCheck() string {
58+
func (m *Option) initCheck() string {
5659
if m.Desc != "" {
5760
desc := strings.Trim(m.Desc, "; ")
5861
if strings.ContainsRune(desc, ';') {
@@ -79,14 +82,14 @@ func (m *FlagMeta) initCheck() string {
7982
}
8083

8184
// good name of the flag
82-
func (m *FlagMeta) goodName() string {
85+
func (m *Option) goodName() string {
8386
name := strings.Trim(m.Name, "- ")
8487
if name == "" {
8588
helper.Panicf("option flag name cannot be empty")
8689
}
8790

8891
if !helper.IsGoodName(name) {
89-
helper.Panicf("option flag name '%s' is invalid", name)
92+
helper.Panicf("option flag name '%s' is invalid, must match: %s", name, helper.RegGoodName)
9093
}
9194

9295
// update self name
@@ -95,24 +98,24 @@ func (m *FlagMeta) goodName() string {
9598
}
9699

97100
// Shorts2String join shorts to a string
98-
func (m *FlagMeta) Shorts2String(sep ...string) string {
101+
func (m *Option) Shorts2String(sep ...string) string {
99102
if len(m.Shorts) == 0 {
100103
return ""
101104
}
102105
return strings.Join(m.Shorts, sepStr(sep))
103106
}
104107

105108
// HelpName for show help
106-
func (m *FlagMeta) HelpName() string {
109+
func (m *Option) HelpName() string {
107110
return cflag.AddPrefixes(m.Name, m.Shorts)
108111
}
109112

110-
func (m *FlagMeta) helpNameLen() int {
113+
func (m *Option) helpNameLen() int {
111114
return len(m.HelpName())
112115
}
113116

114117
// Validate the binding value
115-
func (m *FlagMeta) Validate(val string) error {
118+
func (m *Option) Validate(val string) error {
116119
if m.Required && val == "" {
117120
return fmt.Errorf("flag '%s' is required", m.Name)
118121
}
@@ -125,12 +128,12 @@ func (m *FlagMeta) Validate(val string) error {
125128
}
126129

127130
// Flag value
128-
func (m *FlagMeta) Flag() *flag.Flag {
131+
func (m *Option) Flag() *flag.Flag {
129132
return m.flag
130133
}
131134

132135
// DValue wrap the default value
133-
func (m *FlagMeta) DValue() *stdutil.Value {
136+
func (m *Option) DValue() *stdutil.Value {
134137
if m.defVal == nil {
135138
m.defVal = &stdutil.Value{V: m.DefVal}
136139
}

gflag/util.go

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ func sepStr(seps []string) string {
1616
return comdef.DefaultSep
1717
}
1818

19+
func getRequiredMark(must bool) string {
20+
if must {
21+
return "<red>*</>"
22+
}
23+
return ""
24+
}
25+
1926
// allowed keys on struct tag.
2027
var flagTagKeys = arrutil.Strings{"name", "shorts", "desc", "default", "required"}
2128

0 commit comments

Comments
 (0)