mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
eda0ca54c1
Clap has focused on reporting development errors through assertions rather than mixing user errors with development errors. Sometimes, developers need to handle things more flexibly so included in #3732 was the reporting of value accessor failures as internal errors with a distinct type. I've been going back and forth on whether the extra error pessimises the usability in the common case vs dealing with the proliferation of different function combinations. In working on deprecating the `value_of` functions, I decided that it was going to be worth duplicating so long as we can keep the documentation focused.
103 lines
3.5 KiB
Rust
103 lines
3.5 KiB
Rust
// Note: this requires the `cargo` feature
|
|
|
|
use std::ffi::OsString;
|
|
use std::path::PathBuf;
|
|
|
|
use clap::{arg, Command};
|
|
|
|
fn cli() -> Command<'static> {
|
|
Command::new("git")
|
|
.about("A fictional versioning CLI")
|
|
.subcommand_required(true)
|
|
.arg_required_else_help(true)
|
|
.allow_external_subcommands(true)
|
|
.allow_invalid_utf8_for_external_subcommands(true)
|
|
.subcommand(
|
|
Command::new("clone")
|
|
.about("Clones repos")
|
|
.arg(arg!(<REMOTE> "The remote to clone"))
|
|
.arg_required_else_help(true),
|
|
)
|
|
.subcommand(
|
|
Command::new("push")
|
|
.about("pushes things")
|
|
.arg(arg!(<REMOTE> "The remote to target"))
|
|
.arg_required_else_help(true),
|
|
)
|
|
.subcommand(
|
|
Command::new("add")
|
|
.about("adds things")
|
|
.arg_required_else_help(true)
|
|
.arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
|
|
)
|
|
.subcommand(
|
|
Command::new("stash")
|
|
.args_conflicts_with_subcommands(true)
|
|
.args(push_args())
|
|
.subcommand(Command::new("push").args(push_args()))
|
|
.subcommand(Command::new("pop").arg(arg!([STASH])))
|
|
.subcommand(Command::new("apply").arg(arg!([STASH]))),
|
|
)
|
|
}
|
|
|
|
fn push_args() -> Vec<clap::Arg<'static>> {
|
|
vec![arg!(-m --message <MESSAGE>).required(false)]
|
|
}
|
|
|
|
fn main() {
|
|
let matches = cli().get_matches();
|
|
|
|
match matches.subcommand() {
|
|
Some(("clone", sub_matches)) => {
|
|
println!(
|
|
"Cloning {}",
|
|
sub_matches.get_one::<String>("REMOTE").expect("required")
|
|
);
|
|
}
|
|
Some(("push", sub_matches)) => {
|
|
println!(
|
|
"Pushing to {}",
|
|
sub_matches.get_one::<String>("REMOTE").expect("required")
|
|
);
|
|
}
|
|
Some(("add", sub_matches)) => {
|
|
let paths = sub_matches
|
|
.get_many::<PathBuf>("PATH")
|
|
.into_iter()
|
|
.flatten()
|
|
.collect::<Vec<_>>();
|
|
println!("Adding {:?}", paths);
|
|
}
|
|
Some(("stash", sub_matches)) => {
|
|
let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches));
|
|
match stash_command {
|
|
("apply", sub_matches) => {
|
|
let stash = sub_matches.get_one::<String>("STASH");
|
|
println!("Applying {:?}", stash);
|
|
}
|
|
("pop", sub_matches) => {
|
|
let stash = sub_matches.get_one::<String>("STASH");
|
|
println!("Popping {:?}", stash);
|
|
}
|
|
("push", sub_matches) => {
|
|
let message = sub_matches.get_one::<String>("message");
|
|
println!("Pushing {:?}", message);
|
|
}
|
|
(name, _) => {
|
|
unreachable!("Unsupported subcommand `{}`", name)
|
|
}
|
|
}
|
|
}
|
|
Some((ext, sub_matches)) => {
|
|
let args = sub_matches
|
|
.get_many::<OsString>("")
|
|
.into_iter()
|
|
.flatten()
|
|
.collect::<Vec<_>>();
|
|
println!("Calling out to {:?} with {:?}", ext, args);
|
|
}
|
|
_ => unreachable!(), // If all subcommands are defined above, anything else is unreachabe!()
|
|
}
|
|
|
|
// Continued program logic goes here...
|
|
}
|