Command

Struct Command 

Source
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.

§Examples

let m = Command::new("My Program")
    .author("Me, [email protected]")
    .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

§Basic API

Source

pub fn new(name: impl Into<Str>) -> Command

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?
examples/multicall-busybox.rs (line 8)
6fn applet_commands() -> [Command; 2] {
7    [
8        Command::new("true").about("does nothing successfully"),
9        Command::new("false").about("does nothing unsuccessfully"),
10    ]
11}
12
13fn main() {
14    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
15        .multicall(true)
16        .subcommand(
17            Command::new("busybox")
18                .arg_required_else_help(true)
19                .subcommand_value_name("APPLET")
20                .subcommand_help_heading("APPLETS")
21                .arg(
22                    Arg::new("install")
23                        .long("install")
24                        .help("Install hardlinks for all subcommands in path")
25                        .exclusive(true)
26                        .action(ArgAction::Set)
27                        .default_missing_value("/usr/local/bin")
28                        .value_parser(value_parser!(PathBuf)),
29                )
30                .subcommands(applet_commands()),
31        )
32        .subcommands(applet_commands());
33
34    let matches = cmd.get_matches();
35    let mut subcommand = matches.subcommand();
36    if let Some(("busybox", cmd)) = subcommand {
37        if cmd.contains_id("install") {
38            unimplemented!("Make hardlinks to the executable here");
39        }
40        subcommand = cmd.subcommand();
41    }
42    match subcommand {
43        Some(("false", _)) => exit(1),
44        Some(("true", _)) => exit(0),
45        _ => unreachable!("parser should ensure only valid subcommand names are used"),
46    }
47}
More examples
Hide additional examples
examples/derive_ref/hand_subcommand.rs (line 55)
54    fn augment_subcommands(cmd: Command) -> Command {
55        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
56            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
57            .subcommand_required(true)
58    }
59    fn augment_subcommands_for_update(cmd: Command) -> Command {
60        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
61            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
62            .subcommand_required(true)
63    }
examples/derive_ref/augment_subcommands.rs (line 12)
11fn main() {
12    let cli = Command::new("Built CLI");
13    // Augment with derived subcommands
14    let cli = Subcommands::augment_subcommands(cli);
15
16    let matches = cli.get_matches();
17    let derived_subcommands = Subcommands::from_arg_matches(&matches)
18        .map_err(|err| err.exit())
19        .unwrap();
20    println!("Derived subcommands: {derived_subcommands:#?}");
21}
examples/tutorial_builder/02_apps.rs (line 4)
3fn main() {
4    let matches = Command::new("MyApp")
5        .version("1.0")
6        .about("Does awesome things")
7        .arg(arg!(--two <VALUE>).required(true))
8        .arg(arg!(--one <VALUE>).required(true))
9        .get_matches();
10
11    println!(
12        "two: {:?}",
13        matches.get_one::<String>("two").expect("required")
14    );
15    println!(
16        "one: {:?}",
17        matches.get_one::<String>("one").expect("required")
18    );
19}
examples/multicall-hostname.rs (line 4)
3fn main() {
4    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
5        .multicall(true)
6        .arg_required_else_help(true)
7        .subcommand_value_name("APPLET")
8        .subcommand_help_heading("APPLETS")
9        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
10        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
11
12    match cmd.get_matches().subcommand_name() {
13        Some("hostname") => println!("www"),
14        Some("dnsdomainname") => println!("example.com"),
15        _ => unreachable!("parser should ensure only valid subcommand names are used"),
16    }
17}
examples/derive_ref/augment_args.rs (line 10)
9fn main() {
10    let cli = Command::new("CLI").arg(arg!(-b - -built).action(clap::ArgAction::SetTrue));
11    // Augment built args with derived args
12    let cli = DerivedArgs::augment_args(cli);
13
14    let matches = cli.get_matches();
15    println!("Value of built: {:?}", matches.get_flag("built"));
16    println!(
17        "Value of derived via ArgMatches: {:?}",
18        matches.get_flag("derived")
19    );
20
21    // Since DerivedArgs implements FromArgMatches, we can extract it from the unstructured ArgMatches.
22    // This is the main benefit of using derived arguments.
23    let derived_matches = DerivedArgs::from_arg_matches(&matches)
24        .map_err(|err| err.exit())
25        .unwrap();
26    println!("Value of derived: {derived_matches:#?}");
27}
Source

pub fn arg(self, a: impl Into<Arg>) -> Command

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?
examples/tutorial_builder/02_apps.rs (line 7)
3fn main() {
4    let matches = Command::new("MyApp")
5        .version("1.0")
6        .about("Does awesome things")
7        .arg(arg!(--two <VALUE>).required(true))
8        .arg(arg!(--one <VALUE>).required(true))
9        .get_matches();
10
11    println!(
12        "two: {:?}",
13        matches.get_one::<String>("two").expect("required")
14    );
15    println!(
16        "one: {:?}",
17        matches.get_one::<String>("one").expect("required")
18    );
19}
More examples
Hide additional examples
examples/derive_ref/flatten_hand_args.rs (lines 39-44)
38    fn augment_args(cmd: Command) -> Command {
39        cmd.arg(
40            Arg::new("foo")
41                .short('f')
42                .long("foo")
43                .action(ArgAction::SetTrue),
44        )
45        .arg(
46            Arg::new("bar")
47                .short('b')
48                .long("bar")
49                .action(ArgAction::SetTrue),
50        )
51        .arg(
52            Arg::new("quuz")
53                .short('q')
54                .long("quuz")
55                .action(ArgAction::Set),
56        )
57    }
58    fn augment_args_for_update(cmd: Command) -> Command {
59        cmd.arg(
60            Arg::new("foo")
61                .short('f')
62                .long("foo")
63                .action(ArgAction::SetTrue),
64        )
65        .arg(
66            Arg::new("bar")
67                .short('b')
68                .long("bar")
69                .action(ArgAction::SetTrue),
70        )
71        .arg(
72            Arg::new("quuz")
73                .short('q')
74                .long("quuz")
75                .action(ArgAction::Set),
76        )
77    }
examples/derive_ref/augment_args.rs (line 10)
9fn main() {
10    let cli = Command::new("CLI").arg(arg!(-b - -built).action(clap::ArgAction::SetTrue));
11    // Augment built args with derived args
12    let cli = DerivedArgs::augment_args(cli);
13
14    let matches = cli.get_matches();
15    println!("Value of built: {:?}", matches.get_flag("built"));
16    println!(
17        "Value of derived via ArgMatches: {:?}",
18        matches.get_flag("derived")
19    );
20
21    // Since DerivedArgs implements FromArgMatches, we can extract it from the unstructured ArgMatches.
22    // This is the main benefit of using derived arguments.
23    let derived_matches = DerivedArgs::from_arg_matches(&matches)
24        .map_err(|err| err.exit())
25        .unwrap();
26    println!("Value of derived: {derived_matches:#?}");
27}
examples/multicall-busybox.rs (lines 21-29)
13fn main() {
14    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
15        .multicall(true)
16        .subcommand(
17            Command::new("busybox")
18                .arg_required_else_help(true)
19                .subcommand_value_name("APPLET")
20                .subcommand_help_heading("APPLETS")
21                .arg(
22                    Arg::new("install")
23                        .long("install")
24                        .help("Install hardlinks for all subcommands in path")
25                        .exclusive(true)
26                        .action(ArgAction::Set)
27                        .default_missing_value("/usr/local/bin")
28                        .value_parser(value_parser!(PathBuf)),
29                )
30                .subcommands(applet_commands()),
31        )
32        .subcommands(applet_commands());
33
34    let matches = cmd.get_matches();
35    let mut subcommand = matches.subcommand();
36    if let Some(("busybox", cmd)) = subcommand {
37        if cmd.contains_id("install") {
38            unimplemented!("Make hardlinks to the executable here");
39        }
40        subcommand = cmd.subcommand();
41    }
42    match subcommand {
43        Some(("false", _)) => exit(1),
44        Some(("true", _)) => exit(0),
45        _ => unreachable!("parser should ensure only valid subcommand names are used"),
46    }
47}
examples/git.rs (line 15)
6fn cli() -> Command {
7    Command::new("git")
8        .about("A fictional versioning CLI")
9        .subcommand_required(true)
10        .arg_required_else_help(true)
11        .allow_external_subcommands(true)
12        .subcommand(
13            Command::new("clone")
14                .about("Clones repos")
15                .arg(arg!(<REMOTE> "The remote to clone"))
16                .arg_required_else_help(true),
17        )
18        .subcommand(
19            Command::new("diff")
20                .about("Compare two commits")
21                .arg(arg!(base: [COMMIT]))
22                .arg(arg!(head: [COMMIT]))
23                .arg(arg!(path: [PATH]).last(true))
24                .arg(
25                    arg!(--color <WHEN>)
26                        .value_parser(["always", "auto", "never"])
27                        .num_args(0..=1)
28                        .require_equals(true)
29                        .default_value("auto")
30                        .default_missing_value("always"),
31                ),
32        )
33        .subcommand(
34            Command::new("push")
35                .about("pushes things")
36                .arg(arg!(<REMOTE> "The remote to target"))
37                .arg_required_else_help(true),
38        )
39        .subcommand(
40            Command::new("add")
41                .about("adds things")
42                .arg_required_else_help(true)
43                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
44        )
45        .subcommand(
46            Command::new("stash")
47                .args_conflicts_with_subcommands(true)
48                .flatten_help(true)
49                .args(push_args())
50                .subcommand(Command::new("push").args(push_args()))
51                .subcommand(Command::new("pop").arg(arg!([STASH])))
52                .subcommand(Command::new("apply").arg(arg!([STASH]))),
53        )
54}
examples/pacman.rs (lines 17-25)
3fn main() {
4    let matches = Command::new("pacman")
5        .about("package manager utility")
6        .version("5.2.1")
7        .subcommand_required(true)
8        .arg_required_else_help(true)
9        // Query subcommand
10        //
11        // Only a few of its arguments are implemented below.
12        .subcommand(
13            Command::new("query")
14                .short_flag('Q')
15                .long_flag("query")
16                .about("Query the package database.")
17                .arg(
18                    Arg::new("search")
19                        .short('s')
20                        .long("search")
21                        .help("search locally installed packages for matching strings")
22                        .conflicts_with("info")
23                        .action(ArgAction::Set)
24                        .num_args(1..),
25                )
26                .arg(
27                    Arg::new("info")
28                        .long("info")
29                        .short('i')
30                        .conflicts_with("search")
31                        .help("view package information")
32                        .action(ArgAction::Set)
33                        .num_args(1..),
34                ),
35        )
36        // Sync subcommand
37        //
38        // Only a few of its arguments are implemented below.
39        .subcommand(
40            Command::new("sync")
41                .short_flag('S')
42                .long_flag("sync")
43                .about("Synchronize packages.")
44                .arg(
45                    Arg::new("search")
46                        .short('s')
47                        .long("search")
48                        .conflicts_with("info")
49                        .action(ArgAction::Set)
50                        .num_args(1..)
51                        .help("search remote repositories for matching strings"),
52                )
53                .arg(
54                    Arg::new("info")
55                        .long("info")
56                        .conflicts_with("search")
57                        .short('i')
58                        .action(ArgAction::SetTrue)
59                        .help("view package information"),
60                )
61                .arg(
62                    Arg::new("package")
63                        .help("packages")
64                        .required_unless_present("search")
65                        .action(ArgAction::Set)
66                        .num_args(1..),
67                ),
68        )
69        .get_matches();
70
71    match matches.subcommand() {
72        Some(("sync", sync_matches)) => {
73            if sync_matches.contains_id("search") {
74                let packages: Vec<_> = sync_matches
75                    .get_many::<String>("search")
76                    .expect("contains_id")
77                    .map(|s| s.as_str())
78                    .collect();
79                let values = packages.join(", ");
80                println!("Searching for {values}...");
81                return;
82            }
83
84            let packages: Vec<_> = sync_matches
85                .get_many::<String>("package")
86                .expect("is present")
87                .map(|s| s.as_str())
88                .collect();
89            let values = packages.join(", ");
90
91            if sync_matches.get_flag("info") {
92                println!("Retrieving info for {values}...");
93            } else {
94                println!("Installing {values}...");
95            }
96        }
97        Some(("query", query_matches)) => {
98            if let Some(packages) = query_matches.get_many::<String>("info") {
99                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
100                println!("Retrieving info for {comma_sep}...");
101            } else if let Some(queries) = query_matches.get_many::<String>("search") {
102                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
103                println!("Searching Locally for {comma_sep}...");
104            } else {
105                println!("Displaying all locally installed packages...");
106            }
107        }
108        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
109    }
110}
Source

pub fn args(self, args: impl IntoIterator<Item = impl Into<Arg>>) -> Command

Adds multiple arguments to the list of valid possibilities.

§Examples
Command::new("myprog")
    .args([
        arg!(-d --debug "turns on debugging info"),
        Arg::new("input").help("the input file to use")
    ])
Examples found in repository?
examples/git.rs (line 49)
6fn cli() -> Command {
7    Command::new("git")
8        .about("A fictional versioning CLI")
9        .subcommand_required(true)
10        .arg_required_else_help(true)
11        .allow_external_subcommands(true)
12        .subcommand(
13            Command::new("clone")
14                .about("Clones repos")
15                .arg(arg!(<REMOTE> "The remote to clone"))
16                .arg_required_else_help(true),
17        )
18        .subcommand(
19            Command::new("diff")
20                .about("Compare two commits")
21                .arg(arg!(base: [COMMIT]))
22                .arg(arg!(head: [COMMIT]))
23                .arg(arg!(path: [PATH]).last(true))
24                .arg(
25                    arg!(--color <WHEN>)
26                        .value_parser(["always", "auto", "never"])
27                        .num_args(0..=1)
28                        .require_equals(true)
29                        .default_value("auto")
30                        .default_missing_value("always"),
31                ),
32        )
33        .subcommand(
34            Command::new("push")
35                .about("pushes things")
36                .arg(arg!(<REMOTE> "The remote to target"))
37                .arg_required_else_help(true),
38        )
39        .subcommand(
40            Command::new("add")
41                .about("adds things")
42                .arg_required_else_help(true)
43                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
44        )
45        .subcommand(
46            Command::new("stash")
47                .args_conflicts_with_subcommands(true)
48                .flatten_help(true)
49                .args(push_args())
50                .subcommand(Command::new("push").args(push_args()))
51                .subcommand(Command::new("pop").arg(arg!([STASH])))
52                .subcommand(Command::new("apply").arg(arg!([STASH]))),
53        )
54}
Source

pub fn mut_arg<F>(self, arg_id: impl AsRef<str>, f: F) -> Command
where F: FnOnce(Arg) -> Arg,

Allows one to mutate an Arg after it’s been added to a Command.

§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());
Source

pub fn mut_args<F>(self, f: F) -> Command
where F: FnMut(Arg) -> Arg,

Allows one to mutate all Args after they’ve been added to a