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.
//
// 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
// 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.
// Parse, it is assumed that a sub-command is required 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) {
@ -156,9 +154,7 @@ func (cli *SourceCLI) parse(
if subCmd.callback != nil {
ctx = subCmd.callback(ctx)
}
if subCmd.name != "" {
subCmdPrefix = append(subCmdPrefix, subCmd.name)
}
*subCmd.flag = true
return cli.parse(ctx, subCmdPrefix, args)
}
@ -238,22 +234,18 @@ func (cli *SourceCLI) parse(
}
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 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
// allowed, check if that's the case
if subCmd, ok := subCmdM[""]; ok {
return subCmd, args, true
}
if len(args) == 0 {
return subCmd{}, args, false
}
s, ok := subCmdM[args[0]]
if !ok {
return subCmd{}, args, false
}
return s, args[1:], true
}
func (cli *SourceCLI) cliParams(params []Param) (map[string]Param, error) {
m := map[string]Param{}
for _, p := range params {
@ -307,9 +299,6 @@ func (cli *SourceCLI) printHelp(
subCmdA := make([]subCmdEntry, 0, len(subCmdM))
for name, subCmd := range subCmdM {
if name == "" {
name = "<None>"
}
subCmdA = append(subCmdA, subCmdEntry{name: name, subCmd: subCmd})
}
@ -322,12 +311,8 @@ func (cli *SourceCLI) printHelp(
fmt.Fprintf(w, " %s", strings.Join(subCmdPrefix, " "))
}
if len(subCmdA) > 0 {
if _, ok := subCmdM[""]; ok {
fmt.Fprint(w, " [sub-command]")
} else {
fmt.Fprint(w, " <sub-command>")
}
}
if len(pA) > 0 {
fmt.Fprint(w, " [options]")
}

View File

@ -106,32 +106,6 @@ Options:
--foo \(Default: 5\)
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.
$`)
}
@ -260,10 +234,10 @@ func TestWithCLISubCommand(t *T) {
bar *int
baz *int
aFlag *bool
defaultFlag *bool
bFlag *bool
)
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, foo = WithInt(ctx, "foo", 0, "Description of foo.")
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.")
return ctx
})
ctx, defaultFlag = WithCLISubCommand(ctx, "", "Description of default.",
ctx, bFlag = WithCLISubCommand(ctx, "b", "Description of b.",
func(ctx context.Context) context.Context {
ctx, baz = WithInt(ctx, "baz", 0, "Description of baz.")
return ctx
@ -288,12 +262,12 @@ func TestWithCLISubCommand(t *T) {
massert.Equal(2, *bar),
massert.Nil(baz),
massert.Equal(true, *aFlag),
massert.Equal(false, *defaultFlag),
massert.Equal(false, *bFlag),
)
reset()
_, err = Populate(ctx, &SourceCLI{
Args: []string{"--foo=1", "--baz=3"},
Args: []string{"b", "--foo=1", "--baz=3"},
})
massert.Require(t,
massert.Comment(massert.Nil(err), "%v", err),
@ -301,7 +275,7 @@ func TestWithCLISubCommand(t *T) {
massert.Nil(bar),
massert.Equal(3, *baz),
massert.Equal(false, *aFlag),
massert.Equal(true, *defaultFlag),
massert.Equal(true, *bFlag),
)
}
@ -317,7 +291,7 @@ func ExampleWithCLISubCommand() {
})
var baz *int
ctx, defaultFlag := WithCLISubCommand(ctx, "", "Description of default.",
ctx, bFlag := WithCLISubCommand(ctx, "b", "Description of b.",
func(ctx context.Context) context.Context {
ctx, baz = WithInt(ctx, "baz", 0, "Description of baz.")
return ctx
@ -327,16 +301,16 @@ func ExampleWithCLISubCommand() {
if _, err := Populate(ctx, &SourceCLI{Args: args}); err != nil {
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
*aFlag = false
args = []string{"--foo=1", "--baz=3"}
args = []string{"b", "--foo=1", "--baz=3"}
if _, err := Populate(ctx, &SourceCLI{Args: args}); err != nil {
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
// foo:1 baz:3 aFlag:false defaultFlag:true
// Output: foo:1 bar:2 aFlag:true bFlag:false
// foo:1 baz:3 aFlag:false bFlag:true
}