From cef66fd2f6e0e061ade3778d3d3868032e4f0a32 Mon Sep 17 00:00:00 2001 From: Alexey Trofimov Date: Wed, 18 Jan 2023 11:50:50 +0300 Subject: [PATCH 1/2] add strict subcommand parsing --- go.sum | 2 -- parse.go | 11 ++++++- parse_test.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/go.sum b/go.sum index 5b536f9..385ca8f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/alexflint/go-scalar v1.1.0 h1:aaAouLLzI9TChcPXotr6gUhq+Scr8rl0P9P4PnltbhM= -github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/parse.go b/parse.go index 6ac5e99..3efe858 100644 --- a/parse.go +++ b/parse.go @@ -115,6 +115,10 @@ type Config struct { // IgnoreDefault instructs the library not to reset the variables to the // default values, including pointers to sub commands IgnoreDefault bool + + // IgnoreDefault intructs the library not to allow global commands after + // subcommand + StrictSubcommands bool } // Parser represents a set of command line options with destination values @@ -588,7 +592,12 @@ func (p *Parser) process(args []string) error { } // add the new options to the set of allowed options - specs = append(specs, subcmd.specs...) + if p.config.StrictSubcommands { + specs = make([]*spec, len(subcmd.specs)) + copy(specs, subcmd.specs) + } else { + specs = append(specs, subcmd.specs...) + } // capture environment vars for these new options if !p.config.IgnoreEnv { diff --git a/parse_test.go b/parse_test.go index 5d38306..64119a8 100644 --- a/parse_test.go +++ b/parse_test.go @@ -98,9 +98,9 @@ func TestInt(t *testing.T) { func TestHexOctBin(t *testing.T) { var args struct { - Hex int - Oct int - Bin int + Hex int + Oct int + Bin int Underscored int } err := parse("--hex 0xA --oct 0o10 --bin 0b101 --underscored 123_456", &args) @@ -1614,3 +1614,79 @@ func TestTextMarshalerUnmarshalerEmptyPointer(t *testing.T) { require.NoError(t, err) assert.Nil(t, args.Config) } + +func TestSubcommandGlobalFlag_Before(t *testing.T) { + var args struct { + Global bool `arg:"-g"` + Sub *struct { + } `arg:"subcommand"` + } + + p, err := NewParser(Config{StrictSubcommands: false}, &args) + require.NoError(t, err) + + err = p.Parse([]string{"-g", "sub"}) + assert.NoError(t, err) + assert.True(t, args.Global) +} + +func TestSubcommandGlobalFlag_InCommand(t *testing.T) { + var args struct { + Global bool `arg:"-g"` + Sub *struct { + } `arg:"subcommand"` + } + + p, err := NewParser(Config{StrictSubcommands: false}, &args) + require.NoError(t, err) + + err = p.Parse([]string{"sub", "-g"}) + assert.NoError(t, err) + assert.True(t, args.Global) +} + +func TestSubcommandGlobalFlag_Before_Strict(t *testing.T) { + var args struct { + Global bool `arg:"-g"` + Sub *struct { + } `arg:"subcommand"` + } + + p, err := NewParser(Config{StrictSubcommands: true}, &args) + require.NoError(t, err) + + err = p.Parse([]string{"-g", "sub"}) + assert.NoError(t, err) + assert.True(t, args.Global) +} + +func TestSubcommandGlobalFlag_InCommand_Strict(t *testing.T) { + var args struct { + Global bool `arg:"-g"` + Sub *struct { + } `arg:"subcommand"` + } + + p, err := NewParser(Config{StrictSubcommands: true}, &args) + require.NoError(t, err) + + err = p.Parse([]string{"sub", "-g"}) + assert.Error(t, err) +} + +func TestSubcommandGlobalFlag_InCommand_Strict_Inner(t *testing.T) { + var args struct { + Global bool `arg:"-g"` + Sub *struct { + Guard bool `arg:"-g"` + } `arg:"subcommand"` + } + + p, err := NewParser(Config{StrictSubcommands: true}, &args) + require.NoError(t, err) + + err = p.Parse([]string{"sub", "-g"}) + assert.NoError(t, err) + assert.False(t, args.Global) + assert.True(t, args.Sub.Guard) +} From 5036dce2d6a64b2dd1b6e270947bde1e8110708c Mon Sep 17 00:00:00 2001 From: Alexey Trofimov Date: Wed, 18 Jan 2023 11:52:13 +0300 Subject: [PATCH 2/2] fix typo --- parse.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.go b/parse.go index 3efe858..b935fad 100644 --- a/parse.go +++ b/parse.go @@ -116,7 +116,7 @@ type Config struct { // default values, including pointers to sub commands IgnoreDefault bool - // IgnoreDefault intructs the library not to allow global commands after + // StrictSubcommands intructs the library not to allow global commands after // subcommand StrictSubcommands bool }