Allow to chain subcommands using `command.Use(subcommandName, subcommand)`.

This commit is contained in:
David Calavera 2013-12-28 21:24:08 -08:00
Родитель fce2d4df47
Коммит 51428d5449
4 изменённых файлов: 63 добавлений и 21 удалений

Просмотреть файл

@ -72,6 +72,10 @@ func (a *Args) LastParam() string {
return a.Params[a.ParamsSize()-1]
}
func (a *Args) HasSubcommand() bool {
return !a.IsParamsEmpty() && a.Params[0][0] != '-'
}
func (a *Args) InsertParam(i int, items ...string) {
if i < 0 || (i != 0 && i > a.ParamsSize()-1) {
panic(fmt.Sprintf("Index %d is out of bound", i))

Просмотреть файл

@ -3,6 +3,7 @@ package commands
import (
"flag"
"fmt"
"os"
"strings"
)
@ -20,6 +21,50 @@ type Command struct {
Short string
Long string
GitExtension bool
subCommands map[string]*Command
}
func (c *Command) Call(args *Args) (err error) {
runCommand := c
if len(c.subCommands) > 0 && args.HasSubcommand() {
subCommandName := args.FirstParam()
if subCommand, ok := c.subCommands[subCommandName]; ok {
runCommand = subCommand
args.Params = args.Params[1:]
} else {
fmt.Printf("error: Unknown subcommand: %s\n", subCommandName)
c.PrintUsage()
os.Exit(1)
}
}
if err = c.parseArguments(args); err != nil {
return
}
runCommand.Run(runCommand, args)
return
}
func (c *Command) parseArguments(args *Args) (err error) {
if err := c.Flag.Parse(args.Params); err != nil {
if err == flag.ErrHelp {
return nil
} else {
return err
}
}
args.Params = c.Flag.Args()
return
}
func (c *Command) Use(name string, subCommand *Command) {
if c.subCommands == nil {
c.subCommands = make(map[string]*Command)
}
c.subCommands[name] = subCommand
}
func (c *Command) PrintUsage() {
@ -77,7 +122,6 @@ var GitHub = []*Command{
cmdCiStatus,
cmdBrowse,
cmdCompare,
cmdReleases,
cmdRelease,
cmdIssue,
}

Просмотреть файл

@ -16,15 +16,15 @@ import (
)
var (
cmdReleases = &Command{
Run: releases,
Usage: "releases",
cmdRelease = &Command{
Run: release,
Usage: "release",
Short: "Retrieve releases from GitHub",
Long: `Retrieve releases from GitHub for the project that the "origin" remote points to.`}
cmdRelease = &Command{
Run: release,
Usage: "release [-d] [-p] [-a <ASSETS_DIR>] [-m <MESSAGE>|-f <FILE>] TAG",
cmdCreateRelease = &Command{
Run: createRelease,
Usage: "release create [-d] [-p] [-a <ASSETS_DIR>] [-m <MESSAGE>|-f <FILE>] TAG",
Short: "Create a new release in GitHub",
Long: `Create a new release in GitHub for the project that the "origin" remote points to.
- It requires the name of the tag to release as a first argument.
@ -42,6 +42,8 @@ var (
)
func init() {
cmdRelease.Use("create", cmdCreateRelease)
cmdRelease.Flag.BoolVar(&flagReleaseDraft, "d", false, "DRAFT")
cmdRelease.Flag.BoolVar(&flagReleasePrerelease, "p", false, "PRERELEASE")
cmdRelease.Flag.StringVar(&flagReleaseAssetsDir, "a", "", "ASSETS_DIR")
@ -49,7 +51,7 @@ func init() {
cmdRelease.Flag.StringVar(&flagReleaseFile, "f", "", "FILE")
}
func releases(cmd *Command, args *Args) {
func release(cmd *Command, args *Args) {
runInLocalRepo(func(localRepo *github.GitHubRepo, project *github.Project, gh *github.Client) {
if args.Noop {
fmt.Printf("Would request list of releases for %s\n", project)
@ -67,7 +69,7 @@ func releases(cmd *Command, args *Args) {
})
}
func release(cmd *Command, args *Args) {
func createRelease(cmd *Command, args *Args) {
if args.IsParamsEmpty() {
utils.Check(fmt.Errorf("Missed argument TAG"))
return

Просмотреть файл

@ -1,7 +1,6 @@
package commands
import (
"flag"
"fmt"
"github.com/jingweno/gh/cmd"
"github.com/jingweno/gh/git"
@ -59,21 +58,14 @@ func (r *Runner) Execute() ExecError {
cmd.Flag.Usage = func() {
cmd.PrintUsage()
}
if err := cmd.Flag.Parse(args.Params); err != nil {
if err == flag.ErrHelp {
return newExecError(nil)
} else {
return newExecError(err)
}
}
args.Params = cmd.Flag.Args()
}
cmd.Run(cmd, args)
err := cmd.Call(args)
if err != nil {
return newExecError(err)
}
cmds := args.Commands()
var err error
if args.Noop {
printCommands(cmds)
} else {