Command-Line Argument Parsing with structopt
This challenge focuses on leveraging the structopt crate in Rust to elegantly parse command-line arguments. You will create a Rust program that accepts various command-line options and subcommands, demonstrating how structopt simplifies the process of mapping these arguments to a structured representation. This is a fundamental skill for building robust and user-friendly command-line applications in Rust.
Problem Description
Your task is to build a simple command-line utility that performs different operations based on user-provided arguments. You will use the structopt crate to define the structure of your command-line interface (CLI) and automatically handle the parsing of arguments.
Specifically, your program should:
- Define a main CLI structure: This structure will hold global options and subcommands.
- Implement at least two subcommands: Each subcommand should have its own set of arguments.
- Support different argument types: Include string, integer, and boolean arguments.
- Handle optional arguments: Demonstrate how to make arguments optional.
- Parse and display the arguments: Upon execution, the program should print a nicely formatted representation of the parsed arguments, showing which subcommand was invoked and its associated parameters.
Consider the following when implementing:
- Argument Naming:
structoptuses Rust's field names and attributes to infer command-line argument names. - Subcommand Structure:
structoptallows you to define subcommands using anenum. - Default Values: Implement default values for certain optional arguments.
- Help Messages: Ensure that meaningful help messages are generated by
structoptfor your arguments and subcommands.
Examples
Example 1: add subcommand
Input:
./my_cli add --name "Alice" --age 30 --verbose
Output:
Operation: Add
Name: Alice
Age: 30
Verbose: true
Explanation: The program parses the add subcommand with the provided name, age, and verbose flags.
Example 2: greet subcommand with optional argument
Input:
./my_cli greet --person Bob
Output:
Operation: Greet
Person: Bob
Greeting: Hello
Explanation: The greet subcommand is invoked. The person argument is provided, and since the greeting argument is optional and not provided, its default value is used.
Example 3: greet subcommand with optional argument and custom greeting
Input:
./my_cli greet --person Charlie --greeting "Good morning"
Output:
Operation: Greet
Person: Charlie
Greeting: Good morning
Explanation: The greet subcommand is invoked with a custom greeting.
Example 4: Help message
Input:
./my_cli --help
Output:
Usage: my_cli [OPTIONS] <SUBCOMMAND>
Options:
-h, --help Print help information
Subcommands:
add Add a new entry
greet Greet a person
Explanation: structopt automatically generates help messages based on your struct and enum definitions.
Constraints
- The program must be written in Rust.
- The
structoptcrate must be used for argument parsing. - The program must compile and run without errors.
- The output for each example must match the provided output format exactly.
- The
addsubcommand should have a required--name(String), a required--age(u32), and an optional--verbose(bool) flag. - The
greetsubcommand should have a required--person(String) and an optional--greeting(String) with a default value of "Hello".
Notes
- You'll need to add
structoptas a dependency in yourCargo.toml. - Consider using
#[derive(StructOpt)]for your main struct and#[derive(StructOpt)]for your subcommand enum. - Use
#[structopt(about = "...")]and#[structopt(long_help = "...")]for better help messages. - Pay attention to how you define argument names, types, and attributes (
required,default_value,short,long).