-
-
Notifications
You must be signed in to change notification settings - Fork 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
Better than display_order and DeriveDisplayOrder argument positioning #1807
Comments
This might be pretty hairy to implement, especially if we end up trying to detect loops ( I'm leaning towards closing this feature, as it'd significantly impact the code used to generate help messages for (my subjectively) little benefit. @I60R could you elaborate on why doesn't |
Okay, I understand.
I actually use it. The problem was that it don't play well with
|
Aaah ok, I understand. Yeah to me that sounds like either a feature/bug we could work on as part of I'm open to others opinions as well, but even when flattening the order should be preserved. That sounds like a new issue to me, or perhaps we re-name this issue and update the OP with this new constraint/requirement. |
@I60R Could you provide us a sample code where it doesn't work? AFAIK, even flattening should make it work. |
Done. I also think that I've found what argument positioning I want:
display_all = &[
("FLAGS", &[
"first",
"second",
"x",
...
]),
("OPTIONS", &[
"nth",
"nth+1",
...
]),
...,
("CUSTOM SECTION", &[
...,
"last-1",
"last"
])
], it could substitute @kbknapp is it possible to be implemented? |
We have them.
You are not exactly giving us a sample of the code where |
The whole point isn't in having them, but in having them in the same place and not using them explicitly.
That's actually the problem e.g. if you have this unflattened struct: #[derive(StructOpt)]
#[structopt(global_settings=&[DeriveDisplayOrder])]
struct Opt {
a: bool,
b: bool,
c: bool,
...
} and then refactors it to flattened #[derive(StructOpt)]
#[structopt(global_settings=&[DeriveDisplayOrder])]
struct Opt {
b: bool,
#[structopt(flatten)]
flattened: Flattened,
...
}
#[derive(StructOpt)]
struct Flattened {
a: bool,
c: bool,
} you may find that the original order is messed up (b-a-c) and there's no straightforward way to fix it |
Yes, that can be implemented. |
This is already done. We detect defaults and don't override them. The only thing remaining is what the starting display order should be when deriving. |
Now that we use options, we can rely on that, instead of sentinels, for detecting a default and overriding only a default. Noticed this as part of looking at clap-rs#1807.
So the crux of the issue is that if the struct hierarchy doesn't match your visual hierarchy, you have to manually specify all of the display orders. I was wondering if we could do something like |
I think the case for that would be pretty niche. I think people would just find it easy to reorder the struct. |
If we feel its niche enough, is there anything left to do for this issue? |
I think that. Unless another issue covers that? I will leave it up to you. |
- ArgSettings are part of clap-rs#2717 - Errors are part of clap-rs#2628 - `help_heading` is part of clap-rs#1807 and clap-rs#1553 - Some misc parts are for API consistency
- ArgSettings are part of clap-rs#2717 - Errors are part of clap-rs#2628 - `help_heading` is part of clap-rs#1807 and clap-rs#1553 - Some misc parts are for API consistency
Huh, so derive helper attributes can only be identifiers. Item paths seem to be used for attribute macros. |
Context: Clap has context-specific builder functions. let cmd = Command::new("blorp")
.author("Will M.")
.about("does stuff")
.version("1.4")
.arg(
arg!(-f --fake "some help")
.required(true)
.value_names(&["some", "val"])
.takes_value(true)
.use_value_delimiter(true)
.require_value_delimiter(true)
.value_delimiter(':'),
)
.next_help_heading(Some("NETWORKING"))
.arg(
Arg::new("no-proxy")
.short('n')
.long("no-proxy")
.help("Do not use system proxy settings"),
)
.args(&[Arg::new("port").long("port")]); Problem: this is not currently exposed in the derive API. #[derive(Debug, Clone, Parser)]
struct CliOptions {
#[clap(flatten)]
options_a: OptionsA,
}
#[derive(Debug, Clone, Args)]
#[clap(next_help_heading = "HEADING A")]
struct OptionsA {
#[clap(long)]
should_be_in_section_a: u32,
} How do we support context-specific builder methods like this without forcing a Possible solutions: Key off of the inner-attribute name and call switch which we can from that (if attr inner name is Have the user explicitly state what the attribute is for. I feel like this would also make what is happening clearer. How does the user specify which kind of attribute it is? Some ideas include:
Per-use outer-attributes
I'm leaning towards inner-attribute namespaces |
As for |
To clarify, we already do what serde does. Note the example is |
We aren't enumerating arguments but values for an argument, so the name should reflect that. This will be important as part of clap-rs#1807 when we have more specific attribute names.
We aren't enumerating arguments but values for an argument, so the name should reflect that. This will be important as part of clap-rs#1807 when we have more specific attribute names.
We aren't enumerating arguments but values for an argument, so the name should reflect that. This will be important as part of clap-rs#1807 when we have more specific attribute names.
We aren't enumerating arguments but values for an argument, so the name should reflect that. This will be important as part of clap-rs#1807 when we have more specific attribute names.
#4180 renames the attributes: /// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Name of the person to greet
#[arg(short, long)]
name: String,
/// Number of times to greet
#[arg(short, long, default_value_t = 1)]
count: u8,
} My original plan was to support: /// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Name of the person to greet
#[command(next_help_heading = "Foo")]
#[arg(short, long)]
name: String,
/// Number of times to greet
#[command(next_help_heading = "Bar")]
#[arg(short, long, default_value_t = 1)]
count: u8,
} but alternatively we could do something like /// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[command(next_help_heading = "Foo")]
_foo: (),
/// Name of the person to greet
#[arg(short, long)]
name: String,
/// Number of times to greet
#[command(next_help_heading = "Bar")]
_bar: (),
#[arg(short, long, default_value_t = 1)]
count: u8,
}
Thoughts? |
In planning this, I forgot about #1553 which has |
Another problem I ran into with this is that |
To recap Ideally, we would like to support use of at least I had made the
Problems
One alternative I had considered is just special casing
Out-there ideas
@pksunkara and anyone else, I'd appreciate input on this. |
I don't think any of the proposed options require breaking changes beyond what is already merged, so going to push this out of 4.0.0. |
Originally, I saw the ideal as the parent command being isolated from `#[clap(flatte)]` especially after all of the doc comment leakage issues. We scaled that back to just `next_help_heading` because of the issues with settling on a policy and maintenance to cover everything. When doing `next_display_order`, we decided it would mess things up too much to isolate it. With clap-rs#1807, we instead have been moving towards setting `#[command(next_help_heading)]` anywhere, we just need to finish working out how it should work.
Make sure you completed the following tasks
Describe your use case
The same as for
Arg::display_order(usize)
andDeriveDisplayOrder
but should be easier to applyDescribe the solution you'd like
structopt
/clap_derive
flattening.display_order
(because 999 is default for every argument).DeriveDisplayOrder
shouldn't override itAlternatives, if applicable
Keep using
Arg::display_order(usize)
andDeriveDisplayOrder
Additional context
The text was updated successfully, but these errors were encountered: