Skip to content
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

Allow Nested Subcommands #1

Closed
NWPlayer123 opened this issue Jul 14, 2023 · 2 comments
Closed

Allow Nested Subcommands #1

NWPlayer123 opened this issue Jul 14, 2023 · 2 comments

Comments

@NWPlayer123
Copy link

I'm trying to port my code from clap, where I have a secondarily nested subcommand, but it seems like argh and argp (and gumdrop) are unable to do this. Here's the error, it seems to not like multiple enums that point to subcommands.

error[E0277]: the trait bound `MySecondSubCommandEnum: SubCommand` is not satisfied
  --> src\main.rs:18:10
   |
18 | #[derive(FromArgs, PartialEq, Debug)]
   |          ^^^^^^^^ the trait `SubCommand` is not implemented for `MySecondSubCommandEnum`
   |
   = help: the following other types implement trait `SubCommand`:
             SubCommandOne
             SubCommandTwo
   = note: this error originates in the derive macro `FromArgs` (in Nightly builds, run with -Z macro-backtrace for more info)

Here's a simple modified example from the docs, basically I want the base subcommand enum to be able to point to other subcommand enums.

use argp::FromArgs;

/// Top-level command.
#[derive(FromArgs, PartialEq, Debug)]
struct TopLevel {
    /// Be verbose.
    #[argp(switch, short = 'v', global)]
    verbose: bool,

    /// Run locally.
    #[argp(switch)]
    quiet: bool,

    #[argp(subcommand)]
    nested: MySubCommandEnum,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum MySubCommandEnum {
    One(SubCommandOne),
    Two(MySecondSubCommandEnum),
}

#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum MySecondSubCommandEnum {
    Two(SubCommandTwo),
}

/// First subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "one")]
struct SubCommandOne {
    /// How many x.
    #[argp(option)]
    x: usize,
}

/// Second subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "two")]
struct SubCommandTwo {
    /// Whether to fooey.
    #[argp(switch)]
    fooey: bool,
}

fn main() {
    let args: TopLevel = argp::parse_args_or_exit(argp::DEFAULT);
    println!("{:#?}", args);
}
@jirutka
Copy link
Owner

jirutka commented Jul 16, 2023

You just need to use an intermediate struct with #[argp(subcommand)]:

use argp::FromArgs;

/// Top-level command.
#[derive(FromArgs, PartialEq, Debug)]
struct TopLevel {
    /// Be verbose.
    #[argp(switch, short = 'v', global)]
    verbose: bool,

    /// Run locally.
    #[argp(switch)]
    quiet: bool,

    #[argp(subcommand)]
    nested: MySubCommandEnum,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum MySubCommandEnum {
    One(SubCommandOne),
    Two(SubCommandTwo),
}

/// First subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "one")]
struct SubCommandOne {
    /// How many x.
    #[argp(option)]
    x: usize,
}

/// Second subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "two")]
struct SubCommandTwo {
    #[argp(subcommand)]
    nested: MySecondSubCommandEnum,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum MySecondSubCommandEnum {
    Three(SubCommandThree),
}

/// Nested subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "three")]
struct SubCommandThree {
    /// Whether to fooey.
    #[argp(switch)]
    fooey: bool,
}

fn main() {
    let args: TopLevel = argp::parse_args_or_exit(argp::DEFAULT);
    println!("{:#?}", args);
}
$ ./nested_subcommands --help
Usage: nested_subcommands [-v] [--quiet] <command> [<args>]

Top-level command.

Options:
  -v, --verbose  Be verbose.
      --quiet    Run locally.
  -h, --help     Show this help message and exit.

Commands:
  one            First subcommand.
  two            Second subcommand.

$ ./nested_subcommands two --help
Usage: nested_subcommands two [-v] <command> [<args>]

Second subcommand.

Options:
  -v, --verbose  Be verbose.
  -h, --help     Show this help message and exit.

Commands:
  three          Nested subcommand.

$ ./nested_subcommands two three --help
Usage: nested_subcommands two three [-v] [--fooey]

Nested subcommand.

Options:
  -v, --verbose  Be verbose.
      --fooey    Whether to fooey.
  -h, --help     Show this help message and exit.

@NWPlayer123
Copy link
Author

I figured I had to be missing something. Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants