clap

Derive 教程

快速开始

添加 clap derive 依赖

cargo add clap --features derive

预览一个应用程序

use std::path::PathBuf;

use clap::{Parser, Subcommand};

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    /// 要操作的名字
    name: Option<String>,

    /// 设置自定义配置文件
    #[arg(short, long, value_name = "FILE")]
    config: Option<PathBuf>,

    /// 开启调试
    #[arg(short, long, action = clap::ArgAction::Count)]
    debug: u8,

    /// 子命令
    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand)]
enum Commands {
    /// 测试
    Test {
        /// 列出测试的值
        #[arg(short, long)]
        list: bool,
    },
}

fn main() {
    let cli = Cli::parse();

    // You can check the value provided by positional arguments, or option arguments
    if let Some(name) = cli.name.as_deref() {
        println!("Value for name: {name}");
    }

    if let Some(config_path) = cli.config.as_deref() {
        println!("Value for config: {}", config_path.display());
    }

    // You can see how many times a particular flag or argument occurred
    // Note, only flags can have multiple occurrences
    match cli.debug {
        0 => println!("Debug mode is off"),
        1 => println!("Debug mode is kind of on"),
        2 => println!("Debug mode is on"),
        _ => println!("Don't be crazy"),
    }

    // 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 {
        Some(Commands::Test { list }) => {
            if *list {
                println!("Printing testing lists...");
            } else {
                println!("Not printing testing lists...");
            }
        }
        None => {}
    }

}

配置 Parser

代码指定

use clap::Parser;

#[derive(Parser)]
#[command(name = "MyApp")]
#[command(version = "1.0")]
#[command(about = "Does awesome things", long_about = None)]
struct Cli {
    name: Vec<String>,
    #[arg(long)]
    two: String,
    #[arg(long)]
    one: String,
}

fn main() {
    let cli = Cli::parse();
    println!("name: {:?}", cli.name);
    println!("two: {:?}", cli.two);
    println!("one: {:?}", cli.one);
}

运行程序

$ cargo run -- --help
# 查看帮助信息
Does awesome things

Usage: clap_config --two <TWO> --one <ONE>

Options:
      --two <TWO>
      --one <ONE>
  -h, --help       Print help
  -V, --version    Print version

$ cargo run -- --version
# 查看版本
MyApp 1.0

$ cargo run -- --two=2 --one=1
# 程序输出获取的参数
two: "2"
one: "1"

从 cargo.toml 读取

use clap::Parser;

#[derive(Parser)]
#[command(name = "MyApp")]
#[command(version, about)]
struct Cli {
    #[arg(long)]
    two: String,
    #[arg(long)]
    one: String,
}

fn main() {
    let cli = Cli::parse();
    println!("two: {:?}", cli.two);
    println!("one: {:?}", cli.one);
}

cargo.toml

[package]
name = "clap_config_from_cargo"
version = "0.1.0"
edition = "2024"
authors = ["hanjian <hanjian@zhouyi.com>"]
description = "A simple CLI app using clap"

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

运行命令查看

$ cargo run -- --help

A simple CLI app using clap

Usage: clap_config_from_cargo --two <TWO> --one <ONE>

Options:
      --two <TWO>
      --one <ONE>
  -h, --help       Print help
  -V, --version    Print version


cargo run -- -V
MyApp 0.1.0

next_line_help

use clap::Parser;

#[derive(Parser)]
#[command(name = "MyApp")]
#[command(version, about)]
#[command(next_line_help = true)]
struct Cli {
    #[arg(long)]
    two: String,
    #[arg(long)]
    one: String,
}

fn main() {
    let cli = Cli::parse();
    println!("two: {:?}", cli.two);
    println!("one: {:?}", cli.one);
}

执行程序查看结果,帮助信息会在下一行展示

$ cargo run -- --help
A simple CLI app using clap

Usage: clap_config_from_cargo --two <TWO> --one <ONE>

Options:
      --two <TWO>

      --one <ONE>

  -h, --help
          Print help
  -V, --version
          Print version

添加参数

位置参数

默认结构体字段会被定义为位置参数

use clap::Parser;

#[derive(Parser)]
#[command(name = "MyApp")]
#[command(version, about)]
#[command(next_line_help = true)]
struct Cli {
    name: String,
}

fn main() {
    let cli = Cli::parse();
    println!("name:{:?}", cli.name);
}

执行命令查看输出

$ cargo run -- hzx
name:"hzx"

接收多个值

use clap::Parser;

#[derive(Parser)]
#[command(name = "MyApp")]
#[command(version, about)]
struct Cli {
    name: Vec<String>,
}

fn main() {
    let cli = Cli::parse();
    println!("name:{:?}", cli.name);
}

执行命令并查看,可以接收多个值

$ cargo run -- hzx hj
name:["hzx", "hj"]

选项

可以使用 #[arg(short='n')]#[arg(long=name)] 属性在一个字段上。当没有值提供时如 #[arg(short,long)] 将会使用字段名称。

use clap::Parser;

struct Cli {
    #[arg(short, long)]
    name: String,
}
fn main() {
    let cli = Cli.parse();

    println!("name: {:?}", cli.name);
}

执行程序

$ cargo run -- --name bob
$ cargo run -- --name=bob
$ cargo run -- -n bob
$ cargo run -- -n=bob
$ cargo run -- -nbob

name: "bob"

接收多个值

use clap::Parser;

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    #[arg(short, long)]
    name: Vec<String>,
}

fn main() {
    let cli = Cli::parse();

    println!("name: {:?}", cli.name);
}
$ cargo run -- --name bob --name jam
name: ["bob", "jam"]

标志(Flags)

Flags 是一个开关,如果指定该参数就是开,不指定就是关

use clap::Parser;

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    #[arg(short, long)]
    verbose: bool,
}

fn main() {
    let cli = Cli::parse();

    println!("verbose: {:?}", cli.verbose);
}

执行程序并查看结果

$ cargo run -- -v
verbose: true
$ cargo run --
verbose: false

可选参数

use clap::Parser;

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    name: Option<String>,
}

fn main() {
    let cli = Cli::parse();

    println!("name: {:?}", cli.name);
}
$ cargo run
name: None
$ cargo run jam
name: Some("jam")

默认值

use clap::Parser;

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
    #[arg(default_value_t = 2020)]
    port: u16,

    #[arg(default_value = "127.0.0.1")]
    host: String,
}

fn main() {
    let cli = Cli::parse();

    println!("host: {:?}", cli.host);
    println!("port: {:?}", cli.port);
}
$ cargo run
host: "127.0.0.1"
port: 2020
$ cargo run 22
host: "127.0.0.1"
port: 22