diff --git a/command.go b/command.go index 7910c49..9f172af 100644 --- a/command.go +++ b/command.go @@ -210,6 +210,8 @@ func (c *Command) Execute() error { // cmd here will be c. cmd, args := findRequestedCommand(c, c.args) + // Below this point, use cmd not c! + if err := cmd.flagSet().Parse(args); err != nil { return fmt.Errorf("failed to parse command flags: %w", err) } @@ -257,9 +259,9 @@ func (c *Command) Execute() error { // // We're modifying the slice in place here, hence not using a range loop as it // would take a copy of the c.positionalArgs slice - for i := 0; i < len(c.positionalArgs); i++ { + for i := 0; i < len(cmd.positionalArgs); i++ { if i >= len(argsWithoutFlags) { - arg := c.positionalArgs[i] + arg := cmd.positionalArgs[i] // If we've fallen off the end of argsWithoutFlags and the positionalArg at this // index does not have a default, it means the arg was required but not provided @@ -267,12 +269,12 @@ func (c *Command) Execute() error { return fmt.Errorf("missing required argument %q, expected at position %d", arg.name, i) } // It does have a default, so use that instead - c.positionalArgs[i].value = arg.defaultValue + cmd.positionalArgs[i].value = arg.defaultValue } else { // We are in a valid index in both slices which means the named positional // argument at this index was provided on the command line, so all we need // to do is set its value - c.positionalArgs[i].value = argsWithoutFlags[i] + cmd.positionalArgs[i].value = argsWithoutFlags[i] } } diff --git a/command_test.go b/command_test.go index 1034d19..f57b138 100644 --- a/command_test.go +++ b/command_test.go @@ -228,6 +228,18 @@ func TestSubCommandExecute(t *testing.T) { } func TestPositionalArgs(t *testing.T) { + sub := func() (*cli.Command, error) { + return cli.New( + "sub", + cli.Short("Sub command"), + cli.Arg("subarg", "Argument given to a subcommand", ""), + cli.Run(func(cmd *cli.Command, args []string) error { + fmt.Fprintf(cmd.Stdout(), "Hello from sub command, subarg: %s", cmd.Arg("subarg")) + return nil + }), + ) + } + tests := []struct { name string // The name of the test case stdout string // The expected stdout @@ -320,6 +332,15 @@ func TestPositionalArgs(t *testing.T) { wantErr: true, errMsg: `missing required argument "something", expected at position 2`, }, + { + name: "subcommand with named arg", + options: []cli.Option{ + cli.SubCommands(sub), + }, + stdout: "Hello from sub command, subarg: blah", + args: []string{"sub", "blah"}, // subarg should be "blah" + wantErr: false, + }, } for _, tt := range tests {