rework the commands thing and add a "commands" command to list all commands

Michael Muré created

Change summary

bug/bug.go           |  2 
commands/command.go  | 54 +++++++++++++++++++++++++++++++++++++++++++++
commands/commands.go | 53 ++++++++++++++++++++++++++++-----------------
commands/comment.go  | 16 +++++-------
commands/ls.go       |  7 ++---
commands/new.go      | 10 +++-----
commands/pull.go     |  7 ++---
commands/push.go     |  7 ++---
8 files changed, 108 insertions(+), 48 deletions(-)

Detailed changes

bug/bug.go 🔗

@@ -34,7 +34,7 @@ type Bug struct {
 
 // Create a new Bug
 func NewBug() (*Bug, error) {
-	// TODO: replace with simple random bytes + hash
+	// TODO: replace with commit hash of (first commit + some random)
 
 	// Creating UUID Version 4
 	unique, err := uuid.ID4()

commands/command.go 🔗

@@ -0,0 +1,54 @@
+// Package commands contains the assorted sub commands supported by the git-bug tool.
+package commands
+
+import (
+	"flag"
+	"fmt"
+	"github.com/MichaelMure/git-bug/repository"
+)
+
+const messageFilename = "BUG_MESSAGE_EDITMSG"
+
+// Command represents the definition of a single command.
+type Command struct {
+	// Short description of the command
+	Description string
+	// Command line usage
+	Usage string
+	// Flag set of the command
+	flagSet *flag.FlagSet
+	// Execute the command
+	RunMethod func(repository.Repo, []string) error
+}
+
+// Run executes a command, given its arguments.
+//
+// The args parameter is all of the command line args that followed the
+// subcommand.
+func (cmd *Command) Run(repo repository.Repo, args []string) error {
+	return cmd.RunMethod(repo, args)
+}
+
+func (cmd *Command) PrintUsage(rootCommand string, cmdName string) {
+	fmt.Printf("Usage: %s %s %s\n", rootCommand, cmdName, cmd.Usage)
+
+	if cmd.flagSet != nil {
+		fmt.Printf("\nOptions:\n")
+		cmd.flagSet.PrintDefaults()
+	}
+}
+
+// CommandMap defines all of the available (sub)commands.
+var CommandMap map[string]*Command
+
+// We use init() to avoid a cycle in the data initialization because of the "commands" command
+func init() {
+	CommandMap = map[string]*Command{
+		"commands": commandsCmd,
+		"comment":  commentCmd,
+		"ls":       lsCmd,
+		"new":      newCmd,
+		"pull":     pullCmd,
+		"push":     pushCmd,
+	}
+}

commands/commands.go 🔗

@@ -1,31 +1,44 @@
-// Package commands contains the assorted sub commands supported by the git-bug tool.
 package commands
 
 import (
+	"flag"
+	"fmt"
 	"github.com/MichaelMure/git-bug/repository"
 )
 
-const messageFilename = "BUG_MESSAGE_EDITMSG"
+var commandsFlagSet = flag.NewFlagSet("commands", flag.ExitOnError)
 
-// Command represents the definition of a single command.
-type Command struct {
-	Usage     func(string)
-	RunMethod func(repository.Repo, []string) error
-}
+var (
+	commandsDesc = commandsFlagSet.Bool("pretty", false, "Output the command description as well as Markdown compatible comment")
+)
+
+func runCommands(repo repository.Repo, args []string) error {
+	commandsFlagSet.Parse(args)
+	args = commandsFlagSet.Args()
+
+	first := true
+
+	for name, cmd := range CommandMap {
+		if !first {
+			fmt.Println()
+		}
+
+		first = false
+
+		if *commandsDesc {
+			fmt.Printf("# %s\n", cmd.Description)
+		}
+
+		// TODO: the root name command ("git bug") should be passed from git-bug.go but well ...
+		fmt.Printf("%s %s %s\n", "git bug", name, cmd.Usage)
+	}
 
-// Run executes a command, given its arguments.
-//
-// The args parameter is all of the command line args that followed the
-// subcommand.
-func (cmd *Command) Run(repo repository.Repo, args []string) error {
-	return cmd.RunMethod(repo, args)
+	return nil
 }
 
-// CommandMap defines all of the available (sub)commands.
-var CommandMap = map[string]*Command{
-	"comment": commentCmd,
-	"ls":      lsCmd,
-	"new":     newCmd,
-	"pull":    pullCmd,
-	"push":    pushCmd,
+var commandsCmd = &Command{
+	Description: "Display available commands",
+	Usage:       "[<option>...]",
+	flagSet:     commandsFlagSet,
+	RunMethod:   runCommands,
 }

commands/comment.go 🔗

@@ -3,7 +3,6 @@ package commands
 import (
 	"errors"
 	"flag"
-	"fmt"
 	"github.com/MichaelMure/git-bug/bug"
 	"github.com/MichaelMure/git-bug/bug/operations"
 	"github.com/MichaelMure/git-bug/commands/input"
@@ -50,24 +49,23 @@ func runComment(repo repository.Repo, args []string) error {
 		return err
 	}
 
-	bug, err := bug.FindBug(repo, prefix)
+	b, err := bug.FindBug(repo, prefix)
 	if err != nil {
 		return err
 	}
 
 	addCommentOp := operations.NewAddCommentOp(author, *commentMessage)
 
-	bug.Append(addCommentOp)
+	b.Append(addCommentOp)
 
-	err = bug.Commit(repo)
+	err = b.Commit(repo)
 
 	return err
 }
 
 var commentCmd = &Command{
-	Usage: func(arg0 string) {
-		fmt.Printf("Usage: %s comment <id> [<option>...]\n\nOptions:\n", arg0)
-		commentFlagSet.PrintDefaults()
-	},
-	RunMethod: runComment,
+	Description: "Add a new comment to a bug",
+	Usage:       "[<options>...] <id>",
+	flagSet:     commentFlagSet,
+	RunMethod:   runComment,
 }

commands/ls.go 🔗

@@ -29,8 +29,7 @@ func runLsBug(repo repository.Repo, args []string) error {
 }
 
 var lsCmd = &Command{
-	Usage: func(arg0 string) {
-		fmt.Printf("Usage: %s ls\n", arg0)
-	},
-	RunMethod: runLsBug,
+	Description: "Display a summary of all bugs",
+	Usage:       "",
+	RunMethod:   runLsBug,
 }

commands/new.go 🔗

@@ -3,7 +3,6 @@ package commands
 import (
 	"errors"
 	"flag"
-	"fmt"
 	"github.com/MichaelMure/git-bug/bug"
 	"github.com/MichaelMure/git-bug/bug/operations"
 	"github.com/MichaelMure/git-bug/commands/input"
@@ -66,9 +65,8 @@ func runNewBug(repo repository.Repo, args []string) error {
 }
 
 var newCmd = &Command{
-	Usage: func(arg0 string) {
-		fmt.Printf("Usage: %s new <title> [<option>...]\n\nOptions:\n", arg0)
-		newFlagSet.PrintDefaults()
-	},
-	RunMethod: runNewBug,
+	Description: "Create a new bug",
+	Usage:       "[<option>...] <title>",
+	flagSet:     newFlagSet,
+	RunMethod:   runNewBug,
 }

commands/pull.go 🔗

@@ -25,8 +25,7 @@ func runPull(repo repository.Repo, args []string) error {
 
 // showCmd defines the "push" subcommand.
 var pullCmd = &Command{
-	Usage: func(arg0 string) {
-		fmt.Printf("Usage: %s pull [<remote>]\n", arg0)
-	},
-	RunMethod: runPull,
+	Description: "Pull bugs update from a git remote",
+	Usage:       "[<remote>]",
+	RunMethod:   runPull,
 }

commands/push.go 🔗

@@ -25,8 +25,7 @@ func runPush(repo repository.Repo, args []string) error {
 
 // showCmd defines the "push" subcommand.
 var pushCmd = &Command{
-	Usage: func(arg0 string) {
-		fmt.Printf("Usage: %s push [<remote>]\n", arg0)
-	},
-	RunMethod: runPush,
+	Description: "Push bugs update to a git remote",
+	Usage:       "[<remote>]",
+	RunMethod:   runPush,
 }