Skip to content

Commit

Permalink
refactor: gflag - rename struct FlagMeta to Option
Browse files Browse the repository at this point in the history
- update args help build logic
- update opts help build logic
  • Loading branch information
inhere committed Sep 26, 2022
1 parent 7322987 commit 7a3fd89
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 27 deletions.
30 changes: 30 additions & 0 deletions gflag/args.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package gflag

import (
"fmt"
"strings"

"github.com/gookit/gcli/v3/helper"
"github.com/gookit/goutil/errorx"
"github.com/gookit/goutil/mathutil"
"github.com/gookit/goutil/structs"
"github.com/gookit/goutil/strutil"
)
Expand Down Expand Up @@ -34,6 +36,8 @@ type Arguments struct {
// "arg1": 1,
// }
argsIndexes map[string]int
// arg name max width
argWidth int
// validate the args number is right
validateNum bool
// mark exists array argument
Expand Down Expand Up @@ -134,6 +138,7 @@ func (ags *Arguments) BindArg(arg *Argument) *Argument {
// - The (array) argument of multiple values can only be defined at the end
func (ags *Arguments) AddArgument(arg *Argument) *Argument {
if ags.argsIndexes == nil {
ags.argWidth = 12 // default width
ags.argsIndexes = make(map[string]int)
}

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

// add argument
ags.args = append(ags.args, arg)
Expand Down Expand Up @@ -212,6 +218,30 @@ func (ags *Arguments) ArgByIndex(i int) *Argument {
return ags.args[i]
}

// String build args help string
func (ags *Arguments) String() string {
return ags.BuildArgsHelp()
}

// BuildArgsHelp string
func (ags *Arguments) BuildArgsHelp() string {
if len(ags.args) < 1 {
return ""
}

var sb strings.Builder
for _, arg := range ags.args {
sb.WriteString(fmt.Sprintf(
"<info>%s</> %s%s\n",
strutil.PadRight(arg.HelpName(), " ", ags.argWidth),
getRequiredMark(arg.Required),
strutil.UpperFirst(arg.Desc),
))
}

return sb.String()
}

/*************************************************************
* Argument definition
*************************************************************/
Expand Down
49 changes: 35 additions & 14 deletions gflag/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Flags struct {
// all option names of the command. {name: length} // TODO delete, move len to meta.
names map[string]int
// metadata for all options
metas map[string]*FlagMeta // TODO support option category
metas map[string]*Option // TODO support option category
// short names map for options. format: {short: name}
// eg. {"n": "name", "o": "opt"}
shorts map[string]string
Expand Down Expand Up @@ -556,7 +556,7 @@ func (fs *Flags) VarOpt(p flag.Value, name, shorts, desc string) {
}

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

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

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

Expand Down Expand Up @@ -652,6 +652,11 @@ func (fs *Flags) PrintHelpPanel() {
color.Fprint(fs.out, fs.String())
}

// String for all flag options
func (fs *Flags) String() string {
return fs.BuildHelp()
}

// BuildHelp string for all flag options
func (fs *Flags) BuildHelp() string {
if fs.buf == nil {
Expand All @@ -660,18 +665,33 @@ func (fs *Flags) BuildHelp() string {

// repeat call the method
if fs.buf.Len() < 1 {
fs.FSet().VisitAll(fs.formatOneFlag)
fs.buf.WriteString("Options:\n")
fs.buf.WriteString(fs.BuildOptsHelp())
fs.buf.WriteByte('\n')

if fs.HasArgs() {
fs.buf.WriteString("Arguments:\n")
fs.buf.WriteString(fs.BuildArgsHelp())
fs.buf.WriteByte('\n')
}
}

return fs.buf.String()
}

// String for all flag options
func (fs *Flags) String() string {
return fs.BuildHelp()
// BuildOptsHelp string.
func (fs *Flags) BuildOptsHelp() string {
var sb strings.Builder

fs.FSet().VisitAll(func(f *flag.Flag) {
sb.WriteString(fs.formatOneFlag(f))
sb.WriteByte('\n')
})

return sb.String()
}

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

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

// flag is required
if meta.Required {
s += "<red>*</>"
s = "<red>*</>" + s
}

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

// save to buffer
fs.buf.WriteString(s)
fs.buf.WriteByte('\n')
return s
}

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

// Opts get all flag options
func (fs *Flags) Opts() map[string]*Option { return fs.metas }

// Hidden there are given option names
// func (gf *Flags) Hidden(names ...string) {
// for _, name := range names {
Expand Down
29 changes: 16 additions & 13 deletions gflag/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import (
* flag options metadata
***********************************************************************/

// FlagMeta for an flag(option/argument)
type FlagMeta struct {
// FlagMeta alias of flag Option
type FlagMeta = Option

// Option define for a flag option
type Option struct {
// go flag value
flag *flag.Flag
// Name of flag and description
Expand All @@ -42,8 +45,8 @@ type FlagMeta struct {
}

// newFlagMeta quick create an FlagMeta
func newFlagMeta(name, desc string, defVal any, shortcut string) *FlagMeta {
return &FlagMeta{
func newFlagMeta(name, desc string, defVal any, shortcut string) *Option {
return &Option{
Name: name,
Desc: desc,
// other info
Expand All @@ -52,7 +55,7 @@ func newFlagMeta(name, desc string, defVal any, shortcut string) *FlagMeta {
}
}

func (m *FlagMeta) initCheck() string {
func (m *Option) initCheck() string {
if m.Desc != "" {
desc := strings.Trim(m.Desc, "; ")
if strings.ContainsRune(desc, ';') {
Expand All @@ -79,14 +82,14 @@ func (m *FlagMeta) initCheck() string {
}

// good name of the flag
func (m *FlagMeta) goodName() string {
func (m *Option) goodName() string {
name := strings.Trim(m.Name, "- ")
if name == "" {
helper.Panicf("option flag name cannot be empty")
}

if !helper.IsGoodName(name) {
helper.Panicf("option flag name '%s' is invalid", name)
helper.Panicf("option flag name '%s' is invalid, must match: %s", name, helper.RegGoodName)
}

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

// Shorts2String join shorts to a string
func (m *FlagMeta) Shorts2String(sep ...string) string {
func (m *Option) Shorts2String(sep ...string) string {
if len(m.Shorts) == 0 {
return ""
}
return strings.Join(m.Shorts, sepStr(sep))
}

// HelpName for show help
func (m *FlagMeta) HelpName() string {
func (m *Option) HelpName() string {
return cflag.AddPrefixes(m.Name, m.Shorts)
}

func (m *FlagMeta) helpNameLen() int {
func (m *Option) helpNameLen() int {
return len(m.HelpName())
}

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

// Flag value
func (m *FlagMeta) Flag() *flag.Flag {
func (m *Option) Flag() *flag.Flag {
return m.flag
}

// DValue wrap the default value
func (m *FlagMeta) DValue() *stdutil.Value {
func (m *Option) DValue() *stdutil.Value {
if m.defVal == nil {
m.defVal = &stdutil.Value{V: m.DefVal}
}
Expand Down
7 changes: 7 additions & 0 deletions gflag/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ func sepStr(seps []string) string {
return comdef.DefaultSep
}

func getRequiredMark(must bool) string {
if must {
return "<red>*</>"
}
return ""
}

// allowed keys on struct tag.
var flagTagKeys = arrutil.Strings{"name", "shorts", "desc", "default", "required"}

Expand Down

0 comments on commit 7a3fd89

Please sign in to comment.