Available on crate feature
unstable-doc
only.Expand description
Example: pacman-like CLI (Builder API)
use clap::{Arg, ArgAction, Command};
fn main() {
let matches = Command::new("pacman")
.about("package manager utility")
.version("5.2.1")
.subcommand_required(true)
.arg_required_else_help(true)
.author("Pacman Development Team")
// Query subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("query")
.short_flag('Q')
.long_flag("query")
.about("Query the package database.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.help("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.takes_value(true)
.multiple_values(true),
),
)
// Sync subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("sync")
.short_flag('S')
.long_flag("sync")
.about("Synchronize packages.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true)
.help("search remote repositories for matching strings"),
)
.arg(
Arg::new("info")
.long("info")
.conflicts_with("search")
.short('i')
.action(ArgAction::SetTrue)
.help("view package information"),
)
.arg(
Arg::new("package")
.help("packages")
.required_unless_present("search")
.takes_value(true)
.multiple_values(true),
),
)
.get_matches();
match matches.subcommand() {
Some(("sync", sync_matches)) => {
if sync_matches.contains_id("search") {
let packages: Vec<_> = sync_matches
.get_many::<String>("search")
.expect("contains_id")
.map(|s| s.as_str())
.collect();
let values = packages.join(", ");
println!("Searching for {}...", values);
return;
}
let packages: Vec<_> = sync_matches
.get_many::<String>("package")
.expect("is present")
.map(|s| s.as_str())
.collect();
let values = packages.join(", ");
if *sync_matches
.get_one::<bool>("info")
.expect("defaulted by clap")
{
println!("Retrieving info for {}...", values);
} else {
println!("Installing {}...", values);
}
}
Some(("query", query_matches)) => {
if let Some(packages) = query_matches.get_many::<String>("info") {
let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
println!("Retrieving info for {}...", comma_sep);
} else if let Some(queries) = query_matches.get_many::<String>("search") {
let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
println!("Searching Locally for {}...", comma_sep);
} else {
println!("Displaying all locally installed packages...");
}
}
_ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
}
}
pacman
defines subcommands via flags.
Here, -S
is a short flag subcommand:
$ pacman -S package
Installing package...
Here --sync
is a long flag subcommand:
$ pacman --sync package
Installing package...
Now the short flag subcommand (-S
) with a long flag:
$ pacman -S --search name
Searching for name...
And the various forms of short flags that work:
$ pacman -S -s name
Searching for name...
$ pacman -Ss name
Searching for name...
(users can “stack” short subcommands with short flags or with other short flag subcommands)
In the help, this looks like:
$ pacman -h
pacman 5.2.1
Pacman Development Team
package manager utility
USAGE:
pacman[EXE] <SUBCOMMAND>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
query -Q --query Query the package database.
sync -S --sync Synchronize packages.
$ pacman -S -h
pacman[EXE]-sync
Synchronize packages.
USAGE:
pacman[EXE] {sync|--sync|-S} [OPTIONS] [--] [package]...
ARGS:
<package>... packages
OPTIONS:
-h, --help Print help information
-i, --info view package information
-s, --search <search>... search remote repositories for matching strings
And errors:
$ pacman -S -s foo -i bar
? failed
error: The argument '--search <search>...' cannot be used with '--info'
USAGE:
pacman[EXE] {sync|--sync|-S} --search <search>... <package>...
For more information try --help
NOTE: Keep in mind that subcommands, flags, and long flags are case sensitive: -Q
and -q
are different flags/subcommands. For example, you can have both -Q
subcommand and -q
flag, and they will be properly disambiguated.
Let’s make a quick program to illustrate.