Subcommands
Some applications, especially large ones, split their functionality
through the use of "subcommands". Each of these act somewhat like a separate
command, but is part of the larger group.
One example is git
, which has subcommands such as add
, commit
,
and clone
, to mention just a few.
clap
has this functionality, and structopt
supports it through enums:
# use structopt::StructOpt;
# use std::path::PathBuf;
#[derive(StructOpt)]
#[structopt(about = "the stupid content tracker")]
enum Git {
Add {
#[structopt(short)]
interactive: bool,
#[structopt(short)]
patch: bool,
#[structopt(parse(from_os_str))]
files: Vec<PathBuf>
},
Fetch {
#[structopt(long)]
dry_run: bool,
#[structopt(long)]
all: bool,
repository: Option<String>
},
Commit {
#[structopt(short)]
message: Option<String>,
#[structopt(short)]
all: bool
}
}
# fn main() {}
Using derive(StructOpt)
on an enum instead of a struct will produce
a clap::App
that only takes subcommands. So git add
, git fetch
,
and git commit
would be commands allowed for the above example.
structopt
also provides support for applications where certain flags
need to apply to all subcommands, as well as nested subcommands:
# use structopt::StructOpt;
# fn main() {}
#[derive(StructOpt)]
struct MakeCookie {
#[structopt(name = "supervisor", default_value = "Puck", long = "supervisor")]
supervising_faerie: String,
/// The faerie tree this cookie is being made in.
tree: Option<String>,
#[structopt(subcommand)] // Note that we mark a field as a subcommand
cmd: Command
}
#[derive(StructOpt)]
enum Command {
/// Pound acorns into flour for cookie dough.
Pound {
acorns: u32
},
/// Add magical sparkles -- the secret ingredient!
Sparkle {
#[structopt(short, parse(from_occurrences))]
magicality: u64,
#[structopt(short)]
color: String
},
Finish(Finish),
}
// Subcommand can also be externalized by using a 1-uple enum variant
#[derive(StructOpt)]
struct Finish {
#[structopt(short)]
time: u32,
#[structopt(subcommand)] // Note that we mark a field as a subcommand
finish_type: FinishType
}
// subsubcommand!
#[derive(StructOpt)]
enum FinishType {
Glaze {
applications: u32
},
Powder {
flavor: String,
dips: u32
}
}
Marking a field with structopt(subcommand)
will add the subcommands of the
designated enum to the current clap::App
. The designated enum must also
be derived StructOpt
. So the above example would take the following
commands:
make-cookie pound 50
make-cookie sparkle -mmm --color "green"
make-cookie finish 130 glaze 3