diff --git a/command.go b/command.go index fab8e19..bbe4600 100644 --- a/command.go +++ b/command.go @@ -8,13 +8,13 @@ import ( ) type Command struct { - Name string - ShortDescription string - LongDescription string + name string + shortDescription string + longDescription string aliases []string arguments []*Argument flags flags.Set - subcommands []*Command + subcommands Set parent *Command run func(args []string) isRoot bool @@ -27,7 +27,7 @@ func NewRoot(options ...Option) *Command { } func New(name string, options ...Option) *Command { - cmd := &Command{Name: name} + cmd := &Command{name: name} cmd.ApplyOptions(options...) return cmd } @@ -43,7 +43,7 @@ func (c *Command) CommandPath() string { return filepath.Base(os.Args[0]) } - return c.parent.CommandPath() + " " + c.Name + return c.parent.CommandPath() + " " + c.name } func (c *Command) CanRun() bool { @@ -65,18 +65,10 @@ func (c *Command) Execute(args []string) { } if len(args) > 0 { - for _, subcommand := range c.subcommands { - if subcommand.Name == args[0] { - subcommand.Execute(args[1:]) - return - } - - for _, alias := range subcommand.aliases { - if alias == args[0] { - subcommand.Execute(args[1:]) - return - } - } + sc, ok := c.subcommands.Get(args[0]) + if ok { + sc.Execute(args[1:]) + return } // TODO: remove when done with flag parsing diff --git a/flags/global.go b/flags/global.go index 8d45606..acc1da6 100644 --- a/flags/global.go +++ b/flags/global.go @@ -1,6 +1,9 @@ package flags -var globalFlags Set +var globalFlags = Set{ + Bool("help", "h", false, "Show the help menu"), + Bool("version", "v", false, "Show the app version"), +} func Global(fs ...Flag) { globalFlags = append(globalFlags, fs...) diff --git a/flags/set.go b/flags/set.go index e6b8e85..60438e3 100644 --- a/flags/set.go +++ b/flags/set.go @@ -6,8 +6,8 @@ func NewSet() Set { return Set{} } -func (s Set) Add(f Flag) Set { - return append(s, f) +func (s *Set) Add(f Flag) { + *s = append(*s, f) } func (s Set) Get(name string) (Flag, bool) { diff --git a/help.go b/help.go index a29cd36..55c91a9 100644 --- a/help.go +++ b/help.go @@ -9,7 +9,7 @@ import ( func (c *Command) ShowHelp() { cmdPath := c.CommandPath() - fmt.Println(c.LongDescription) + fmt.Println(c.longDescription) fmt.Println() fmt.Println("Usage: ") fmt.Printf(" %s ", cmdPath) @@ -34,7 +34,7 @@ func (c *Command) ShowHelp() { } for _, s := range c.subcommands { - fmt.Println(" " + s.Name + " " + s.ShortDescription) + fmt.Println(" " + s.name + " " + s.shortDescription) } } @@ -46,8 +46,15 @@ func (c *Command) ShowHelp() { fmt.Println(" " + flags.HelpLine(f, paddedWidth)) } - fmt.Println(" -h, --help Show the help menu") - fmt.Println(" -v, --version Show the app version") + globalFlags := flags.Globals() + if len(globalFlags) > 0 { + paddedWidth = globalFlags.MaxWidth() + fmt.Println() + fmt.Println("Global flags:") + for _, f := range globalFlags { + fmt.Println(" " + flags.HelpLine(f, paddedWidth)) + } + } if len(c.subcommands) > 0 { fmt.Println() diff --git a/option.go b/option.go index eb26a7b..266a7e0 100644 --- a/option.go +++ b/option.go @@ -6,13 +6,13 @@ type Option func(*Command) func WithShortDescription(s string) Option { return func(c *Command) { - c.ShortDescription = s + c.shortDescription = s } } func WithLongDescription(s string) Option { return func(c *Command) { - c.LongDescription = s + c.longDescription = s } } @@ -42,21 +42,24 @@ func WithFlags(fs ...flags.Flag) Option { func WithSubcommand(s *Command) Option { return func(c *Command) { - c.subcommands = append(c.subcommands, s) + c.subcommands.Add(c) s.parent = c } } func WithSubcommands(ss ...*Command) Option { return func(c *Command) { - c.subcommands = append(c.subcommands, ss...) + c.subcommands.Add(c) + for _, s := range ss { + s.parent = c + } } } func WithParent(p *Command) Option { return func(c *Command) { c.parent = p - p.subcommands = append(p.subcommands, c) + p.subcommands.Add(c) } } diff --git a/set.go b/set.go new file mode 100644 index 0000000..58110a2 --- /dev/null +++ b/set.go @@ -0,0 +1,40 @@ +package cmd + +type Set []*Command + +func NewSet() Set { + return Set{} +} + +func (s *Set) Add(c *Command) { + *s = append(*s, c) +} + +func (s Set) Get(name string) (*Command, bool) { + for _, c := range s { + if c.name == name { + return c, true + } + + for _, alias := range c.aliases { + if alias == name { + return c, true + } + } + } + return nil, false +} + +func (s Set) MaxNameWidth() int { + max := 0 + for _, f := range s { + if w := len(f.name); w > max { + max = w + } + } + return max +} + +func (s Set) Len() int { + return len(s) +}