-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set default subcommand via Derive API #3857
Comments
Why would that break backwards compatibility? Could you clarify how this is related to the default subcommands?
How come you say they would need to be What isn't quite clear is what the concerns are for users implementing this with the existing primitives we offer besides the extra boiler plate.
Ideally we add new major features like this at the Builder API level so everyone can take advantage of it. As we dig in, there might be some technical details that force us into it (like if we need any The challenge we run into is we are trying to focus on providing users building blocks rather than baking in everything to help with
If there are challenges with doing this with the building blocks or if this becomes important enough across our user base, we can re-evaluate native support for it. |
Ah, I didn't realize global had a specific meaning. Let me try again. Here's my understanding: Suppose we have my current implementation: #[derive(Parser)]
struct Args {
sub: Option<Commands>
}
#[derive(Parser)]
enum Commands {
Setup(ArgsSetup),
}
#[derive(Parser)]
struct ArgsSetup; When match args.sub {
Some(Commands::Setup(subargs)) => run_setup(subargs),
None => generate_code(args),
} I want to add an #[derive(Parser)]
struct Args {
#[clap(long)]
offline: bool
sub: Option<Commands>
}
#[derive(Parser)]
enum Commands {
Setup(ArgsSetup),
}
#[derive(Parser)]
struct ArgsSetup; Correct me if I'm wrong, but this would make Ideally, I would like it to look something like this: #[derive(Parser)]
struct Args {
#[clap(subcommand, default = "Code")]
sub: Commands
}
#[derive(Parser)]
enum Commands {
Setup(ArgsSetup),
Code(ArgsCode),
}
#[derive(Parser)]
struct ArgsSetup;
#[derive(Parser)]
struct ArgsCode {
#[clap(long)]
offline: bool
} This way, Regardless, the git-derive example you linked feels really unintuitive to me. I have no idea how to apply it to my situation. |
The derive documentation delegates to the builder documentation with this statement
The key parts
It sounds like doing similar what give you similar results #[derive(Parser)]
#[clap(args_conflicts_with_subcommands = true)]
struct Args {
#[clap(subcommand)]
sub: Option<Commands>,
#[clap(flatten)]
code: ArgsCode,
}
#[derive(Parser)]
enum Commands {
Setup(ArgsSetup),
Code(ArgsCode),
}
#[derive(Parser)]
struct ArgsSetup;
#[derive(Parser)]
struct ArgsCode {
#[clap(long)]
offline: bool
} |
That's a really good breakdown, thank you! I'm able to get the behavior I want. I still think having derive syntax for a default subcommand would be convenient and easier to work with. Purely as a nice to have though, not missing functionality. |
@epage what if some of the commands in For example if we try #[derive(Parser)]
struct Args {
#[clap(subcommand)]
sub: Option<Commands>,
#[clap(flatten)]
code: ArgsCode,
}
#[derive(Parser)]
enum Commands {
Setup(ArgsSetup),
Code(ArgsCode),
}
#[derive(Parser)]
struct ArgsSetup;
#[derive(Parser)]
struct ArgsCode {
#[clap(long)]
name: String,
} |
@gregdhill Your example would look like #[derive(Parser)]
#[clap(args_conflicts_with_subcommands = true)]
struct Args {
#[clap(subcommand)]
sub: Option<Commands>,
#[clap(flatten)]
code: ArgsCode,
}
#[derive(Parser)]
enum Commands {
Setup(ArgsSetup),
Code(ArgsCode),
}
#[derive(Parser)]
struct ArgsSetup;
#[derive(Parser)]
struct ArgsCode {
#[clap(long, required = true)]
name: Option<String>,
}
|
btw another discussion on default subcommands: #4134 |
I'm closing this because
If someone wants to continue the discussion to see if a solution aligns well enough with clap that we can merge it anyways, some points to consider
|
Please complete the following tasks
Clap Version
3.1.18
Describe your use case
I maintain steamguard-cli and I recently upgraded clap to v3, and switched over to the derive API. A feature of the program is that whenever you don't supply a subcommand, it generates a code.
My current solution is to have the subcommands be optional, like so:
https://github.com/dyc3/steamguard-cli/blob/2678961a4c938c153eac0b80b952999903d41861/src/cli.rs#L35-L49
This is OK, but I wanted to add an
--offline
flag that would only be valid when generating a code. This means I need a newCode
subcommand, but adding this in it's current form would break my backwards compatibility.Describe the solution you'd like
It's already possible to have a default subcommand, as shown in this example:
clap/examples/git.rs
Lines 32 to 39 in 731d18f
Alternatives, if applicable
Option<Subcommands>
makes it so that subcommands are optional altogether, but that means any arguments you need in theNone
case must become global arguments, which can get confusing for end users.Additional Context
No response
The text was updated successfully, but these errors were encountered: