Getting Started with StructOpt

Installation

To start using StructOpt, you need to include it in your Cargo.toml file. Here’s how to set it up:

[dependencies]
structopt = "0.3"

Basic Usage

StructOpt allows you to define command-line arguments in a structured way using Rust structs. Below is a simple example that demonstrates how to create a CLI tool that accepts a name and an optional greeting flag.

use structopt::StructOpt;

/// A simple CLI tool to greet users
#[derive(StructOpt)]
struct Cli {
    /// The name of the user
    name: String,

    /// Optional greeting flag
    #[structopt(short, long)]
    greet: bool,
}

fn main() {
    let args = Cli::from_args();
    
    if args.greet {
        println!("Hello, {}!", args.name);
    } else {
        println!("Goodbye, {}!", args.name);
    }
}

Running the CLI Tool

You can compile and run your CLI tool using the following commands:

cargo build
cargo run -- --name Alice --greet

Output:

Hello, Alice!

If you run it without the --greet flag:

cargo run -- --name Bob

Output:

Goodbye, Bob!

Advanced Features

Subcommands

StructOpt supports subcommands, allowing you to create more complex CLI applications. Here’s an example that includes a greet subcommand and a farewell subcommand.

use structopt::StructOpt;

/// A CLI tool that greets and bids farewell
#[derive(StructOpt)]
struct Cli {
    #[structopt(subcommand)]
    command: Command,
}

#[derive(StructOpt)]
enum Command {
    /// Greet a user
    Greet {
        /// The name of the user
        name: String,
    },
    /// Bid farewell to a user
    Farewell {
        /// The name of the user
        name: String,
    },
}

fn main() {
    let args = Cli::from_args();

    match args.command {
        Command::Greet { name } => println!("Hello, {}!", name),
        Command::Farewell { name } => println!("Goodbye, {}!", name),
    }
}

Running Subcommands

You can run the subcommands like this:

cargo run -- greet Alice

Output:

Hello, Alice!

And for farewell:

cargo run -- farewell Bob

Output:

Goodbye, Bob!

Argument Validation

You can also implement validation for your arguments. For instance, you may want to ensure that the provided name is not empty. This can be done using the clap crate, which StructOpt is built upon.

#[derive(StructOpt)]
struct Cli {
    /// The name of the user
    #[structopt(validator = validate_name)]
    name: String,
}

fn validate_name(name: &str) -> Result<(), String> {
    if name.is_empty() {
        Err("Name cannot be empty".to_string())
    } else {
        Ok(())
    }
}

Environment Variable Support

StructOpt can also read values from environment variables. You can specify an environment variable for a field using the env attribute.

#[derive(StructOpt)]
struct Cli {
    /// The name of the user
    #[structopt(env = "USER_NAME")]
    name: String,
}

This allows users to set the USER_NAME environment variable, which will be used as the default value for the name argument.

Summary

Using StructOpt, you can create powerful and user-friendly CLI tools in Rust. The library provides a simple way to define command-line arguments, supports subcommands, and allows for argument validation and environment variable integration.

Comparison of StructOpt Features

FeatureDescription
SubcommandsOrganize commands into logical groups
Argument ValidationValidate inputs with custom functions
Environment VariablesRead default values from environment settings
Help and Usage OutputAutomatically generated help and usage messages

By leveraging these features, you can build sophisticated CLI applications that enhance user experience and functionality.

Learn more with useful resources