pub struct Command { /* private fields */ }
Expand description
Build a command-line interface.
This includes defining arguments, subcommands, parser behavior, and help output.
Once all configuration is complete,
the Command::get_matches
family of methods starts the runtime-parsing
process. These methods then return information about the user supplied
arguments (or lack thereof).
When deriving a Parser
, you can use
CommandFactory::command
to access the
Command
.
- Basic API
- Application-wide Settings
- Command-specific Settings
- Subcommand-specific Settings
- Reflection
Examples
let m = Command::new("My Program")
.author("Me, me@mail.com")
.version("1.0.2")
.about("Explains in brief what the program does")
.arg(
Arg::new("in_file")
)
.after_help("Longer explanation to appear after the options when \
displaying the help information from --help or -h")
.get_matches();
// Your program logic starts here...
Implementations§
source§impl Command
impl Command
sourcepub fn new(name: impl Into<Str>) -> Self
pub fn new(name: impl Into<Str>) -> Self
Creates a new instance of an Command
.
It is common, but not required, to use binary name as the name
. This
name will only be displayed to the user when they request to print
version or help and usage information.
See also command!
and crate_name!
.
Examples
Command::new("My Program")
Examples found in repository?
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn applet_commands() -> [Command; 2] {
[
Command::new("true").about("does nothing successfully"),
Command::new("false").about("does nothing unsuccessfully"),
]
}
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
More examples
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
sourcepub fn arg(self, a: impl Into<Arg>) -> Self
pub fn arg(self, a: impl Into<Arg>) -> Self
Adds an argument to the list of valid possibilities.
Examples
Command::new("myprog")
// Adding a single "flag" argument with a short and help text, using Arg::new()
.arg(
Arg::new("debug")
.short('d')
.help("turns on debugging mode")
)
// Adding a single "option" argument with a short, a long, and help text using the less
// verbose Arg::from()
.arg(
arg!(-c --config <CONFIG> "Optionally sets a config file to use")
)
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}
More examples
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
fn augment_args(cmd: Command) -> Command {
cmd.arg(
Arg::new("foo")
.short('f')
.long("foo")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("bar")
.short('b')
.long("bar")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("quuz")
.short('q')
.long("quuz")
.action(ArgAction::Set),
)
}
fn augment_args_for_update(cmd: Command) -> Command {
cmd.arg(
Arg::new("foo")
.short('f')
.long("foo")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("bar")
.short('b')
.long("bar")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("quuz")
.short('q')
.long("quuz")
.action(ArgAction::Set),
)
}
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
fn main() {
let cli = Command::new("CLI").arg(arg!(-b - -built).action(clap::ArgAction::SetTrue));
// Augment built args with derived args
let cli = DerivedArgs::augment_args(cli);
let matches = cli.get_matches();
println!("Value of built: {:?}", matches.get_flag("built"));
println!(
"Value of derived via ArgMatches: {:?}",
matches.get_flag("derived")
);
// Since DerivedArgs implements FromArgMatches, we can extract it from the unstructured ArgMatches.
// This is the main benefit of using derived arguments.
let derived_matches = DerivedArgs::from_arg_matches(&matches)
.map_err(|err| err.exit())
.unwrap();
println!("Value of derived: {:#?}", derived_matches);
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
sourcepub fn args(self, args: impl IntoIterator<Item = impl Into<Arg>>) -> Self
pub fn args(self, args: impl IntoIterator<Item = impl Into<Arg>>) -> Self
Adds multiple arguments to the list of valid possibilities.
Examples
Command::new("myprog")
.args([
arg!("[debug] -d 'turns on debugging info'"),
Arg::new("input").help("the input file to use")
])
Examples found in repository?
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
sourcepub fn mut_arg<F>(self, arg_id: impl AsRef<str>, f: F) -> Selfwhere
F: FnOnce(Arg) -> Arg,
pub fn mut_arg<F>(self, arg_id: impl AsRef<str>, f: F) -> Selfwhere
F: FnOnce(Arg) -> Arg,
Allows one to mutate an Arg
after it’s been added to a Command
.
This can be useful for modifying the auto-generated help or version arguments.
Panics
If the argument is undefined
Examples
let mut cmd = Command::new("foo")
.arg(Arg::new("bar")
.short('b')
.action(ArgAction::SetTrue))
.mut_arg("bar", |a| a.short('B'));
let res = cmd.try_get_matches_from_mut(vec!["foo", "-b"]);
// Since we changed `bar`'s short to "B" this should err as there
// is no `-b` anymore, only `-B`
assert!(res.is_err());
let res = cmd.try_get_matches_from_mut(vec!["foo", "-B"]);
assert!(res.is_ok());
sourcepub fn mut_subcommand<F>(self, name: impl AsRef<str>, f: F) -> Selfwhere
F: FnOnce(Self) -> Self,
pub fn mut_subcommand<F>(self, name: impl AsRef<str>, f: F) -> Selfwhere
F: FnOnce(Self) -> Self,
Allows one to mutate a Command
after it’s been added as a subcommand.
This can be useful for modifying auto-generated arguments of nested subcommands with
Command::mut_arg
.
Panics
If the subcommand is undefined
Examples
let mut cmd = Command::new("foo")
.subcommand(Command::new("bar"))
.mut_subcommand("bar", |subcmd| subcmd.disable_help_flag(true));
let res = cmd.try_get_matches_from_mut(vec!["foo", "bar", "--help"]);
// Since we disabled the help flag on the "bar" subcommand, this should err.
assert!(res.is_err());
let res = cmd.try_get_matches_from_mut(vec!["foo", "bar"]);
assert!(res.is_ok());
sourcepub fn group(self, group: impl Into<ArgGroup>) -> Self
pub fn group(self, group: impl Into<ArgGroup>) -> Self
Adds an ArgGroup
to the application.
ArgGroup
s are a family of related arguments.
By placing them in a logical group, you can build easier requirement and exclusion rules.
Example use cases:
- Make an entire
ArgGroup
required, meaning that one (and only one) argument from that group must be present at runtime. - Name an
ArgGroup
as a conflict to another argument. Meaning any of the arguments that belong to that group will cause a failure if present with the conflicting argument. - Ensure exclusion between arguments.
- Extract a value from a group instead of determining exactly which argument was used.
Examples
The following example demonstrates using an ArgGroup
to ensure that one, and only one,
of the arguments from the specified group is present at runtime.
Command::new("cmd")
.arg(arg!("--set-ver [ver] 'set the version manually'"))
.arg(arg!("--major 'auto increase major'"))
.arg(arg!("--minor 'auto increase minor'"))
.arg(arg!("--patch 'auto increase patch'"))
.group(ArgGroup::new("vers")
.args(["set-ver", "major", "minor","patch"])
.required(true))
sourcepub fn groups(
self,
groups: impl IntoIterator<Item = impl Into<ArgGroup>>
) -> Self
pub fn groups(
self,
groups: impl IntoIterator<Item = impl Into<ArgGroup>>
) -> Self
Adds multiple ArgGroup
s to the Command
at once.
Examples
Command::new("cmd")
.arg(arg!("--set-ver [ver] 'set the version manually'"))
.arg(arg!("--major 'auto increase major'"))
.arg(arg!("--minor 'auto increase minor'"))
.arg(arg!("--patch 'auto increase patch'"))
.arg(arg!("-c [FILE] 'a config file'"))
.arg(arg!("-i [IFACE] 'an interface'"))
.groups([
ArgGroup::new("vers")
.args(["set-ver", "major", "minor","patch"])
.required(true),
ArgGroup::new("input")
.args(["c", "i"])
])
sourcepub fn subcommand(self, subcmd: impl Into<Command>) -> Self
pub fn subcommand(self, subcmd: impl Into<Command>) -> Self
Adds a subcommand to the list of valid possibilities.
Subcommands are effectively sub-Command
s, because they can contain their own arguments,
subcommands, version, usage, etc. They also function just like Command
s, in that they get
their own auto generated help, version, and usage.
A subcommand’s Command::name
will be used for:
- The argument the user passes in
- Programmatically looking up the subcommand
Examples
Command::new("myprog")
.subcommand(Command::new("config")
.about("Controls configuration features")
.arg(arg!("<config> 'Required configuration file to use'")))
Examples found in repository?
More examples
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
sourcepub fn subcommands(
self,
subcmds: impl IntoIterator<Item = impl Into<Self>>
) -> Self
pub fn subcommands(
self,
subcmds: impl IntoIterator<Item = impl Into<Self>>
) -> Self
Adds multiple subcommands to the list of valid possibilities.
Examples
.subcommands( [
Command::new("config").about("Controls configuration functionality")
.arg(Arg::new("config_file")),
Command::new("debug").about("Controls debug functionality")])
Examples found in repository?
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
sourcepub fn debug_assert(self)
pub fn debug_assert(self)
Catch problems earlier in the development cycle.
Most error states are handled as asserts under the assumption they are programming mistake and not something to handle at runtime. Rather than relying on tests (manual or automated) that exhaustively test your CLI to ensure the asserts are evaluated, this will run those asserts in a way convenient for running as a test.
Note:: This will not help with asserts in ArgMatches
, those will need exhaustive
testing of your CLI.
Examples
fn cmd() -> Command {
Command::new("foo")
.arg(
Arg::new("bar").short('b').action(ArgAction::SetTrue)
)
}
#[test]
fn verify_app() {
cmd().debug_assert();
}
fn main() {
let m = cmd().get_matches_from(vec!["foo", "-b"]);
println!("{}", *m.get_one::<bool>("bar").expect("defaulted by clap"));
}
sourcepub fn error(&mut self, kind: ErrorKind, message: impl Display) -> Error
pub fn error(&mut self, kind: ErrorKind, message: impl Display) -> Error
Custom error message for post-parsing validation
Examples
let mut cmd = Command::new("myprog");
let err = cmd.error(ErrorKind::InvalidValue, "Some failure case");
Examples found in repository?
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
fn main() {
let cli = Cli::parse();
// Let's assume the old version 1.2.3
let mut major = 1;
let mut minor = 2;
let mut patch = 3;
// See if --set-ver was used to set the version manually
let version = if let Some(ver) = cli.set_ver.as_deref() {
if cli.major || cli.minor || cli.patch {
let mut cmd = Cli::command();
cmd.error(
ErrorKind::ArgumentConflict,
"Can't do relative and absolute version change",
)
.exit();
}
ver.to_string()
} else {
// Increment the one requested (in a real program, we'd reset the lower numbers)
let (maj, min, pat) = (cli.major, cli.minor, cli.patch);
match (maj, min, pat) {
(true, false, false) => major += 1,
(false, true, false) => minor += 1,
(false, false, true) => patch += 1,
_ => {
let mut cmd = Cli::command();
cmd.error(
ErrorKind::ArgumentConflict,
"Can only modify one version field",
)
.exit();
}
};
format!("{}.{}.{}", major, minor, patch)
};
println!("Version: {}", version);
// Check for usage of -c
if let Some(config) = cli.config.as_deref() {
let input = cli
.input_file
.as_deref()
// 'or' is preferred to 'or_else' here since `Option::as_deref` is 'const'
.or(cli.spec_in.as_deref())
.unwrap_or_else(|| {
let mut cmd = Cli::command();
cmd.error(
ErrorKind::MissingRequiredArgument,
"INPUT_FILE or --spec-in is required when using --config",
)
.exit()
});
println!("Doing work using input {} and config {}", input, config);
}
}
sourcepub fn get_matches(self) -> ArgMatches
pub fn get_matches(self) -> ArgMatches
Parse env::args_os
, exiting on failure.
Panics
If contradictory arguments or settings exist.
Examples
let matches = Command::new("myprog")
// Args and options go here...
.get_matches();
Examples found in repository?
More examples
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
fn main() {
let cli = Command::new("CLI").arg(arg!(-b - -built).action(clap::ArgAction::SetTrue));
// Augment built args with derived args
let cli = DerivedArgs::augment_args(cli);
let matches = cli.get_matches();
println!("Value of built: {:?}", matches.get_flag("built"));
println!(
"Value of derived via ArgMatches: {:?}",
matches.get_flag("derived")
);
// Since DerivedArgs implements FromArgMatches, we can extract it from the unstructured ArgMatches.
// This is the main benefit of using derived arguments.
let derived_matches = DerivedArgs::from_arg_matches(&matches)
.map_err(|err| err.exit())
.unwrap();
println!("Value of derived: {:#?}", derived_matches);
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
sourcepub fn get_matches_mut(&mut self) -> ArgMatches
pub fn get_matches_mut(&mut self) -> ArgMatches
Parse env::args_os
, exiting on failure.
Like Command::get_matches
but doesn’t consume the Command
.
Panics
If contradictory arguments or settings exist.
Examples
let mut cmd = Command::new("myprog")
// Args and options go here...
;
let matches = cmd.get_matches_mut();
sourcepub fn try_get_matches(self) -> ClapResult<ArgMatches>
pub fn try_get_matches(self) -> ClapResult<ArgMatches>
Parse env::args_os
, returning a clap::Result
on failure.
NOTE: This method WILL NOT exit when --help
or --version
(or short versions) are
used. It will return a clap::Error
, where the kind
is a
ErrorKind::DisplayHelp
or ErrorKind::DisplayVersion
respectively. You must call
Error::exit
or perform a std::process::exit
.
Panics
If contradictory arguments or settings exist.
Examples
let matches = Command::new("myprog")
// Args and options go here...
.try_get_matches()
.unwrap_or_else(|e| e.exit());
sourcepub fn get_matches_from<I, T>(self, itr: I) -> ArgMatcheswhere
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
pub fn get_matches_from<I, T>(self, itr: I) -> ArgMatcheswhere
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
Parse the specified arguments, exiting on failure.
NOTE: The first argument will be parsed as the binary name unless
Command::no_binary_name
is used.
Panics
If contradictory arguments or settings exist.
Examples
let arg_vec = vec!["my_prog", "some", "args", "to", "parse"];
let matches = Command::new("myprog")
// Args and options go here...
.get_matches_from(arg_vec);
sourcepub fn try_get_matches_from<I, T>(self, itr: I) -> ClapResult<ArgMatches>where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
pub fn try_get_matches_from<I, T>(self, itr: I) -> ClapResult<ArgMatches>where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
Parse the specified arguments, returning a clap::Result
on failure.
NOTE: This method WILL NOT exit when --help
or --version
(or short versions) are
used. It will return a clap::Error
, where the kind
is a ErrorKind::DisplayHelp
or ErrorKind::DisplayVersion
respectively. You must call Error::exit
or
perform a std::process::exit
yourself.
NOTE: The first argument will be parsed as the binary name unless
Command::no_binary_name
is used.
Panics
If contradictory arguments or settings exist.
Examples
let arg_vec = vec!["my_prog", "some", "args", "to", "parse"];
let matches = Command::new("myprog")
// Args and options go here...
.try_get_matches_from(arg_vec)
.unwrap_or_else(|e| e.exit());
Examples found in repository?
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
fn respond(line: &str) -> Result<bool, String> {
let args = shlex::split(line).ok_or("error: Invalid quoting")?;
let matches = cli()
.try_get_matches_from(&args)
.map_err(|e| e.to_string())?;
match matches.subcommand() {
Some(("ping", _matches)) => {
write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
}
Some(("quit", _matches)) => {
write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
return Ok(true);
}
Some((name, _matches)) => unimplemented!("{}", name),
None => unreachable!("subcommand required"),
}
Ok(false)
}
sourcepub fn try_get_matches_from_mut<I, T>(
&mut self,
itr: I
) -> ClapResult<ArgMatches>where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
pub fn try_get_matches_from_mut<I, T>(
&mut self,
itr: I
) -> ClapResult<ArgMatches>where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
Parse the specified arguments, returning a clap::Result
on failure.
Like Command::try_get_matches_from
but doesn’t consume the Command
.
NOTE: This method WILL NOT exit when --help
or --version
(or short versions) are
used. It will return a clap::Error
, where the kind
is a ErrorKind::DisplayHelp
or ErrorKind::DisplayVersion
respectively. You must call Error::exit
or
perform a std::process::exit
yourself.
NOTE: The first argument will be parsed as the binary name unless
Command::no_binary_name
is used.
Panics
If contradictory arguments or settings exist.
Examples
let arg_vec = vec!["my_prog", "some", "args", "to", "parse"];
let mut cmd = Command::new("myprog");
// Args and options go here...
let matches = cmd.try_get_matches_from_mut(arg_vec)
.unwrap_or_else(|e| e.exit());
sourcepub fn print_help(&mut self) -> Result<()>
pub fn print_help(&mut self) -> Result<()>
Prints the short help message (-h
) to io::stdout()
.
See also Command::print_long_help
.
Examples
let mut cmd = Command::new("myprog");
cmd.print_help();
sourcepub fn print_long_help(&mut self) -> Result<()>
pub fn print_long_help(&mut self) -> Result<()>
Prints the long help message (--help
) to io::stdout()
.
See also Command::print_help
.
Examples
let mut cmd = Command::new("myprog");
cmd.print_long_help();
sourcepub fn render_help(&mut self) -> StyledStr
pub fn render_help(&mut self) -> StyledStr
Render the short help message (-h
) to a StyledStr
See also Command::render_long_help
.
Examples
use std::io;
let mut cmd = Command::new("myprog");
let mut out = io::stdout();
let help = cmd.render_help();
println!("{}", help);
sourcepub fn render_long_help(&mut self) -> StyledStr
pub fn render_long_help(&mut self) -> StyledStr
Render the long help message (--help
) to a StyledStr
.
See also Command::render_help
.
Examples
use std::io;
let mut cmd = Command::new("myprog");
let mut out = io::stdout();
let help = cmd.render_long_help();
println!("{}", help);
sourcepub fn render_version(&self) -> String
pub fn render_version(&self) -> String
Version message rendered as if the user ran -V
.
See also Command::render_long_version
.
Coloring
This function does not try to color the message nor it inserts any ANSI escape codes.
Examples
use std::io;
let cmd = Command::new("myprog");
println!("{}", cmd.render_version());
sourcepub fn render_long_version(&self) -> String
pub fn render_long_version(&self) -> String
Version message rendered as if the user ran --version
.
See also Command::render_version
.
Coloring
This function does not try to color the message nor it inserts any ANSI escape codes.
Examples
use std::io;
let cmd = Command::new("myprog");
println!("{}", cmd.render_long_version());
sourcepub fn render_usage(&mut self) -> StyledStr
pub fn render_usage(&mut self) -> StyledStr
Usage statement
Examples
use std::io;
let mut cmd = Command::new("myprog");
println!("{}", cmd.render_usage());
source§impl Command
impl Command
Application-wide Settings
These settings will apply to the top-level command and all subcommands, by default. Some settings can be overridden in subcommands.
sourcepub fn no_binary_name(self, yes: bool) -> Self
pub fn no_binary_name(self, yes: bool) -> Self
Specifies that the parser should not assume the first argument passed is the binary name.
This is normally the case when using a “daemon” style mode. For shells / REPLs, see
Command::multicall
.
Examples
let m = Command::new("myprog")
.no_binary_name(true)
.arg(arg!(<cmd> ... "commands to run"))
.get_matches_from(vec!["command", "set"]);
let cmds: Vec<_> = m.get_many::<String>("cmd").unwrap().collect();
assert_eq!(cmds, ["command", "set"]);
sourcepub fn ignore_errors(self, yes: bool) -> Self
pub fn ignore_errors(self, yes: bool) -> Self
Try not to fail on parse errors, like missing option values.
NOTE: This choice is propagated to all child subcommands.
Examples
let cmd = Command::new("cmd")
.ignore_errors(true)
.arg(arg!(-c --config <FILE> "Sets a custom config file"))
.arg(arg!(-x --stuff <FILE> "Sets a custom stuff file"))
.arg(arg!(f: -f "Flag"));
let r = cmd.try_get_matches_from(vec!["cmd", "-c", "file", "-f", "-x"]);
assert!(r.is_ok(), "unexpected error: {:?}", r);
let m = r.unwrap();
assert_eq!(m.get_one::<String>("config").unwrap(), "file");
assert!(*m.get_one::<bool>("f").expect("defaulted"));
assert_eq!(m.get_one::<String>("stuff"), None);
sourcepub fn args_override_self(self, yes: bool) -> Self
pub fn args_override_self(self, yes: bool) -> Self
Replace prior occurrences of arguments rather than error
For any argument that would conflict with itself by default (e.g.
ArgAction::Set
, it will now override itself.
This is the equivalent to saying the foo
arg using Arg::overrides_with("foo")
for all
defined arguments.
NOTE: This choice is propagated to all child subcommands.
sourcepub fn dont_delimit_trailing_values(self, yes: bool) -> Self
pub fn dont_delimit_trailing_values(self, yes: bool) -> Self
Disables the automatic delimiting of values after --
or when Command::trailing_var_arg
was used.
NOTE: The same thing can be done manually by setting the final positional argument to
Arg::value_delimiter(None)
. Using this setting is safer, because it’s easier to locate
when making changes.
NOTE: This choice is propagated to all child subcommands.
Examples
Command::new("myprog")
.dont_delimit_trailing_values(true)
.get_matches();
sourcepub fn color(self, color: ColorChoice) -> Self
pub fn color(self, color: ColorChoice) -> Self
Sets when to color output.
NOTE: This choice is propagated to all child subcommands.
NOTE: Default behaviour is ColorChoice::Auto
.
Examples
Command::new("myprog")
.color(ColorChoice::Never)
.get_matches();
sourcepub fn term_width(self, width: usize) -> Self
pub fn term_width(self, width: usize) -> Self
Sets the terminal width at which to wrap help messages.
Using 0
will ignore terminal widths and use source formatting.
Defaults to current terminal width when wrap_help
feature flag is enabled. If the flag
is disabled or it cannot be determined, the default is 100.
NOTE: This setting applies globally and not on a per-command basis.
NOTE: This requires the [wrap_help
feature][crate::_features]
Examples
Command::new("myprog")
.term_width(80)
sourcepub fn max_term_width(self, w: usize) -> Self
pub fn max_term_width(self, w: usize) -> Self
Limit the line length for wrapping help when using the current terminal’s width.
This only applies when term_width
is unset so that the current
terminal’s width will be used. See Command::term_width
for more details.
Using 0
will ignore terminal widths and use source formatting (default).
NOTE: This setting applies globally and not on a per-command basis.
NOTE: This requires the [wrap_help
feature][crate::_features]
Examples
Command::new("myprog")
.max_term_width(100)
sourcepub fn disable_version_flag(self, yes: bool) -> Self
pub fn disable_version_flag(self, yes: bool) -> Self
Disables -V
and --version
flag.
Examples
let res = Command::new("myprog")
.disable_version_flag(true)
.try_get_matches_from(vec![
"myprog", "-V"
]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
sourcepub fn propagate_version(self, yes: bool) -> Self
pub fn propagate_version(self, yes: bool) -> Self
Specifies to use the version of the current command for all subcommands
.
Defaults to false
; subcommands have independent version strings from their parents.
NOTE: This choice is propagated to all child subcommands.
Examples
Command::new("myprog")
.version("v1.1")
.propagate_version(true)
.subcommand(Command::new("test"))
.get_matches();
// running `$ myprog test --version` will display
// "myprog-test v1.1"
sourcepub fn next_line_help(self, yes: bool) -> Self
pub fn next_line_help(self, yes: bool) -> Self
Places the help string for all arguments and subcommands on the line after them.
NOTE: This choice is propagated to all child subcommands.
Examples
Command::new("myprog")
.next_line_help(true)
.get_matches();
sourcepub fn disable_help_flag(self, yes: bool) -> Self
pub fn disable_help_flag(self, yes: bool) -> Self
Disables -h
and --help
flag.
NOTE: This choice is propagated to all child subcommands.
Examples
let res = Command::new("myprog")
.disable_help_flag(true)
.try_get_matches_from(vec![
"myprog", "-h"
]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
sourcepub fn disable_help_subcommand(self, yes: bool) -> Self
pub fn disable_help_subcommand(self, yes: bool) -> Self
Disables the help
subcommand
.
Examples
let res = Command::new("myprog")
.disable_help_subcommand(true)
// Normally, creating a subcommand causes a `help` subcommand to automatically
// be generated as well
.subcommand(Command::new("test"))
.try_get_matches_from(vec![
"myprog", "help"
]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::InvalidSubcommand);
sourcepub fn disable_colored_help(self, yes: bool) -> Self
pub fn disable_colored_help(self, yes: bool) -> Self
Disables colorized help messages.
NOTE: This choice is propagated to all child subcommands.
Examples
Command::new("myprog")
.disable_colored_help(true)
.get_matches();
sourcepub fn help_expected(self, yes: bool) -> Self
pub fn help_expected(self, yes: bool) -> Self
Panic if help descriptions are omitted.
NOTE: When deriving Parser
, you could instead check this at
compile-time with #![deny(missing_docs)]
NOTE: This choice is propagated to all child subcommands.
Examples
Command::new("myprog")
.help_expected(true)
.arg(
Arg::new("foo").help("It does foo stuff")
// As required via `help_expected`, a help message was supplied
)
Panics
Command::new("myapp")
.help_expected(true)
.arg(
Arg::new("foo")
// Someone forgot to put .about("...") here
// Since the setting `help_expected` is activated, this will lead to
// a panic (if you are in debug mode)
)
sourcepub fn hide_possible_values(self, yes: bool) -> Self
pub fn hide_possible_values(self, yes: bool) -> Self
Tells clap
not to print possible values when displaying help information.
This can be useful if there are many values, or they are explained elsewhere.
To set this per argument, see
Arg::hide_possible_values
.
NOTE: This choice is propagated to all child subcommands.
sourcepub fn infer_long_args(self, yes: bool) -> Self
pub fn infer_long_args(self, yes: bool) -> Self
Allow partial matches of long arguments or their aliases.
For example, to match an argument named --test
, one could use --t
, --te
, --tes
, and
--test
.
NOTE: The match must not be ambiguous at all in order to succeed. i.e. to match
--te
to --test
there could not also be another argument or alias --temp
because both
start with --te
NOTE: This choice is propagated to all child subcommands.
sourcepub fn infer_subcommands(self, yes: bool) -> Self
pub fn infer_subcommands(self, yes: bool) -> Self
Allow partial matches of subcommand names and their aliases.
For example, to match a subcommand named test
, one could use t
, te
, tes
, and
test
.
NOTE: The match must not be ambiguous at all in order to succeed. i.e. to match te
to test
there could not also be a subcommand or alias temp
because both start with te
CAUTION: This setting can interfere with positional/free arguments, take care when
designing CLIs which allow inferred subcommands and have potential positional/free
arguments whose values could start with the same characters as subcommands. If this is the
case, it’s recommended to use settings such as Command::args_conflicts_with_subcommands
in
conjunction with this setting.
NOTE: This choice is propagated to all child subcommands.
Examples
let m = Command::new("prog")
.infer_subcommands(true)
.subcommand(Command::new("test"))
.get_matches_from(vec![
"prog", "te"
]);
assert_eq!(m.subcommand_name(), Some("test"));
source§impl Command
impl Command
Command-specific Settings
These apply only to the current command and are not inherited by subcommands.
sourcepub fn name(self, name: impl Into<Str>) -> Self
pub fn name(self, name: impl Into<Str>) -> Self
(Re)Sets the program’s name.
See Command::new
for more details.
Examples
let cmd = clap::command!()
.name("foo");
// continued logic goes here, such as `cmd.get_matches()` etc.
sourcepub fn bin_name(self, name: impl IntoResettable<String>) -> Self
pub fn bin_name(self, name: impl IntoResettable<String>) -> Self
Overrides the runtime-determined name of the binary for help and error messages.
This should only be used when absolutely necessary, such as when the binary name for your application is misleading, or perhaps not how the user should invoke your program.
Pro-tip: When building things such as third party cargo
subcommands, this setting should be used!
NOTE: This does not change or set the name of the binary file on disk. It only changes what clap thinks the name is for the purposes of error or help messages.
Examples
Command::new("My Program")
.bin_name("my_binary")
sourcepub fn display_name(self, name: impl IntoResettable<String>) -> Self
pub fn display_name(self, name: impl IntoResettable<String>) -> Self
Overrides the runtime-determined display name of the program for help and error messages.
Examples
Command::new("My Program")
.display_name("my_program")
Sets the author(s) for the help message.
Pro-tip: Use clap
s convenience macro [crate_authors!
] to
automatically set your application’s author(s) to the same thing as your
crate at compile time.
NOTE: A custom help_template
is needed for author to show
up.
Examples
Command::new("myprog")
.author("Me, me@mymain.com")
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}
More examples
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
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")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// 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")
.action(ArgAction::Set)
.num_args(1..)
.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")
.action(ArgAction::Set)
.num_args(1..),
),
)
.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_flag("info") {
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
}
}
sourcepub fn about(self, about: impl IntoResettable<StyledStr>) -> Self
pub fn about(self, about: impl IntoResettable<StyledStr>) -> Self
Sets the program’s description for the short help (-h
).
If Command::long_about
is not specified, this message will be displayed for --help
.
NOTE: Only Command::about
(short format) is used in completion
script generation in order to be concise.
See also crate_description!
.
Examples
Command::new("myprog")
.about("Does really amazing things for great people")
Examples found in repository?
More examples
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
sourcepub fn long_about(self, long_about: impl IntoResettable<StyledStr>) -> Self
pub fn long_about(self, long_about: impl IntoResettable<StyledStr>) -> Self
Sets the program’s description for the long help (--help
).
If Command::about
is not specified, this message will be displayed for -h
.
NOTE: Only Command::about
(short format) is used in completion
script generation in order to be concise.
Examples
Command::new("myprog")
.long_about(
"Does really amazing things to great people. Now let's talk a little
more in depth about how this subcommand really works. It may take about
a few lines of text, but that's ok!")
Examples found in repository?
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
sourcepub fn after_help(self, help: impl IntoResettable<StyledStr>) -> Self
pub fn after_help(self, help: impl IntoResettable<StyledStr>) -> Self
Free-form help text for after auto-generated short help (-h
).
This is often used to describe how to use the arguments, caveats to be noted, or license and contact information.
If Command::after_long_help
is not specified, this message will be displayed for --help
.
Examples
Command::new("myprog")
.after_help("Does really amazing things for great people... but be careful with -R!")
Examples found in repository?
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
sourcepub fn after_long_help(self, help: impl IntoResettable<StyledStr>) -> Self
pub fn after_long_help(self, help: impl IntoResettable<StyledStr>) -> Self
Free-form help text for after auto-generated long help (--help
).
This is often used to describe how to use the arguments, caveats to be noted, or license and contact information.
If Command::after_help
is not specified, this message will be displayed for -h
.
Examples
Command::new("myprog")
.after_long_help("Does really amazing things to great people... but be careful with -R, \
like, for real, be careful with this!")
Examples found in repository?
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
sourcepub fn before_help(self, help: impl IntoResettable<StyledStr>) -> Self
pub fn before_help(self, help: impl IntoResettable<StyledStr>) -> Self
Free-form help text for before auto-generated short help (-h
).
This is often used for header, copyright, or license information.
If Command::before_long_help
is not specified, this message will be displayed for --help
.
Examples
Command::new("myprog")
.before_help("Some info I'd like to appear before the help info")
sourcepub fn before_long_help(self, help: impl IntoResettable<StyledStr>) -> Self
pub fn before_long_help(self, help: impl IntoResettable<StyledStr>) -> Self
Free-form help text for before auto-generated long help (--help
).
This is often used for header, copyright, or license information.
If Command::before_help
is not specified, this message will be displayed for -h
.
Examples
Command::new("myprog")
.before_long_help("Some verbose and long info I'd like to appear before the help info")
sourcepub fn version(self, ver: impl IntoResettable<Str>) -> Self
pub fn version(self, ver: impl IntoResettable<Str>) -> Self
Sets the version for the short version (-V
) and help messages.
If Command::long_version
is not specified, this message will be displayed for --version
.
Pro-tip: Use clap
s convenience macro [crate_version!
] to
automatically set your application’s version to the same thing as your
crate at compile time.
Examples
Command::new("myprog")
.version("v0.1.24")
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}
More examples
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
fn main() -> Result<(), std::io::Error> {
let cmd = Command::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>:Ola Nordmann <old@nordmann.no>")
.about("Does awesome things")
.long_about(
"With a longer description to help clarify some things.
And a few newlines.",
)
.after_help("This is an extra section added to the end of the manpage.")
.after_long_help("With even more text added.")
.arg(
arg!(-c --config <FILE> "Sets a custom config file")
.long_help("Some more text about how to set a custom config file")
.default_value("config.toml")
.env("CONFIG_FILE"),
)
.arg(arg!([output] "Sets an output file").default_value("result.txt"))
.arg(
arg!(-d --debug ... "Turn debugging information on")
.env("DEBUG_ON")
.hide_env(true),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "Lists test values")),
);
Man::new(cmd).render(&mut io::stdout())
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
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")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// 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")
.action(ArgAction::Set)
.num_args(1..)
.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")
.action(ArgAction::Set)
.num_args(1..),
),
)
.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_flag("info") {
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
}
}
sourcepub fn long_version(self, ver: impl IntoResettable<Str>) -> Self
pub fn long_version(self, ver: impl IntoResettable<Str>) -> Self
Sets the version for the long version (--version
) and help messages.
If Command::version
is not specified, this message will be displayed for -V
.
Pro-tip: Use clap
s convenience macro [crate_version!
] to
automatically set your application’s version to the same thing as your
crate at compile time.
Examples
Command::new("myprog")
.long_version(
"v0.1.24
commit: abcdef89726d
revision: 123
release: 2
binary: myprog")
sourcepub fn override_usage(self, usage: impl IntoResettable<StyledStr>) -> Self
pub fn override_usage(self, usage: impl IntoResettable<StyledStr>) -> Self
Overrides the clap
generated usage string for help and error messages.
NOTE: Using this setting disables clap
s “context-aware” usage
strings. After this setting is set, this will be the only usage string
displayed to the user!
NOTE: Multiple usage lines may be present in the usage argument, but some rules need to be followed to ensure the usage lines are formatted correctly by the default help formatter:
- Do not indent the first usage line.
- Indent all subsequent usage lines with seven spaces.
- The last line must not end with a newline.
Examples
Command::new("myprog")
.override_usage("myapp [-clDas] <some_file>")
Or for multiple usage lines:
Command::new("myprog")
.override_usage(
"myapp -X [-a] [-b] <file>\n \
myapp -Y [-c] <file1> <file2>\n \
myapp -Z [-d|-e]"
)
sourcepub fn override_help(self, help: impl IntoResettable<StyledStr>) -> Self
pub fn override_help(self, help: impl IntoResettable<StyledStr>) -> Self
Overrides the clap
generated help message (both -h
and --help
).
This should only be used when the auto-generated message does not suffice.
NOTE: This only replaces the help message for the current
command, meaning if you are using subcommands, those help messages will
still be auto-generated unless you specify a Command::override_help
for
them as well.
Examples
Command::new("myapp")
.override_help("myapp v1.0\n\
Does awesome things\n\
(C) me@mail.com\n\n\
Usage: myapp <opts> <command>\n\n\
Options:\n\
-h, --help Display this message\n\
-V, --version Display version info\n\
-s <stuff> Do something with stuff\n\
-v Be verbose\n\n\
Commands:\n\
help Print this message\n\
work Do some work")
sourcepub fn help_template(self, s: impl IntoResettable<StyledStr>) -> Self
pub fn help_template(self, s: impl IntoResettable<StyledStr>) -> Self
Sets the help template to be used, overriding the default format.
NOTE: The template system is by design very simple. Therefore, the tags have to be written in the lowercase and without spacing.
Tags are given inside curly brackets.
Valid tags are:
{name}
- Display name for the (sub-)command.{bin}
- Binary name.{version}
- Version number.{author}
- Author information.{author-with-newline}
- Author followed by\n
.{author-section}
- Author preceded and followed by\n
.{about}
- General description (fromCommand::about
orCommand::long_about
).{about-with-newline}
- About followed by\n
.{about-section}
- About preceded and followed by ‘\n’.{usage-heading}
- Automatically generated usage heading.{usage}
- Automatically generated or given usage string.{all-args}
- Help for all arguments (options, flags, positional arguments, and subcommands) including titles.{options}
- Help for options.{positionals}
- Help for positional arguments.{subcommands}
- Help for subcommands.{tag}
- Standard tab sized used within clap{after-help}
- Help fromCommand::after_help
orCommand::after_long_help
.{before-help}
- Help fromCommand::before_help
orCommand::before_long_help
.
Examples
For a very brief help:
Command::new("myprog")
.version("1.0")
.help_template("{bin} ({version}) - {usage}")
For showing more application context:
Command::new("myprog")
.version("1.0")
.help_template("\
{before-help}{name} {version}
{author-with-newline}{about-with-newline}
{usage-heading} {usage}
{all-args}{after-help}
")
Examples found in repository?
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
sourcepub fn next_help_heading(self, heading: impl IntoResettable<Str>) -> Self
pub fn next_help_heading(self, heading: impl IntoResettable<Str>) -> Self
Set the default section heading for future args.
This will be used for any arg that hasn’t had Arg::help_heading
called.
This is useful if the default Options
or Arguments
headings are
not specific enough for one’s use case.
For subcommands, see Command::subcommand_help_heading
sourcepub fn next_display_order(self, disp_ord: impl IntoResettable<usize>) -> Self
pub fn next_display_order(self, disp_ord: impl IntoResettable<usize>) -> Self
Change the starting value for assigning future display orders for ags.
This will be used for any arg that hasn’t had Arg::display_order
called.
sourcepub fn arg_required_else_help(self, yes: bool) -> Self
pub fn arg_required_else_help(self, yes: bool) -> Self
Exit gracefully if no arguments are present (e.g. $ myprog
).
NOTE: subcommands
count as arguments
Examples
Command::new("myprog")
.arg_required_else_help(true);
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
More examples
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
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")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// 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")
.action(ArgAction::Set)
.num_args(1..)
.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")
.action(ArgAction::Set)
.num_args(1..),
),
)
.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_flag("info") {
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
}
}
sourcepub fn allow_missing_positional(self, yes: bool) -> Self
pub fn allow_missing_positional(self, yes: bool) -> Self
Allows one to implement two styles of CLIs where positionals can be used out of order.
The first example is a CLI where the second to last positional argument is optional, but
the final positional argument is required. Such as $ prog [optional] <required>
where one
of the two following usages is allowed:
$ prog [optional] <required>
$ prog <required>
This would otherwise not be allowed. This is useful when [optional]
has a default value.
Note: when using this style of “missing positionals” the final positional must be
required if --
will not be used to skip to the final positional argument.
Note: This style also only allows a single positional argument to be “skipped” without
the use of --
. To skip more than one, see the second example.
The second example is when one wants to skip multiple optional positional arguments, and use
of the --
operator is OK (but not required if all arguments will be specified anyways).
For example, imagine a CLI which has three positional arguments [foo] [bar] [baz]...
where
baz
accepts multiple values (similar to man ARGS...
style training arguments).
With this setting the following invocations are posisble:
$ prog foo bar baz1 baz2 baz3
$ prog foo -- baz1 baz2 baz3
$ prog -- baz1 baz2 baz3
Examples
Style number one from above:
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.allow_missing_positional(true)
.arg(Arg::new("arg1"))
.arg(Arg::new("arg2")
.required(true))
.get_matches_from(vec![
"prog", "other"
]);
assert_eq!(m.get_one::<String>("arg1"), None);
assert_eq!(m.get_one::<String>("arg2").unwrap(), "other");
Now the same example, but using a default value for the first optional positional argument
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.allow_missing_positional(true)
.arg(Arg::new("arg1")
.default_value("something"))
.arg(Arg::new("arg2")
.required(true))
.get_matches_from(vec![
"prog", "other"
]);
assert_eq!(m.get_one::<String>("arg1").unwrap(), "something");
assert_eq!(m.get_one::<String>("arg2").unwrap(), "other");
Style number two from above:
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.allow_missing_positional(true)
.arg(Arg::new("foo"))
.arg(Arg::new("bar"))
.arg(Arg::new("baz").action(ArgAction::Set).num_args(1..))
.get_matches_from(vec![
"prog", "foo", "bar", "baz1", "baz2", "baz3"
]);
assert_eq!(m.get_one::<String>("foo").unwrap(), "foo");
assert_eq!(m.get_one::<String>("bar").unwrap(), "bar");
assert_eq!(m.get_many::<String>("baz").unwrap().collect::<Vec<_>>(), &["baz1", "baz2", "baz3"]);
Now nofice if we don’t specify foo
or baz
but use the --
operator.
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.allow_missing_positional(true)
.arg(Arg::new("foo"))
.arg(Arg::new("bar"))
.arg(Arg::new("baz").action(ArgAction::Set).num_args(1..))
.get_matches_from(vec![
"prog", "--", "baz1", "baz2", "baz3"
]);
assert_eq!(m.get_one::<String>("foo"), None);
assert_eq!(m.get_one::<String>("bar"), None);
assert_eq!(m.get_many::<String>("baz").unwrap().collect::<Vec<_>>(), &["baz1", "baz2", "baz3"]);
source§impl Command
impl Command
sourcepub fn short_flag(self, short: impl IntoResettable<char>) -> Self
pub fn short_flag(self, short: impl IntoResettable<char>) -> Self
Sets the short version of the subcommand flag without the preceding -
.
Allows the subcommand to be used as if it were an Arg::short
.
Examples
let matches = Command::new("pacman")
.subcommand(
Command::new("sync").short_flag('S').arg(
Arg::new("search")
.short('s')
.long("search")
.action(ArgAction::SetTrue)
.help("search remote repositories for matching strings"),
),
)
.get_matches_from(vec!["pacman", "-Ss"]);
assert_eq!(matches.subcommand_name().unwrap(), "sync");
let sync_matches = matches.subcommand_matches("sync").unwrap();
assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
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")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// 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")
.action(ArgAction::Set)
.num_args(1..)
.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")
.action(ArgAction::Set)
.num_args(1..),
),
)
.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_flag("info") {
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
}
}
sourcepub fn long_flag(self, long: impl Into<Str>) -> Self
pub fn long_flag(self, long: impl Into<Str>) -> Self
Sets the long version of the subcommand flag without the preceding --
.
Allows the subcommand to be used as if it were an Arg::long
.
NOTE: Any leading -
characters will be stripped.
Examples
To set long_flag
use a word containing valid UTF-8 codepoints. If you supply a double leading
--
such as --sync
they will be stripped. Hyphens in the middle of the word; however,
will not be stripped (i.e. sync-file
is allowed).
let matches = Command::new("pacman")
.subcommand(
Command::new("sync").long_flag("sync").arg(
Arg::new("search")
.short('s')
.long("search")
.action(ArgAction::SetTrue)
.help("search remote repositories for matching strings"),
),
)
.get_matches_from(vec!["pacman", "--sync", "--search"]);
assert_eq!(matches.subcommand_name().unwrap(), "sync");
let sync_matches = matches.subcommand_matches("sync").unwrap();
assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
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")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// 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")
.action(ArgAction::Set)
.num_args(1..)
.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")
.action(ArgAction::Set)
.num_args(1..),
),
)
.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_flag("info") {
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
}
}
sourcepub fn alias(self, name: impl IntoResettable<Str>) -> Self
pub fn alias(self, name: impl IntoResettable<Str>) -> Self
Sets a hidden alias to this subcommand.
This allows the subcommand to be accessed via either the original name, or this given alias. This is more efficient and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all aliased variants.
NOTE: Aliases defined with this method are hidden from the help
message. If you’re looking for aliases that will be displayed in the help
message, see Command::visible_alias
.
NOTE: When using aliases and checking for the existence of a
particular subcommand within an ArgMatches
struct, one only needs to
search for the original name and not all aliases.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test")
.alias("do-stuff"))
.get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));
Examples found in repository?
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
sourcepub fn short_flag_alias(self, name: impl IntoResettable<char>) -> Self
pub fn short_flag_alias(self, name: impl IntoResettable<char>) -> Self
Add an alias, which functions as “hidden” short flag subcommand
This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").short_flag('t')
.short_flag_alias('d'))
.get_matches_from(vec!["myprog", "-d"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn long_flag_alias(self, name: impl IntoResettable<Str>) -> Self
pub fn long_flag_alias(self, name: impl IntoResettable<Str>) -> Self
Add an alias, which functions as a “hidden” long flag subcommand.
This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").long_flag("test")
.long_flag_alias("testing"))
.get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn aliases(self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self
pub fn aliases(self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self
Sets multiple hidden aliases to this subcommand.
This allows the subcommand to be accessed via either the original name or any of the given aliases. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command and not all aliased variants.
NOTE: Aliases defined with this method are hidden from the help
message. If looking for aliases that will be displayed in the help
message, see Command::visible_aliases
.
NOTE: When using aliases and checking for the existence of a
particular subcommand within an ArgMatches
struct, one only needs to
search for the original name and not all aliases.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test")
.aliases(["do-stuff", "do-tests", "tests"]))
.arg(Arg::new("input")
.help("the file to add")
.required(false))
.get_matches_from(vec!["myprog", "do-tests"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn short_flag_aliases(self, names: impl IntoIterator<Item = char>) -> Self
pub fn short_flag_aliases(self, names: impl IntoIterator<Item = char>) -> Self
Add aliases, which function as “hidden” short flag subcommands.
These will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").short_flag('t')
.short_flag_aliases(['a', 'b', 'c']))
.arg(Arg::new("input")
.help("the file to add")
.required(false))
.get_matches_from(vec!["myprog", "-a"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn long_flag_aliases(
self,
names: impl IntoIterator<Item = impl Into<Str>>
) -> Self
pub fn long_flag_aliases(
self,
names: impl IntoIterator<Item = impl Into<Str>>
) -> Self
Add aliases, which function as “hidden” long flag subcommands.
These will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").long_flag("test")
.long_flag_aliases(["testing", "testall", "test_all"]))
.arg(Arg::new("input")
.help("the file to add")
.required(false))
.get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn visible_alias(self, name: impl IntoResettable<Str>) -> Self
pub fn visible_alias(self, name: impl IntoResettable<Str>) -> Self
Sets a visible alias to this subcommand.
This allows the subcommand to be accessed via either the original name or the given alias. This is more efficient and easier than creating hidden subcommands as one only needs to check for the existence of this command and not all aliased variants.
NOTE: The alias defined with this method is visible from the help
message and displayed as if it were just another regular subcommand. If
looking for an alias that will not be displayed in the help message, see
Command::alias
.
NOTE: When using aliases and checking for the existence of a
particular subcommand within an ArgMatches
struct, one only needs to
search for the original name and not all aliases.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test")
.visible_alias("do-stuff"))
.get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));
Examples found in repository?
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
fn build_cli() -> Command {
let value_hint_command = Command::new("value-hint")
.visible_alias("hint")
.arg(
Arg::new("unknown")
.long("unknown")
.value_hint(ValueHint::Unknown),
)
.arg(Arg::new("other").long("other").value_hint(ValueHint::Other))
.arg(
Arg::new("path")
.long("path")
.short('p')
.value_hint(ValueHint::AnyPath),
)
.arg(
Arg::new("file")
.long("file")
.short('f')
.value_hint(ValueHint::FilePath),
)
.arg(
Arg::new("dir")
.long("dir")
.short('d')
.value_hint(ValueHint::DirPath),
)
.arg(
Arg::new("exe")
.long("exe")
.short('e')
.value_hint(ValueHint::ExecutablePath),
)
.arg(
Arg::new("cmd_name")
.long("cmd-name")
.value_hint(ValueHint::CommandName),
)
.arg(
Arg::new("cmd")
.long("cmd")
.short('c')
.value_hint(ValueHint::CommandString),
)
.arg(
Arg::new("command_with_args")
.num_args(1..)
// AppSettings::TrailingVarArg is required to use ValueHint::CommandWithArguments
.trailing_var_arg(true)
.value_hint(ValueHint::CommandWithArguments),
)
.arg(
Arg::new("user")
.short('u')
.long("user")
.value_hint(ValueHint::Username),
)
.arg(
Arg::new("host")
.long("host")
.value_hint(ValueHint::Hostname),
)
.arg(Arg::new("url").long("url").value_hint(ValueHint::Url))
.arg(
Arg::new("email")
.long("email")
.value_hint(ValueHint::EmailAddress),
);
Command::new("completion")
.arg(
Arg::new("generator")
.long("generate")
.value_parser(value_parser!(Shell)),
)
.subcommand(value_hint_command)
}
sourcepub fn visible_short_flag_alias(self, name: impl IntoResettable<char>) -> Self
pub fn visible_short_flag_alias(self, name: impl IntoResettable<char>) -> Self
Add an alias, which functions as “visible” short flag subcommand
This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.
See also Command::short_flag_alias
.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").short_flag('t')
.visible_short_flag_alias('d'))
.get_matches_from(vec!["myprog", "-d"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn visible_long_flag_alias(self, name: impl IntoResettable<Str>) -> Self
pub fn visible_long_flag_alias(self, name: impl IntoResettable<Str>) -> Self
Add an alias, which functions as a “visible” long flag subcommand.
This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.
See also Command::long_flag_alias
.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").long_flag("test")
.visible_long_flag_alias("testing"))
.get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn visible_aliases(
self,
names: impl IntoIterator<Item = impl Into<Str>>
) -> Self
pub fn visible_aliases(
self,
names: impl IntoIterator<Item = impl Into<Str>>
) -> Self
Sets multiple visible aliases to this subcommand.
This allows the subcommand to be accessed via either the original name or any of the given aliases. This is more efficient and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command and not all aliased variants.
NOTE: The alias defined with this method is visible from the help
message and displayed as if it were just another regular subcommand. If
looking for an alias that will not be displayed in the help message, see
Command::alias
.
NOTE: When using aliases, and checking for the existence of a
particular subcommand within an ArgMatches
struct, one only needs to
search for the original name and not all aliases.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test")
.visible_aliases(["do-stuff", "tests"]))
.get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn visible_short_flag_aliases(
self,
names: impl IntoIterator<Item = char>
) -> Self
pub fn visible_short_flag_aliases(
self,
names: impl IntoIterator<Item = char>
) -> Self
Add aliases, which function as visible short flag subcommands.
See Command::short_flag_aliases
.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").short_flag('b')
.visible_short_flag_aliases(['t']))
.get_matches_from(vec!["myprog", "-t"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn visible_long_flag_aliases(
self,
names: impl IntoIterator<Item = impl Into<Str>>
) -> Self
pub fn visible_long_flag_aliases(
self,
names: impl IntoIterator<Item = impl Into<Str>>
) -> Self
Add aliases, which function as visible long flag subcommands.
See Command::long_flag_aliases
.
Examples
let m = Command::new("myprog")
.subcommand(Command::new("test").long_flag("test")
.visible_long_flag_aliases(["testing", "testall", "test_all"]))
.get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));
sourcepub fn display_order(self, ord: impl IntoResettable<usize>) -> Self
pub fn display_order(self, ord: impl IntoResettable<usize>) -> Self
Set the placement of this subcommand within the help.
Subcommands with a lower value will be displayed first in the help message. Subcommands with duplicate display orders will be displayed in alphabetical order.
This is helpful when one would like to emphasize frequently used subcommands, or prioritize those towards the top of the list.
NOTE: The default is 999 for all subcommands.
Examples
let m = Command::new("cust-ord")
.subcommand(Command::new("alpha") // typically subcommands are grouped
// alphabetically by name. Subcommands
// without a display_order have a value of
// 999 and are displayed alphabetically with
// all other 999 subcommands
.about("Some help and text"))
.subcommand(Command::new("beta")
.display_order(1) // In order to force this subcommand to appear *first*
// all we have to do is give it a value lower than 999.
// Any other subcommands with a value of 1 will be displayed
// alphabetically with this one...then 2 values, then 3, etc.
.about("I should be first!"))
.get_matches_from(vec![
"cust-ord", "--help"
]);
The above example displays the following help message
cust-ord
Usage: cust-ord [OPTIONS]
Commands:
beta I should be first!
alpha Some help and text
Options:
-h, --help Print help information
-V, --version Print version information
sourcepub fn hide(self, yes: bool) -> Self
pub fn hide(self, yes: bool) -> Self
Specifies that this subcommand
should be hidden from help messages
Examples
Command::new("myprog")
.subcommand(
Command::new("test").hide(true)
)
sourcepub fn subcommand_required(self, yes: bool) -> Self
pub fn subcommand_required(self, yes: bool) -> Self
If no subcommand
is present at runtime, error and exit gracefully.
Examples
let err = Command::new("myprog")
.subcommand_required(true)
.subcommand(Command::new("test"))
.try_get_matches_from(vec![
"myprog",
]);
assert!(err.is_err());
assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand);
Examples found in repository?
More examples
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
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")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// 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")
.action(ArgAction::Set)
.num_args(1..)
.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")
.action(ArgAction::Set)
.num_args(1..),
),
)
.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_flag("info") {
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
}
}
sourcepub fn allow_external_subcommands(self, yes: bool) -> Self
pub fn allow_external_subcommands(self, yes: bool) -> Self
Assume unexpected positional arguments are a subcommand
.
Arguments will be stored in the ""
argument in the ArgMatches
NOTE: Use this setting with caution, as a truly unexpected argument (i.e. one that is NOT an external subcommand) will not cause an error and instead be treated as a potential subcommand. One should check for such cases manually and inform the user appropriately.
NOTE: A built-in subcommand will be parsed as an external subcommand when escaped with
--
.
Examples
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.allow_external_subcommands(true)
.get_matches_from(vec![
"myprog", "subcmd", "--option", "value", "-fff", "--flag"
]);
// All trailing arguments will be stored under the subcommand's sub-matches using an empty
// string argument name
match m.subcommand() {
Some((external, ext_m)) => {
let ext_args: Vec<_> = ext_m.get_many::<OsString>("").unwrap().collect();
assert_eq!(external, "subcmd");
assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
},
_ => {},
}
Examples found in repository?
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
sourcepub fn external_subcommand_value_parser(
self,
parser: impl IntoResettable<ValueParser>
) -> Self
pub fn external_subcommand_value_parser(
self,
parser: impl IntoResettable<ValueParser>
) -> Self
Specifies how to parse external subcommand arguments.
The default parser is for OsString
. This can be used to switch it to String
or another
type.
NOTE: Setting this requires Command::allow_external_subcommands
Examples
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.allow_external_subcommands(true)
.get_matches_from(vec![
"myprog", "subcmd", "--option", "value", "-fff", "--flag"
]);
// All trailing arguments will be stored under the subcommand's sub-matches using an empty
// string argument name
match m.subcommand() {
Some((external, ext_m)) => {
let ext_args: Vec<_> = ext_m.get_many::<OsString>("").unwrap().collect();
assert_eq!(external, "subcmd");
assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
},
_ => {},
}
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
.external_subcommand_value_parser(value_parser!(String))
.get_matches_from(vec![
"myprog", "subcmd", "--option", "value", "-fff", "--flag"
]);
// All trailing arguments will be stored under the subcommand's sub-matches using an empty
// string argument name
match m.subcommand() {
Some((external, ext_m)) => {
let ext_args: Vec<_> = ext_m.get_many::<String>("").unwrap().collect();
assert_eq!(external, "subcmd");
assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
},
_ => {},
}
sourcepub fn args_conflicts_with_subcommands(self, yes: bool) -> Self
pub fn args_conflicts_with_subcommands(self, yes: bool) -> Self
Specifies that use of an argument prevents the use of subcommands
.
By default clap
allows arguments between subcommands such
as <cmd> [cmd_args] <subcmd> [subcmd_args] <subsubcmd> [subsubcmd_args]
.
This setting disables that functionality and says that arguments can only follow the final subcommand. For instance using this setting makes only the following invocations possible:
<cmd> <subcmd> <subsubcmd> [subsubcmd_args]
<cmd> <subcmd> [subcmd_args]
<cmd> [cmd_args]
Examples
Command::new("myprog")
.args_conflicts_with_subcommands(true);
Examples found in repository?
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_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("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.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]))),
)
}
sourcepub fn subcommand_precedence_over_arg(self, yes: bool) -> Self
pub fn subcommand_precedence_over_arg(self, yes: bool) -> Self
Prevent subcommands from being consumed as an arguments value.
By default, if an option taking multiple values is followed by a subcommand, the subcommand will be parsed as another value.
cmd --foo val1 val2 subcommand
--------- ----------
values another value
This setting instructs the parser to stop when encountering a subcommand instead of greedily consuming arguments.
cmd --foo val1 val2 subcommand
--------- ----------
values subcommand
Examples
let cmd = Command::new("cmd").subcommand(Command::new("sub")).arg(
Arg::new("arg")
.long("arg")
.num_args(1..)
.action(ArgAction::Set),
);
let matches = cmd
.clone()
.try_get_matches_from(&["cmd", "--arg", "1", "2", "3", "sub"])
.unwrap();
assert_eq!(
matches.get_many::<String>("arg").unwrap().collect::<Vec<_>>(),
&["1", "2", "3", "sub"]
);
assert!(matches.subcommand_matches("sub").is_none());
let matches = cmd
.subcommand_precedence_over_arg(true)
.try_get_matches_from(&["cmd", "--arg", "1", "2", "3", "sub"])
.unwrap();
assert_eq!(
matches.get_many::<String>("arg").unwrap().collect::<Vec<_>>(),
&["1", "2", "3"]
);
assert!(matches.subcommand_matches("sub").is_some());
sourcepub fn subcommand_negates_reqs(self, yes: bool) -> Self
pub fn subcommand_negates_reqs(self, yes: bool) -> Self
Allows subcommands
to override all requirements of the parent command.
For example, if you had a subcommand or top level application with a required argument
that is only required as long as there is no subcommand present,
using this setting would allow you to set those arguments to Arg::required(true)
and yet receive no error so long as the user uses a valid subcommand instead.
NOTE: This defaults to false (using subcommand does not negate requirements)
Examples
This first example shows that it is an error to not use a required argument
let err = Command::new("myprog")
.subcommand_negates_reqs(true)
.arg(Arg::new("opt").required(true))
.subcommand(Command::new("test"))
.try_get_matches_from(vec![
"myprog"
]);
assert!(err.is_err());
assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
This next example shows that it is no longer error to not use a required argument if a valid subcommand is used.
let noerr = Command::new("myprog")
.subcommand_negates_reqs(true)
.arg(Arg::new("opt").required(true))
.subcommand(Command::new("test"))
.try_get_matches_from(vec![
"myprog", "test"
]);
assert!(noerr.is_ok());
sourcepub fn multicall(self, yes: bool) -> Self
pub fn multicall(self, yes: bool) -> Self
Multiple-personality program dispatched on the binary name (argv[0]
)
A “multicall” executable is a single executable that contains a variety of applets, and decides which applet to run based on the name of the file. The executable can be called from different names by creating hard links or symbolic links to it.
This is desirable for:
- Easy distribution, a single binary that can install hardlinks to access the different personalities.
- Minimal binary size by sharing common code (e.g. standard library, clap)
- Custom shells or REPLs where there isn’t a single top-level command
Setting multicall
will cause
argv[0]
to be stripped to the base name and parsed as the first argument, as ifCommand::no_binary_name
was set.- Help and errors to report subcommands as if they were the top-level command
When the subcommand is not present, there are several strategies you may employ, depending on your needs:
- Let the error percolate up normally
- Print a specialized error message using the
Error::context
- Print the help but this might be ambiguous
- Disable
multicall
and re-parse it - Disable
multicall
and re-parse it with a specific subcommand
When detecting the error condition, the ErrorKind
isn’t sufficient as a sub-subcommand
might report the same error. Enable
allow_external_subcommands
if you want to specifically
get the unrecognized binary name.
NOTE: Multicall can’t be used with no_binary_name
since they interpret
the command name in incompatible ways.
NOTE: The multicall command cannot have arguments.
NOTE: Applets are slightly semantically different from subcommands,
so it’s recommended to use Command::subcommand_help_heading
and
Command::subcommand_value_name
to change the descriptive text as above.
Examples
hostname
is an example of a multicall executable.
Both hostname
and dnsdomainname
are provided by the same executable
and which behaviour to use is based on the executable file name.
This is desirable when the executable has a primary purpose but there is related functionality that would be convenient to provide and implement it to be in the same executable.
The name of the cmd is essentially unused and may be the same as the name of a subcommand.
The names of the immediate subcommands of the Command are matched against the basename of the first argument, which is conventionally the path of the executable.
This does not allow the subcommand to be passed as the first non-path argument.
let mut cmd = Command::new("hostname")
.multicall(true)
.subcommand(Command::new("hostname"))
.subcommand(Command::new("dnsdomainname"));
let m = cmd.try_get_matches_from_mut(&["/usr/bin/hostname", "dnsdomainname"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
let m = cmd.get_matches_from(&["/usr/bin/dnsdomainname"]);
assert_eq!(m.subcommand_name(), Some("dnsdomainname"));
Busybox is another common example of a multicall executable
with a subcommmand for each applet that can be run directly,
e.g. with the cat
applet being run by running busybox cat
,
or with cat
as a link to the busybox
binary.
This is desirable when the launcher program has additional options or it is useful to run the applet without installing a symlink e.g. to test the applet without installing it or there may already be a command of that name installed.
To make an applet usable as both a multicall link and a subcommand the subcommands must be defined both in the top-level Command and as subcommands of the “main” applet.
fn applet_commands() -> [Command; 2] {
[Command::new("true"), Command::new("false")]
}
let mut cmd = Command::new("busybox")
.multicall(true)
.subcommand(
Command::new("busybox")
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
// When called from the executable's canonical name
// its applets can be matched as subcommands.
let m = cmd.try_get_matches_from_mut(&["/usr/bin/busybox", "true"]).unwrap();
assert_eq!(m.subcommand_name(), Some("busybox"));
assert_eq!(m.subcommand().unwrap().1.subcommand_name(), Some("true"));
// When called from a link named after an applet that applet is matched.
let m = cmd.get_matches_from(&["/usr/bin/true"]);
assert_eq!(m.subcommand_name(), Some("true"));
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
More examples
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
sourcepub fn subcommand_value_name(self, value_name: impl IntoResettable<Str>) -> Self
pub fn subcommand_value_name(self, value_name: impl IntoResettable<Str>) -> Self
Sets the value name used for subcommands when printing usage and help.
By default, this is “COMMAND”.
See also Command::subcommand_help_heading
Examples
Command::new("myprog")
.subcommand(Command::new("sub1"))
.print_help()
will produce
myprog
Usage: myprog [COMMAND]
Commands:
help Print this message or the help of the given subcommand(s)
sub1
Options:
-h, --help Print help information
-V, --version Print version information
but usage of subcommand_value_name
Command::new("myprog")
.subcommand(Command::new("sub1"))
.subcommand_value_name("THING")
.print_help()
will produce
myprog
Usage: myprog [THING]
Commands:
help Print this message or the help of the given subcommand(s)
sub1
Options:
-h, --help Print help information
-V, --version Print version information
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
More examples
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
sourcepub fn subcommand_help_heading(self, heading: impl IntoResettable<Str>) -> Self
pub fn subcommand_help_heading(self, heading: impl IntoResettable<Str>) -> Self
Sets the help heading used for subcommands when printing usage and help.
By default, this is “Commands”.
See also Command::subcommand_value_name
Examples
Command::new("myprog")
.subcommand(Command::new("sub1"))
.print_help()
will produce
myprog
Usage: myprog [COMMAND]
Commands:
help Print this message or the help of the given subcommand(s)
sub1
Options:
-h, --help Print help information
-V, --version Print version information
but usage of subcommand_help_heading
Command::new("myprog")
.subcommand(Command::new("sub1"))
.subcommand_help_heading("Things")
.print_help()
will produce
myprog
Usage: myprog [COMMAND]
Things:
help Print this message or the help of the given subcommand(s)
sub1
Options:
-h, --help Print help information
-V, --version Print version information
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
More examples
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}
source§impl Command
impl Command
sourcepub fn get_display_name(&self) -> Option<&str>
pub fn get_display_name(&self) -> Option<&str>
Get the name of the binary.
sourcepub fn get_bin_name(&self) -> Option<&str>
pub fn get_bin_name(&self) -> Option<&str>
Get the name of the binary.
sourcepub fn set_bin_name(&mut self, name: impl Into<String>)
pub fn set_bin_name(&mut self, name: impl Into<String>)
Set binary name. Uses &mut self
instead of self
.
sourcepub fn get_name(&self) -> &str
pub fn get_name(&self) -> &str
Get the name of the cmd.
Examples found in repository?
More examples
sourcepub fn get_version(&self) -> Option<&str>
pub fn get_version(&self) -> Option<&str>
Get the version of the cmd.
sourcepub fn get_long_version(&self) -> Option<&str>
pub fn get_long_version(&self) -> Option<&str>
Get the long version of the cmd.
Get the authors of the cmd.
sourcepub fn get_short_flag(&self) -> Option<char>
pub fn get_short_flag(&self) -> Option<char>
Get the short flag of the subcommand.
sourcepub fn get_long_flag(&self) -> Option<&str>
pub fn get_long_flag(&self) -> Option<&str>
Get the long flag of the subcommand.
sourcepub fn get_about(&self) -> Option<&StyledStr>
pub fn get_about(&self) -> Option<&StyledStr>
Get the help message specified via Command::about
.
sourcepub fn get_long_about(&self) -> Option<&StyledStr>
pub fn get_long_about(&self) -> Option<&StyledStr>
Get the help message specified via Command::long_about
.
sourcepub fn get_next_help_heading(&self) -> Option<&str>
pub fn get_next_help_heading(&self) -> Option<&str>
Get the custom section heading specified via Command::next_help_heading
.
sourcepub fn get_visible_aliases(&self) -> impl Iterator<Item = &str> + '_
pub fn get_visible_aliases(&self) -> impl Iterator<Item = &str> + '_
Iterate through the visible aliases for this subcommand.
sourcepub fn get_visible_short_flag_aliases(&self) -> impl Iterator<Item = char> + '_
pub fn get_visible_short_flag_aliases(&self) -> impl Iterator<Item = char> + '_
Iterate through the visible short aliases for this subcommand.
sourcepub fn get_visible_long_flag_aliases(&self) -> impl Iterator<Item = &str> + '_
pub fn get_visible_long_flag_aliases(&self) -> impl Iterator<Item = &str> + '_
Iterate through the visible long aliases for this subcommand.
sourcepub fn get_all_aliases(&self) -> impl Iterator<Item = &str> + '_
pub fn get_all_aliases(&self) -> impl Iterator<Item = &str> + '_
Iterate through the set of all the aliases for this subcommand, both visible and hidden.
sourcepub fn get_all_short_flag_aliases(&self) -> impl Iterator<Item = char> + '_
pub fn get_all_short_flag_aliases(&self) -> impl Iterator<Item = char> + '_
Iterate through the set of all the short aliases for this subcommand, both visible and hidden.
sourcepub fn get_all_long_flag_aliases(&self) -> impl Iterator<Item = &str> + '_
pub fn get_all_long_flag_aliases(&self) -> impl Iterator<Item = &str> + '_
Iterate through the set of all the long aliases for this subcommand, both visible and hidden.
sourcepub fn get_color(&self) -> ColorChoice
pub fn get_color(&self) -> ColorChoice
Should we color the output?
sourcepub fn get_subcommands(&self) -> impl Iterator<Item = &Command>
pub fn get_subcommands(&self) -> impl Iterator<Item = &Command>
Iterate through the set of subcommands, getting a reference to each.
sourcepub fn get_subcommands_mut(&mut self) -> impl Iterator<Item = &mut Command>
pub fn get_subcommands_mut(&mut self) -> impl Iterator<Item = &mut Command>
Iterate through the set of subcommands, getting a mutable reference to each.
sourcepub fn has_subcommands(&self) -> bool
pub fn has_subcommands(&self) -> bool
Returns true
if this Command
has subcommands.
sourcepub fn get_subcommand_help_heading(&self) -> Option<&str>
pub fn get_subcommand_help_heading(&self) -> Option<&str>
Returns the help heading for listing subcommands.
sourcepub fn get_subcommand_value_name(&self) -> Option<&str>
pub fn get_subcommand_value_name(&self) -> Option<&str>
Returns the subcommand value name.
sourcepub fn get_before_help(&self) -> Option<&StyledStr>
pub fn get_before_help(&self) -> Option<&StyledStr>
Returns the help heading for listing subcommands.
sourcepub fn get_before_long_help(&self) -> Option<&StyledStr>
pub fn get_before_long_help(&self) -> Option<&StyledStr>
Returns the help heading for listing subcommands.
sourcepub fn get_after_help(&self) -> Option<&StyledStr>
pub fn get_after_help(&self) -> Option<&StyledStr>
Returns the help heading for listing subcommands.
sourcepub fn get_after_long_help(&self) -> Option<&StyledStr>
pub fn get_after_long_help(&self) -> Option<&StyledStr>
Returns the help heading for listing subcommands.
sourcepub fn find_subcommand(&self, name: impl AsRef<OsStr>) -> Option<&Command>
pub fn find_subcommand(&self, name: impl AsRef<OsStr>) -> Option<&Command>
Find subcommand such that its name or one of aliases equals name
.
This does not recurse through subcommands of subcommands.
sourcepub fn find_subcommand_mut(
&mut self,
name: impl AsRef<OsStr>
) -> Option<&mut Command>
pub fn find_subcommand_mut(
&mut self,
name: impl AsRef<OsStr>
) -> Option<&mut Command>
Find subcommand such that its name or one of aliases equals name
, returning
a mutable reference to the subcommand.
This does not recurse through subcommands of subcommands.
sourcepub fn get_groups(&self) -> impl Iterator<Item = &ArgGroup>
pub fn get_groups(&self) -> impl Iterator<Item = &ArgGroup>
Iterate through the set of groups.
sourcepub fn get_arguments(&self) -> impl Iterator<Item = &Arg>
pub fn get_arguments(&self) -> impl Iterator<Item = &Arg>
Iterate through the set of arguments.
sourcepub fn get_positionals(&self) -> impl Iterator<Item = &Arg>
pub fn get_positionals(&self) -> impl Iterator<Item = &Arg>
Iterate through the positionals arguments.
sourcepub fn get_arg_conflicts_with(&self, arg: &Arg) -> Vec<&Arg>
pub fn get_arg_conflicts_with(&self, arg: &Arg) -> Vec<&Arg>
Get a list of all arguments the given argument conflicts with.
If the provided argument is declared as global, the conflicts will be determined based on the propagation rules of global arguments.
Panics
If the given arg contains a conflict with an argument that is unknown to
this Command
.
sourcepub fn is_no_binary_name_set(&self) -> bool
pub fn is_no_binary_name_set(&self) -> bool
Report whether Command::no_binary_name
is set
sourcepub fn is_dont_delimit_trailing_values_set(&self) -> bool
pub fn is_dont_delimit_trailing_values_set(&self) -> bool
Report whether Command::dont_delimit_trailing_values
is set
sourcepub fn is_disable_version_flag_set(&self) -> bool
pub fn is_disable_version_flag_set(&self) -> bool
Report whether Command::disable_version_flag
is set
sourcepub fn is_propagate_version_set(&self) -> bool
pub fn is_propagate_version_set(&self) -> bool
Report whether Command::propagate_version
is set
sourcepub fn is_next_line_help_set(&self) -> bool
pub fn is_next_line_help_set(&self) -> bool
Report whether Command::next_line_help
is set
sourcepub fn is_disable_help_flag_set(&self) -> bool
pub fn is_disable_help_flag_set(&self) -> bool
Report whether Command::disable_help_flag
is set
sourcepub fn is_disable_help_subcommand_set(&self) -> bool
pub fn is_disable_help_subcommand_set(&self) -> bool
Report whether Command::disable_help_subcommand
is set
sourcepub fn is_disable_colored_help_set(&self) -> bool
pub fn is_disable_colored_help_set(&self) -> bool
Report whether Command::disable_colored_help
is set
sourcepub fn is_arg_required_else_help_set(&self) -> bool
pub fn is_arg_required_else_help_set(&self) -> bool
Report whether Command::arg_required_else_help
is set
sourcepub fn is_allow_missing_positional_set(&self) -> bool
pub fn is_allow_missing_positional_set(&self) -> bool
Report whether Command::allow_missing_positional
is set
sourcepub fn is_hide_set(&self) -> bool
pub fn is_hide_set(&self) -> bool
Report whether Command::hide
is set
sourcepub fn is_subcommand_required_set(&self) -> bool
pub fn is_subcommand_required_set(&self) -> bool
Report whether Command::subcommand_required
is set
sourcepub fn is_allow_external_subcommands_set(&self) -> bool
pub fn is_allow_external_subcommands_set(&self) -> bool
Report whether Command::allow_external_subcommands
is set
sourcepub fn get_external_subcommand_value_parser(&self) -> Option<&ValueParser>
pub fn get_external_subcommand_value_parser(&self) -> Option<&ValueParser>
Configured parser for values passed to an external subcommand
Example
let cmd = clap::Command::new("raw")
.external_subcommand_value_parser(clap::value_parser!(String));
let value_parser = cmd.get_external_subcommand_value_parser();
println!("{:?}", value_parser);
sourcepub fn is_args_conflicts_with_subcommands_set(&self) -> bool
pub fn is_args_conflicts_with_subcommands_set(&self) -> bool
Report whether Command::args_conflicts_with_subcommands
is set
sourcepub fn is_subcommand_precedence_over_arg_set(&self) -> bool
pub fn is_subcommand_precedence_over_arg_set(&self) -> bool
Report whether Command::subcommand_precedence_over_arg
is set
sourcepub fn is_subcommand_negates_reqs_set(&self) -> bool
pub fn is_subcommand_negates_reqs_set(&self) -> bool
Report whether Command::subcommand_negates_reqs
is set
sourcepub fn is_multicall_set(&self) -> bool
pub fn is_multicall_set(&self) -> bool
Report whether Command::multicall
is set