зеркало из https://github.com/mislav/hub.git
Restructure how command usage is stored and displayed
- No more `c.Short` property. Instead, the first line of `c.Long` property is considered a short command description. - The `c.Usage` text can now contain multiple lines. - The new `c.Synopsis()` method renders usage synopsis for humans: Usage: hub my-command --arg hub my-command --alternative-arg - The new `c.HelpText()` method renders synopsis + full help text.
This commit is contained in:
Родитель
9c9ff2d341
Коммит
1918e011a6
|
@ -103,7 +103,7 @@ func browse(command *Command, args *Args) {
|
|||
}
|
||||
|
||||
if project == nil {
|
||||
err := fmt.Errorf(command.FormattedUsage())
|
||||
err := fmt.Errorf(command.Synopsis())
|
||||
utils.Check(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -23,7 +22,6 @@ type Command struct {
|
|||
|
||||
Key string
|
||||
Usage string
|
||||
Short string
|
||||
Long string
|
||||
GitExtension bool
|
||||
|
||||
|
@ -52,7 +50,10 @@ func (c *Command) Call(args *Args) (err error) {
|
|||
func (c *Command) parseArguments(args *Args) (err error) {
|
||||
c.Flag.SetInterspersed(true)
|
||||
c.Flag.Init(c.Name(), flag.ContinueOnError)
|
||||
c.Flag.Usage = c.PrintUsage
|
||||
c.Flag.Usage = func() {
|
||||
ui.Errorln("")
|
||||
ui.Errorln(c.Synopsis())
|
||||
}
|
||||
if err = c.Flag.Parse(args.Params); err == nil {
|
||||
for _, arg := range args.Params {
|
||||
if arg == "--" {
|
||||
|
@ -72,53 +73,35 @@ func (c *Command) Use(subCommand *Command) {
|
|||
c.subCommands[subCommand.Name()] = subCommand
|
||||
}
|
||||
|
||||
func (c *Command) PrintUsage() {
|
||||
if c.Runnable() {
|
||||
ui.Printf("usage: %s\n\n", c.FormattedUsage())
|
||||
}
|
||||
func (c *Command) Synopsis() string {
|
||||
lines := []string{}
|
||||
usagePrefix := "Usage:"
|
||||
|
||||
ui.Println(strings.Trim(c.Long, "\n"))
|
||||
for _, line := range strings.Split(c.Usage, "\n") {
|
||||
if line != "" {
|
||||
usage := fmt.Sprintf("%s hub %s", usagePrefix, line)
|
||||
usagePrefix = " "
|
||||
lines = append(lines, usage)
|
||||
}
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func (c *Command) FormattedUsage() string {
|
||||
return fmt.Sprintf("git %s", c.Usage)
|
||||
}
|
||||
|
||||
func (c *Command) subCommandsUsage() string {
|
||||
buffer := bytes.NewBufferString("")
|
||||
|
||||
usage := "usage"
|
||||
usage = printUsageBuffer(c, buffer, usage)
|
||||
for _, s := range c.subCommands {
|
||||
usage = printUsageBuffer(s, buffer, usage)
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func printUsageBuffer(c *Command, b *bytes.Buffer, usage string) string {
|
||||
if c.Runnable() {
|
||||
b.WriteString(fmt.Sprintf("%s: %s\n", usage, c.FormattedUsage()))
|
||||
usage = " or"
|
||||
}
|
||||
return usage
|
||||
func (c *Command) HelpText() string {
|
||||
return fmt.Sprintf("%s\n\n%s", c.Synopsis(), strings.Replace(c.Long, "'", "`", -1))
|
||||
}
|
||||
|
||||
func (c *Command) Name() string {
|
||||
if c.Key != "" {
|
||||
return c.Key
|
||||
}
|
||||
return strings.Split(c.Usage, " ")[0]
|
||||
return strings.Split(strings.TrimSpace(c.Usage), " ")[0]
|
||||
}
|
||||
|
||||
func (c *Command) Runnable() bool {
|
||||
return c.Run != nil
|
||||
}
|
||||
|
||||
func (c *Command) List() bool {
|
||||
return c.Short != ""
|
||||
}
|
||||
|
||||
func (c *Command) lookupSubCommand(args *Args) (runCommand *Command, err error) {
|
||||
if len(c.subCommands) > 0 && args.HasSubcommand() {
|
||||
subCommandName := args.FirstParam()
|
||||
|
@ -126,7 +109,7 @@ func (c *Command) lookupSubCommand(args *Args) (runCommand *Command, err error)
|
|||
runCommand = subCommand
|
||||
args.Params = args.Params[1:]
|
||||
} else {
|
||||
err = fmt.Errorf("error: Unknown subcommand: %s\n%s", subCommandName, c.subCommandsUsage())
|
||||
err = fmt.Errorf("error: Unknown subcommand: %s", subCommandName)
|
||||
}
|
||||
} else {
|
||||
runCommand = c
|
||||
|
|
|
@ -87,41 +87,6 @@ func TestFlagsAfterArguments(t *testing.T) {
|
|||
assert.Equal(t, "bar", args.LastParam())
|
||||
}
|
||||
|
||||
func TestCommandUsageSubCommands(t *testing.T) {
|
||||
f1 := func(c *Command, args *Args) {}
|
||||
f2 := func(c *Command, args *Args) {}
|
||||
|
||||
c := &Command{Usage: "foo", Run: f1}
|
||||
s := &Command{Key: "bar", Usage: "foo bar", Run: f2}
|
||||
c.Use(s)
|
||||
|
||||
usage := c.subCommandsUsage()
|
||||
|
||||
expected := `usage: git foo
|
||||
or: git foo bar
|
||||
`
|
||||
assert.Equal(t, expected, usage)
|
||||
}
|
||||
|
||||
func TestCommandUsageSubCommandsPrintOnlyRunnables(t *testing.T) {
|
||||
f1 := func(c *Command, args *Args) {}
|
||||
|
||||
c := &Command{Usage: "foo"}
|
||||
s := &Command{Key: "bar", Usage: "foo bar", Run: f1}
|
||||
c.Use(s)
|
||||
|
||||
usage := c.subCommandsUsage()
|
||||
|
||||
expected := `usage: git foo bar
|
||||
`
|
||||
assert.Equal(t, expected, usage)
|
||||
}
|
||||
|
||||
func TestCommandNameTakeUsage(t *testing.T) {
|
||||
c := &Command{Usage: "foo -t -v --foo"}
|
||||
assert.Equal(t, "foo", c.Name())
|
||||
}
|
||||
|
||||
func TestCommandNameTakeKey(t *testing.T) {
|
||||
c := &Command{Key: "bar", Usage: "foo -t -v --foo"}
|
||||
assert.Equal(t, "bar", c.Name())
|
||||
|
@ -162,22 +127,3 @@ func TestSubCommandCall(t *testing.T) {
|
|||
c.Call(args)
|
||||
assert.Equal(t, "baz", result)
|
||||
}
|
||||
|
||||
func TestSubCommandsUsage(t *testing.T) {
|
||||
// with subcommand
|
||||
f1 := func(c *Command, args *Args) {}
|
||||
f2 := func(c *Command, args *Args) {}
|
||||
|
||||
c := &Command{Usage: "foo", Run: f1}
|
||||
s := &Command{Key: "bar", Usage: "foo bar", Run: f2}
|
||||
c.Use(s)
|
||||
|
||||
usage := c.subCommandsUsage()
|
||||
assert.Equal(t, "usage: git foo\n or: git foo bar\n", usage)
|
||||
|
||||
// no subcommand
|
||||
cc := &Command{Usage: "foo", Run: f1}
|
||||
|
||||
usage = cc.subCommandsUsage()
|
||||
assert.Equal(t, "usage: git foo\n", usage)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/github/hub/cmd"
|
||||
"github.com/github/hub/git"
|
||||
"github.com/github/hub/ui"
|
||||
"github.com/github/hub/utils"
|
||||
)
|
||||
|
||||
|
@ -45,7 +46,7 @@ func runHelp(helpCmd *Command, args *Args) {
|
|||
|
||||
c := CmdRunner.Lookup(command)
|
||||
if c != nil && !c.GitExtension {
|
||||
c.PrintUsage()
|
||||
ui.Println(c.HelpText())
|
||||
os.Exit(0)
|
||||
} else if c == nil {
|
||||
if args.HasFlags("-a", "--all") {
|
||||
|
|
Загрузка…
Ссылка в новой задаче