I have the following setup:
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
struct CliArgs {
#[structopt(short, long)]
aisle: Option<String>,
#[structopt(short, long)]
shelf: Option<String>,
#[structopt(subcommand)]
operation: Option<Ops>,
}
#[derive(Debug, StructOpt)]
enum Ops {
Add {
isbn: Option<String>,
pin: Option<String>
},
Remove {
isbn: Option<String>,
},
Status,
}
In this scenario, I'd like a condition where either aisle
and shelf
are together specified or isbn
alone is specified. I found both raw clap methods required_unless
and conflicts_with
, and their variants required_unless_all
and conflicts_with_all
together could be of use.
Maybe using them like such:
...
#[structopt(short, long, required_unless = "isbn", conflicts_with = "isbn")]
aisle: Option<String>,
#[structopt(short, long, required_unless = "isbn", conflicts_with = "isbn")]
shelf: Option<String>,
...
and
...
Add {
#[structopt(required_unless_all = &["aisle", "shelf"], conflicts_with_all = &["aisle", "shelf"])]
isbn: Option<String>,
pin: Option<String>
}
...
But it results in the following
~❯ RUST_BACKTRACE=full cargo run -q -- --aisle A1 --shelf X3 add 2441
error: The following required arguments were not provided:
<pin>
Which is right because passed pin is used as isbn
instead.
~❯ RUST_BACKTRACE=full cargo run -q -- add A1/X3 2441
error: The following required arguments were not provided:
--aisle <aisle>
--shelf <shelf>
~❯ RUST_BACKTRACE=full cargo run -q -- --aisle B1 --shelf Y3 add A1/X3 2441
<It works>
~❯ RUST_BACKTRACE=full cargo run -q -- add
error: The following required arguments were not provided:
<isbn>
<pin>
Which doesn't work for obvious reasons. I think the main issue with my problem is that the fields can't reference each other if put under a sub-command. Am I doing something wrong with the current approach? Would there be a better alternative to clap::arg methods in this case? Or is there a way of communicating between sub-commands?