Clap - positional command line arguments in Rust

arg positional required default_value

Part of the Clap series.

In most of the examples we used named parameters where the name has one or two dashes. Those are the most common cases for command line parameters, but sometimes, usually in simpler case we can use positional arguments as well.

If we only have one or one type of positional arguments, then we might be better off using std::env::args directly, but as we might want to combine positional arguments with named arguments, let's see how to handle these in Clap.

In order to have a positional parameter we don't need to provide the arg, we only need to define a struct and derive it from the clap::Parser:

#[derive(Parser)]
struct Cli {
    host: String,
}

In most cases positional arguments are required.

Nevertheless we can also defined a default_value in the same manner as we had default values for named command line parameters, but I think this would be rather rare.

#[derive(Parser)]
struct Cli {
    #[arg(default_value = "127.0.0.1")]
    host: String,
}

Accept multiple values

We can accept multiple values for the last positional argument, by defining it as a vector:

#[derive(Parser)]
struct Cli {
    host: String,

    ports: Vec<u16>,
}

In this case we can run the program like this:

$ cargo run -q 127.0.0.1 3000 5000

host:  127.0.0.1
ports: [3000, 5000]

but also without providing any value for the argument that will be stored in a vector:

$ cargo run -q 127.0.0.1
host:  127.0.0.1
ports: []

Required

If we would like to make sure that the user supplies at least one value for the ports argument in our example, we can mark it as required.

#[derive(Parser)]
struct Cli {
    host: String,

    #[arg(required = true)]
    ports: Vec<u16>,
}

Positional and named arguments

Finally, we can also mix the positional and the named arguments. Here test is a named argument.

#[derive(Parser)]
struct Cli {
    host: String,

    #[arg(required = true)]
    ports: Vec<u16>,

    #[arg(long)]
    test: String,
}

This is how we can use them:

$ cargo run -q 127.0.0.1 1000 --test acceptance

test:  acceptance
host:  127.0.0.1
ports: [1000]

Dependencies in Cargo.toml

examples/clap/positional/Cargo.toml

[package]
name = "positional"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "4.4.11", features = ["derive"] }

The full example

examples/clap/positional/src/main.rs

use clap::Parser;

#[derive(Parser)]
struct Cli {
    host: String,

    #[arg(required = true)]
    ports: Vec<u16>,

    #[arg(long)]
    test: String,
}

fn main() {
    let args = Cli::parse();
    println!("test:  {}", args.test);
    println!("host:  {}", args.host);
    println!("ports: {:?}", args.ports);
}

Related Pages

Clap - Command Line Argument Parser for Rust

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo