From 46a6f8d48e642a2f2d5015c401c3fa56cb6028d9 Mon Sep 17 00:00:00 2001 From: Evan Fiordeliso Date: Fri, 10 Nov 2023 15:11:50 -0500 Subject: [PATCH] Better flags help lines --- cmd/test.go | 7 +++++++ flags/bool.go | 2 +- flags/flag.go | 26 ++++++++++++++++++++++++++ flags/float.go | 2 +- flags/int.go | 2 +- flags/set.go | 10 ++++++++++ flags/string.go | 3 +-- help.go | 7 +++++-- option.go | 6 +++--- 9 files changed, 55 insertions(+), 10 deletions(-) diff --git a/cmd/test.go b/cmd/test.go index 1805b2b..34fb99e 100644 --- a/cmd/test.go +++ b/cmd/test.go @@ -5,8 +5,14 @@ import ( "os" "go.fifitido.net/cmd" + "go.fifitido.net/cmd/flags" ) +var stringFlag = flags.String("string", "s", "", "example string flag") +var intFlag = flags.Int("int", "i", 0, "example int flag") +var boolFlag = flags.Bool("bool", "b", false, "example bool flag") +var floatFlag = flags.Float("float", "f", 0, "example float flag") + var root = cmd.NewRoot( cmd.WithShortDescription("Example command"), cmd.WithLongDescription(`An example command to show how to use go.fifitido.net/cmd @@ -15,6 +21,7 @@ this example is just a simple hello world program to show the basics of the library.`), cmd.WithSubcommand(subcmd), cmd.WithArgument("name", false), + cmd.WithFlags(stringFlag, intFlag, boolFlag, floatFlag), cmd.WithRunFunc(func(args []string) { if len(args) == 0 { fmt.Println("Hello World!") diff --git a/flags/bool.go b/flags/bool.go index 7b6ab3d..fb5f45e 100644 --- a/flags/bool.go +++ b/flags/bool.go @@ -11,7 +11,7 @@ type BoolFlag struct { var _ Flag = (*StringFlag)(nil) -func NewBoolFlag(name, shortName string, defaultValue bool, description string) *BoolFlag { +func Bool(name, shortName string, defaultValue bool, description string) *BoolFlag { return &BoolFlag{ name: name, shortName: shortName, diff --git a/flags/flag.go b/flags/flag.go index 9e284c2..3661bd6 100644 --- a/flags/flag.go +++ b/flags/flag.go @@ -1,8 +1,34 @@ package flags +import "fmt" + type Flag interface { Name() string ShortName() string Description() string Parse(raw string) error } + +func Names(f Flag) string { + names := "" + if f.ShortName() != "" { + names += fmt.Sprintf("-%s, ", f.ShortName()) + } + names += fmt.Sprintf("--%s", f.Name()) + return names +} + +func HelpLine(f Flag, paddedWidth int) string { + argNames := "" + if f.ShortName() != "" { + argNames += fmt.Sprintf("-%s, ", f.ShortName()) + } + argNames += fmt.Sprintf("--%s", f.Name()) + + spaceSize := paddedWidth - len(argNames) + if spaceSize > 0 { + argNames += fmt.Sprintf("%*s", spaceSize, "") + } + + return argNames + " " + f.Description() +} diff --git a/flags/float.go b/flags/float.go index e4dff45..d7d7c83 100644 --- a/flags/float.go +++ b/flags/float.go @@ -11,7 +11,7 @@ type FloatFlag struct { var _ Flag = (*FloatFlag)(nil) -func NewFloatFlag(name, shortName string, defaultValue float64, description string) *FloatFlag { +func Float(name, shortName string, defaultValue float64, description string) *FloatFlag { return &FloatFlag{ name: name, shortName: shortName, diff --git a/flags/int.go b/flags/int.go index 97ba5bf..63dfb12 100644 --- a/flags/int.go +++ b/flags/int.go @@ -11,7 +11,7 @@ type IntFlag struct { var _ Flag = (*StringFlag)(nil) -func NewIntFlag(name, shortName string, defaultValue int, description string) *IntFlag { +func Int(name, shortName string, defaultValue int, description string) *IntFlag { return &IntFlag{ name: name, shortName: shortName, diff --git a/flags/set.go b/flags/set.go index 7ae7876..e6b8e85 100644 --- a/flags/set.go +++ b/flags/set.go @@ -23,6 +23,16 @@ func (s Set) Get(name string) (Flag, bool) { return nil, false } +func (s Set) MaxWidth() int { + max := 0 + for _, f := range s { + if w := len(Names(f)); w > max { + max = w + } + } + return max +} + // TODO: Implement func (s Set) Parse(args []string) error { return nil diff --git a/flags/string.go b/flags/string.go index a38c0c3..e2ccf2b 100644 --- a/flags/string.go +++ b/flags/string.go @@ -9,7 +9,7 @@ type StringFlag struct { var _ Flag = (*StringFlag)(nil) -func NewStringFlag(name, shortName, defaultValue, description string) *StringFlag { +func String(name, shortName, defaultValue, description string) *StringFlag { return &StringFlag{ name: name, shortName: shortName, @@ -31,7 +31,6 @@ func (f *StringFlag) Name() string { // ShortName implements Flag. func (f *StringFlag) ShortName() string { return f.shortName - } // Value implements Flag. diff --git a/help.go b/help.go index 1d540db..a29cd36 100644 --- a/help.go +++ b/help.go @@ -2,6 +2,8 @@ package cmd import ( "fmt" + + "go.fifitido.net/cmd/flags" ) func (c *Command) ShowHelp() { @@ -39,8 +41,9 @@ func (c *Command) ShowHelp() { fmt.Println() fmt.Println("Available flags:") - for _, s := range c.flags { - fmt.Println(" " + s.Name() + " " + s.Description()) + paddedWidth := c.flags.MaxWidth() + for _, f := range c.flags { + fmt.Println(" " + flags.HelpLine(f, paddedWidth)) } fmt.Println(" -h, --help Show the help menu") diff --git a/option.go b/option.go index 5a1b3e4..eb26a7b 100644 --- a/option.go +++ b/option.go @@ -22,7 +22,7 @@ func WithArgument(name string, required bool) Option { } } -func WithArguments(args []*Argument) Option { +func WithArguments(args ...*Argument) Option { return func(c *Command) { c.arguments = append(c.arguments, args...) } @@ -34,7 +34,7 @@ func WithFlag(f flags.Flag) Option { } } -func WithFlags(fs []flags.Flag) Option { +func WithFlags(fs ...flags.Flag) Option { return func(c *Command) { c.flags = append(c.flags, fs...) } @@ -47,7 +47,7 @@ func WithSubcommand(s *Command) Option { } } -func WithSubcommands(ss []*Command) Option { +func WithSubcommands(ss ...*Command) Option { return func(c *Command) { c.subcommands = append(c.subcommands, ss...) }