pacak / bpaf

Command line parser with applicative interface
Apache License 2.0
358 stars 21 forks source link

Repeated group help when sharing common args in an adjacent enum #369

Open ozwaldorf opened 4 months ago

ozwaldorf commented 4 months ago

Group help is not deduplicated when using an enum variants with adjacent args that share a common struct.

Example

use bpaf::Bpaf;

/// Example common args
#[derive(Bpaf, Clone, Debug)]
struct Common {
    /// Enable foo
    #[bpaf(short, long)]
    foo: bool,
    /// Enable bar
    #[bpaf(short, long)]
    bar: bool,
}

#[derive(Bpaf, Clone, Debug)]
#[bpaf(options)]
enum Args {
    #[bpaf(adjacent)]
    VariantOne {
        /// Use the first group
        #[bpaf(short('o'), long("one"), req_flag(()))]
        _one: (),
        #[bpaf(external)]
        common: Common,
        /// Enable baz
        #[bpaf(short('B'), long)]
        baz: bool,
    },
    #[bpaf(adjacent)]
    VariantTwo {
        /// Use the second group
        #[bpaf(short('t'), long("two"), req_flag(()))]
        _two: (),
        #[bpaf(external)]
        common: Common,
        /// Enable bau
        #[bpaf(short('B'), long)]
        bau: bool,
    },
}

fn main() {
    let _ = args().run();
}

Output

Usage: example (-o [-f] [-b] [-B] | -t [-f] [-b] [-B])

Example common args
    -f, --foo   Enable foo
    -b, --bar   Enable bar

Example common args
    -f, --foo   Enable foo
    -b, --bar   Enable bar

Available options:
  -o [-f] [-b] [-B]
    -o, --one   Use the first group
    -B, --baz   Enable baz

  -t [-f] [-b] [-B]
    -t, --two   Use the second group
    -B, --bau   Enable bau

    -h, --help  Prints help information
pacak commented 4 months ago

Yea, I'm still thinking about a better way to represent it. common args should probably be inlined inside adjacent groups, but this messes up the formatting. One way would be just to hide one of the groups...

        #[bpaf(external, hide)]
        common: Common,

Or rearrange the structure into something like (-o [-B] | -t [-B]) [-f] [b]

I think eventually I'll give more control to render things like that.

ozwaldorf commented 4 months ago

I think eventually I'll give more control to render things like that.

This would be amazing!


Unfortunately my usecase actually has 2 common structs, one of them that's used inside every variant, and another that's used in only 2 out of 4 variants, so rearranging like that isn't really possible as it would be unclear which ones don't use those args (and I would lose type safety around arg conflicts). The other option of hiding works but it might again be unclear that that adjacent group contains those arguments, which is crucial to my usecase since some variants don't use the shared args

I ended up not using group help at all, and just relied on the adjacent group summaries to show possible fields. I also ended up needing the default variant to work without a req_flag, which contains both structs. I made this variant non-adjacent to allow it to parse as the default without any of the specific flags needed, and it inlines the common args into the top level help, but still deduplicates the other adjacent helps, which is a nice compromise.

image

pacak commented 4 months ago

Nice seed.

I'll see what I can do about giving more control on rendering.

On Tue, Jul 2, 2024, 16:42 ozwaldorf @.***> wrote:

Unfortunately my usecase actually has 2 common structs, one of them that's used inside every variant, and another that's used in only 2 out of 4 variants, so rearranging like that isn't really possible as it would be unclear which ones don't use those args. The other option of hiding works but it might again be unclear that that adjacent group contains those arguments, which is crucial to my usecase since some variants don't use the shared args

I ended up not using group help at all, and just relied on the repetition to show possible fields. I also ended up needing the default variant to work without a req_flag, which contains both structs. I made this variant non-adjacent to allow it to parse as the default, and it inlines the common args into the top level help, but still deduplicates the other adjacent helps, which is a nice compromise.

image.png (view on web) https://github.com/pacak/bpaf/assets/8976745/dcb08524-c5a1-40ef-8a2c-9753deb42377

— Reply to this email directly, view it on GitHub https://github.com/pacak/bpaf/issues/369#issuecomment-2204377311, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAQFI2MZ5NDAV75AEFGDILZKMGBZAVCNFSM6AAAAABKIET6XWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBUGM3TOMZRGE . You are receiving this because you commented.Message ID: @.***>