Feature: Allow to run default command without showing usage
- Dominant language
- Go
- Stars
- 795
- Forks
- 51
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
I found this tiny library that fits my needs much more than a bigger library which I wouldn't use more than 1%. So first of all, thanks for your great work.
I happened to find myself in a situation where I wanted a default command to be executed if no subcommand was provided. The easiest wat I found is to check that the `subcommands.Execute(context.Context)` func returned a `subcommands.ExitUsageError`.
This works well, except that it displays the list of all available commands due to this part of the code
```go
if cdr.topFlags.NArg() < 1 {
cdr.topFlags.Usage()
return ExitUsageError
}
```
What I need is a default command that does what it does, and subcommands that does other things too. If I have a default command, I dont want subcommands to prompt commands usage.
The main problems I found are
* I don't want this feature to impact people using subcommands
* I want to have a distinction between "No subcommand was provided" and "The subcommand provided does not exist"
An easy to implement solution that may impact user (but guarentee a differentiation between no subcommand and invalid subcommand) would be
```go
const (
ExitSuccess ExitStatus = iota
ExitFailure
ExitUsageError
ExitNoArgs
)
// MustShowUsageWhenNoArg when set to true (default) display command usage
// when no argument is set. This allows to execute a command by default if
// no argument is provided when calling the cli
var MustShowUsageWhenNoArg = true
func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStatus {
if cdr.topFlags.NArg() < 1 {
if MustShowUsageWhenNoArg {
cdr.topFlags.Usage()
}
return ExitNoArgs
}
// ...
}
```
These changes would allow to use subcommands like
```go
// disable default behavior
subcommands.MustShowUsageWhenNoArg = false
exitCode := subcommands.Execute(ctx)
if exitCode == subcommands.ExitNoArgs {
defaultCmd.Execute(ctx, flag.NewFlagSet(serverCmd.Name(), flag.ContinueOnError))
}
```
Another approach could be to store directly the command to execute in case no subcommand is set by the user
```go
// DefaultCommand is the command to execute by default if no subcommand was provided
var DefaultCommand Command
func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStatus {
if cdr.topFlags.NArg() < 1 {
if nil != DefaultCommand {
DefaultCommand.Execute(ctx, flag.NewFlagSet(DefaultCommand.Name(), flag.ContinueOnError), args...)
} else {
cdr.topFlags.Usage()
}
return ExitUsageError
}
// ...
}
```
This approach has the less impact on the already existing code using this lib.
The last option would be to check on my code the number of arguments provided. If none, I execute my command mannualy, otherwise, I let `subcommands.Execute` handle the input.
I may miss some subtilities of the subcommands library, so please let me know if there is a another way to delegate the "No args" case to a part of my code
Contributor guide
Assessment
This issue has not been assessed yet.