From 99387d89ac2f85116716e153f35e0e47a7b21095 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Sat, 6 Apr 2019 14:20:01 -0400 Subject: [PATCH] mcfg: don't allow for empty sub-command, as that makes printing help weird --- mcfg/cli.go | 33 ++++++++------------------ mcfg/cli_test.go | 60 ++++++++++++++---------------------------------- 2 files changed, 26 insertions(+), 67 deletions(-) diff --git a/mcfg/cli.go b/mcfg/cli.go index c1cb9c2..7eb9501 100644 --- a/mcfg/cli.go +++ b/mcfg/cli.go @@ -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) - } + subCmdPrefix = append(subCmdPrefix, subCmd.name) *subCmd.flag = true 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) { - // 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 len(args) == 0 { + return subCmd{}, args, false } - // 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 + s, ok := subCmdM[args[0]] + if !ok { + return subCmd{}, args, false } - return subCmd{}, args, false + return s, args[1:], true } func (cli *SourceCLI) cliParams(params []Param) (map[string]Param, error) { @@ -307,9 +299,6 @@ func (cli *SourceCLI) printHelp( subCmdA := make([]subCmdEntry, 0, len(subCmdM)) for name, subCmd := range subCmdM { - if name == "" { - name = "" - } subCmdA = append(subCmdA, subCmdEntry{name: name, subCmd: subCmd}) } @@ -322,11 +311,7 @@ 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, " ") - } + fmt.Fprint(w, " ") } if len(pA) > 0 { fmt.Fprint(w, " [options]") diff --git a/mcfg/cli_test.go b/mcfg/cli_test.go index 0bdc79f..c713e4b 100644 --- a/mcfg/cli_test.go +++ b/mcfg/cli_test.go @@ -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: - - 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) { var ( - ctx context.Context - foo *int - bar *int - baz *int - aFlag *bool - defaultFlag *bool + ctx context.Context + foo *int + bar *int + baz *int + aFlag *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 }