Skip to content

Commit

Permalink
Improve unrecognised subcommand handling (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
FollowTheProcess authored Aug 26, 2024
1 parent d1ee9a8 commit 281df7e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
9 changes: 9 additions & 0 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ func AnyArgs() ArgValidator {
func NoArgs() ArgValidator {
return func(cmd *Command, args []string) error {
if len(args) > 0 {
if len(cmd.subcommands) > 0 {
// Maybe it's a typo of a subcommand
return fmt.Errorf(
"unknown subcommand %q for command %q, available subcommands: %v",
args[0],
cmd.name,
cmd.subcommandNames(),
)
}
return fmt.Errorf("command %s accepts no arguments but got %v", cmd.name, args)
}
return nil
Expand Down
21 changes: 21 additions & 0 deletions args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,27 @@ func TestArgValidators(t *testing.T) {
wantErr: true,
errMsg: "command test accepts no arguments but got [some args here]",
},
{
name: "noargs subcommand",
options: []cli.Option{
cli.Args([]string{"subb", "args", "here"}), // Note: subb is typo of sub
cli.Run(func(cmd *cli.Command, args []string) error {
fmt.Fprintln(cmd.Stdout(), "Hello from noargs")
return nil
}),
cli.Allow(cli.NoArgs()),
cli.SubCommands(
func() (*cli.Command, error) {
return cli.New(
"sub",
cli.Run(func(cmd *cli.Command, args []string) error { return nil }),
)
},
),
},
wantErr: true,
errMsg: `unknown subcommand "subb" for command "test", available subcommands: [sub]`,
},
{
name: "minargs pass",
options: []cli.Option{
Expand Down
9 changes: 9 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,15 @@ func (c *Command) hasShortFlag(name string) bool {
return flag.DefaultValueNoArg != ""
}

// subcommandNames returns a list of all the names of the current command's registered subcommands.
func (c *Command) subcommandNames() []string {
names := make([]string, 0, len(c.subcommands))
for _, sub := range c.subcommands {
names = append(names, sub.name)
}
return names
}

// findRequestedCommand uses the raw arguments and the command tree to determine what
// (if any) subcommand is being requested and return that command along with the arguments
// that were meant for it.
Expand Down

0 comments on commit 281df7e

Please sign in to comment.