mcfg: don't allow for empty sub-command, as that makes printing help weird

This commit is contained in:
Brian Picciano 2019-04-06 14:20:01 -04:00
parent b35b44eb22
commit 99387d89ac
2 changed files with 26 additions and 67 deletions

View File

@ -59,9 +59,7 @@ type subCmd struct {
// support for sub-sub-commands, and more. The callback may be nil. // support for sub-sub-commands, and more. The callback may be nil.
// //
// If any sub-commands have been defined on a Context which is passed into // If any sub-commands have been defined on a Context which is passed into
// Parse, it is assumed that a sub-command is required on the command-line. The // Parse, it is assumed that a sub-command is required on the command-line.
// exception is if a sub-command with a name of "" has been defined; if so, it
// will be used as the intended sub-command if none is specified.
// //
// Sub-commands must be specified before any other options on the command-line. // Sub-commands must be specified before any other options on the command-line.
func WithCLISubCommand(ctx context.Context, name, descr string, callback func(context.Context) context.Context) (context.Context, *bool) { func WithCLISubCommand(ctx context.Context, name, descr string, callback func(context.Context) context.Context) (context.Context, *bool) {
@ -156,9 +154,7 @@ func (cli *SourceCLI) parse(
if subCmd.callback != nil { if subCmd.callback != nil {
ctx = subCmd.callback(ctx) ctx = subCmd.callback(ctx)
} }
if subCmd.name != "" { subCmdPrefix = append(subCmdPrefix, subCmd.name)
subCmdPrefix = append(subCmdPrefix, subCmd.name)
}
*subCmd.flag = true *subCmd.flag = true
return cli.parse(ctx, subCmdPrefix, args) return cli.parse(ctx, subCmdPrefix, args)
} }
@ -238,20 +234,16 @@ func (cli *SourceCLI) parse(
} }
func (cli *SourceCLI) getSubCmd(subCmdM map[string]subCmd, args []string) (subCmd, []string, bool) { func (cli *SourceCLI) getSubCmd(subCmdM map[string]subCmd, args []string) (subCmd, []string, bool) {
// if a proper sub-command is given then great, return that if len(args) == 0 {
if len(args) > 0 { return subCmd{}, args, false
if subCmd, ok := subCmdM[args[0]]; ok {
return subCmd, args[1:], true
}
} }
// if the empty subCmd is set in the map it means an absent sub-command is s, ok := subCmdM[args[0]]
// allowed, check if that's the case if !ok {
if subCmd, ok := subCmdM[""]; ok { return subCmd{}, args, false
return subCmd, args, true
} }
return subCmd{}, args, false return s, args[1:], true
} }
func (cli *SourceCLI) cliParams(params []Param) (map[string]Param, error) { func (cli *SourceCLI) cliParams(params []Param) (map[string]Param, error) {
@ -307,9 +299,6 @@ func (cli *SourceCLI) printHelp(
subCmdA := make([]subCmdEntry, 0, len(subCmdM)) subCmdA := make([]subCmdEntry, 0, len(subCmdM))
for name, subCmd := range subCmdM { for name, subCmd := range subCmdM {
if name == "" {
name = "<None>"
}
subCmdA = append(subCmdA, subCmdEntry{name: name, subCmd: subCmd}) subCmdA = append(subCmdA, subCmdEntry{name: name, subCmd: subCmd})
} }
@ -322,11 +311,7 @@ func (cli *SourceCLI) printHelp(
fmt.Fprintf(w, " %s", strings.Join(subCmdPrefix, " ")) fmt.Fprintf(w, " %s", strings.Join(subCmdPrefix, " "))
} }
if len(subCmdA) > 0 { if len(subCmdA) > 0 {
if _, ok := subCmdM[""]; ok { fmt.Fprint(w, " <sub-command>")
fmt.Fprint(w, " [sub-command]")
} else {
fmt.Fprint(w, " <sub-command>")
}
} }
if len(pA) > 0 { if len(pA) > 0 {
fmt.Fprint(w, " [options]") fmt.Fprint(w, " [options]")

View File

@ -106,32 +106,6 @@ Options:
--foo \(Default: 5\) --foo \(Default: 5\)
Test int param. Test int param.
$`)
ctx, _ = WithCLISubCommand(ctx, "", "No sub-command", nil)
assertHelp(ctx, []string{"foo", "bar"}, `^Usage: \S+ foo bar \[sub-command\] \[options\]
Sub-commands:
<None> No sub-command
first First sub-command
second Second sub-command
Options:
--baz2 \(Required\)
--baz3 \(Required\)
--bar \(Flag\)
Test bool param.
--baz \(Default: "baz"\)
Test string param.
--foo \(Default: 5\)
Test int param.
$`) $`)
} }
@ -255,15 +229,15 @@ func ExampleWithCLITail() {
func TestWithCLISubCommand(t *T) { func TestWithCLISubCommand(t *T) {
var ( var (
ctx context.Context ctx context.Context
foo *int foo *int
bar *int bar *int
baz *int baz *int
aFlag *bool aFlag *bool
defaultFlag *bool bFlag *bool
) )
reset := func() { reset := func() {
foo, bar, baz, aFlag, defaultFlag = nil, nil, nil, nil, nil foo, bar, baz, aFlag, bFlag = nil, nil, nil, nil, nil
ctx = context.Background() ctx = context.Background()
ctx, foo = WithInt(ctx, "foo", 0, "Description of foo.") ctx, foo = WithInt(ctx, "foo", 0, "Description of foo.")
ctx, aFlag = WithCLISubCommand(ctx, "a", "Description of a.", ctx, aFlag = WithCLISubCommand(ctx, "a", "Description of a.",
@ -271,7 +245,7 @@ func TestWithCLISubCommand(t *T) {
ctx, bar = WithInt(ctx, "bar", 0, "Description of bar.") ctx, bar = WithInt(ctx, "bar", 0, "Description of bar.")
return ctx return ctx
}) })
ctx, defaultFlag = WithCLISubCommand(ctx, "", "Description of default.", ctx, bFlag = WithCLISubCommand(ctx, "b", "Description of b.",
func(ctx context.Context) context.Context { func(ctx context.Context) context.Context {
ctx, baz = WithInt(ctx, "baz", 0, "Description of baz.") ctx, baz = WithInt(ctx, "baz", 0, "Description of baz.")
return ctx return ctx
@ -288,12 +262,12 @@ func TestWithCLISubCommand(t *T) {
massert.Equal(2, *bar), massert.Equal(2, *bar),
massert.Nil(baz), massert.Nil(baz),
massert.Equal(true, *aFlag), massert.Equal(true, *aFlag),
massert.Equal(false, *defaultFlag), massert.Equal(false, *bFlag),
) )
reset() reset()
_, err = Populate(ctx, &SourceCLI{ _, err = Populate(ctx, &SourceCLI{
Args: []string{"--foo=1", "--baz=3"}, Args: []string{"b", "--foo=1", "--baz=3"},
}) })
massert.Require(t, massert.Require(t,
massert.Comment(massert.Nil(err), "%v", err), massert.Comment(massert.Nil(err), "%v", err),
@ -301,7 +275,7 @@ func TestWithCLISubCommand(t *T) {
massert.Nil(bar), massert.Nil(bar),
massert.Equal(3, *baz), massert.Equal(3, *baz),
massert.Equal(false, *aFlag), massert.Equal(false, *aFlag),
massert.Equal(true, *defaultFlag), massert.Equal(true, *bFlag),
) )
} }
@ -317,7 +291,7 @@ func ExampleWithCLISubCommand() {
}) })
var baz *int var baz *int
ctx, defaultFlag := WithCLISubCommand(ctx, "", "Description of default.", ctx, bFlag := WithCLISubCommand(ctx, "b", "Description of b.",
func(ctx context.Context) context.Context { func(ctx context.Context) context.Context {
ctx, baz = WithInt(ctx, "baz", 0, "Description of baz.") ctx, baz = WithInt(ctx, "baz", 0, "Description of baz.")
return ctx return ctx
@ -327,16 +301,16 @@ func ExampleWithCLISubCommand() {
if _, err := Populate(ctx, &SourceCLI{Args: args}); err != nil { if _, err := Populate(ctx, &SourceCLI{Args: args}); err != nil {
panic(err) panic(err)
} }
fmt.Printf("foo:%d bar:%d aFlag:%v defaultFlag:%v\n", *foo, *bar, *aFlag, *defaultFlag) fmt.Printf("foo:%d bar:%d aFlag:%v bFlag:%v\n", *foo, *bar, *aFlag, *bFlag)
// reset output for another Populate // reset output for another Populate
*aFlag = false *aFlag = false
args = []string{"--foo=1", "--baz=3"} args = []string{"b", "--foo=1", "--baz=3"}
if _, err := Populate(ctx, &SourceCLI{Args: args}); err != nil { if _, err := Populate(ctx, &SourceCLI{Args: args}); err != nil {
panic(err) panic(err)
} }
fmt.Printf("foo:%d baz:%d aFlag:%v defaultFlag:%v\n", *foo, *baz, *aFlag, *defaultFlag) fmt.Printf("foo:%d baz:%d aFlag:%v bFlag:%v\n", *foo, *baz, *aFlag, *bFlag)
// Output: foo:1 bar:2 aFlag:true defaultFlag:false // Output: foo:1 bar:2 aFlag:true bFlag:false
// foo:1 baz:3 aFlag:false defaultFlag:true // foo:1 baz:3 aFlag:false bFlag:true
} }