diff --git a/command/command.go b/command/command.go index 79833b3..55f0ead 100644 --- a/command/command.go +++ b/command/command.go @@ -1,7 +1,10 @@ // Package command implements generic nested command parsing. package command -import "flag" +import ( + "flag" + "strings" +) type ( // HandlerFunc is called when matching a directly handled subcommand tree. @@ -13,7 +16,7 @@ type ( // FlagDefiner is a deferred flag definer value, usually encapsulating the default value. FlagDefiner interface { // Define defines the flag in set. - Define(set *flag.FlagSet, p any, name, usage string) + Define(b *strings.Builder, set *flag.FlagSet, p any, name, usage string) } Command interface { diff --git a/command/help.go b/command/help.go new file mode 100644 index 0000000..0bcc15f --- /dev/null +++ b/command/help.go @@ -0,0 +1,49 @@ +package command + +import ( + "errors" + "fmt" + "io" + "strings" + "text/tabwriter" +) + +var ErrHelp = errors.New("help requested") + +func (n *node) writeHelp() error { + if _, err := fmt.Fprintf(n.out, + "\nUsage:\t%s [-h | --help]%s COMMAND [OPTIONS]\n", + strings.Join(append(n.prefix, n.name), " "), &n.suffix, + ); err != nil { + return err + } + if n.child != nil { + if _, err := fmt.Fprint(n.out, "\nCommands:\n"); err != nil { + return err + } + } + + tw := tabwriter.NewWriter(n.out, 0, 1, 4, ' ', 0) + if err := n.child.writeCommands(tw); err != nil { + return err + } + if err := tw.Flush(); err != nil { + return err + } + + _, err := n.out.Write([]byte{'\n'}) + if err == nil { + err = ErrHelp + } + return err +} + +func (n *node) writeCommands(w io.Writer) error { + if n == nil { + return nil + } + if _, err := fmt.Fprintf(w, "\t%s\t%s\n", n.name, n.usage); err != nil { + return err + } + return n.next.writeCommands(w) +} diff --git a/command/node.go b/command/node.go index 9ed2149..4d09c97 100644 --- a/command/node.go +++ b/command/node.go @@ -3,6 +3,7 @@ package command import ( "flag" "io" + "strings" ) type node struct { @@ -12,6 +13,9 @@ type node struct { out io.Writer logf LogFunc + prefix []string + suffix strings.Builder + f HandlerFunc set *flag.FlagSet }