What about features not in standard Rust Library ?
Our cli can manage many subcommands but usage is not documented
How to build a cli with nice usage help ?
- add external libraries from crates.io
- use Clap as command line argument parser
Rust provides many libraries out of the box but at a time, we need specifics features
Crates.io is the defaut public repository where to search modules
💡 Notes
What about playing chifoumi with computer as opponent ?
2 ways to add dependency
cargo add rand
Updating crates.io index
Adding rand v0.8.5 to dependencies.
Features:
+ alloc
+ getrandom
+ libc
+ rand_chacha
+ std
+ std_rng
- log
- min_const_gen
- nightly
- packed_simd
- serde
- serde1
- simd_support
- small_rng
📚 Additional resources
- cargo add documentation (ex: specify version, features,etc)
Add dependency in cargo.toml
[dependencies]
rand = "0.8.5"Example of usage
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let n1: u8 = rng.gen();
println!("Random u8: {}", n1);
println!("Integer de 0 to 3 included: {}", rng.gen_range(0..=3));
}📚 Additional resources
Clap a commonly used crate for Cli application in Rust
With Derive feature, we can setup a Cli in few lines
// from clap doc.rs
use clap::Parser;
/// Simple program to greet a person
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// Name of the person to greet
#[clap(short, long, value_parser)]
name: String,
/// Number of times to greet
#[clap(short, long, value_parser, default_value_t = 1)]
count: u8,
}
fn main() {
let args = Args::parse();
for _ in 0..args.count {
println!("Hello {}!", args.name)
}
}$ demo --help
clap [..]
A simple to use, efficient, and full-featured Command Line Argument Parser
USAGE:
demo[EXE] [OPTIONS] --name <NAME>
OPTIONS:
-c, --count <COUNT> Number of times to greet [default: 1]
-h, --help Print help information
-n, --name <NAME> Name of the person to greet
-V, --version Print version information
$ demo --name Me
Hello Me!💡 Notes
- You can describe commands without annotation if you want
📚 Additional resources
Cargo "features" provide a mechanism to express conditional compilation and optional dependencies.
cargo add clap
Updating crates.io index
Adding clap v4.2.1 to dependencies.
Features:
+ color
+ error-context
+ help
+ std
+ suggestions
+ usage
- cargo
- debug
- deprecated
- derive
- env
- string
- unicode
- unstable-doc
- unstable-v5
- wrap_helpNote that Derive Feature is no enabled
📚 Additonal resource
use cargo add option -F (or --features)
cargo add clap -F deriveUpdate dependencies
[dependencies]
clap = { version = "4.2.1", features = ["derive"] }We want to have distinct options for each cli functionality (greets and chifoumi)
Clap provides functionality to create subcommand with struct and enum
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[clap(
author = "Julien Rollin",
version = "1.0.0",
about = "Crabby cli",
long_about = None
)]
#[clap(propagate_version = true)]
struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Adds files to myapp
Add { name: Option<String> },
/// Doc about other command
Greets {
/// Name of the person to greet
#[clap(short, long, value_parser)]
name: String,
},
}
fn main() {
let cli = Cli::parse();
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
match &cli.command {
Commands::Add { name } => {
println!("'myapp add' was used, name is: {:?}", name)
}
Commands::Greets { name } => {
println!("Name: {:?}", name)
}
}
}Try this command by yourself
cargo run
cargo run -- -V
cargo run -- greets --helpRefactor your app code with Clap and Subcommand
you shoud see beautiful cli usage when running your app
$ crabby --help
crabby 0.1.0
I am the crabby help usage.
USAGE:
crabby <SUBCOMMAND>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
chifoumi chifoumi with players
greets Greets with name
help Print this message or the help of the given subcommand(s)
If no player two is provided use a random game value for player 2
cargo run -- chifoumi -a paper
p1: Paper vs p2: Scissors => Lost
you can imagine building any cli now !
Check a solution with unit tests here
What you learned
- add crate with features
- parse and document usage of cli app with clap