语言
中文
English
导航菜单
← 返回 CLI
#clap#args#cli
用 clap derive 写子命令式 CLI
clap 是 Rust 事实标准的命令行解析器。它的 derive 模式把"参数定义"和"数据结构"统一成一件事:你声明一个结构体,clap 负责解析、校验、生成帮助和补全。
derive 的核心思路
把 CLI 的形状写成类型,解析后直接拿到强类型数据:
use clap::Parser;
#[derive(Parser)]
#[command(name = "rie", version, about = "Rust in Everything CLI")]
struct Cli {
/// 输出更详细的日志
#[arg(short, long)]
verbose: bool,
/// 重试次数
#[arg(long, default_value_t = 3)]
retries: u32,
/// 输入文件
input: std::path::PathBuf,
}
fn main() {
let cli = Cli::parse();
if cli.verbose {
eprintln!("reading {}", cli.input.display());
}
}
Cli::parse() 在参数非法时自动打印用法并以非零码退出——你拿到的 Cli 一定是合法的。这就是"让非法状态不可表示"在 CLI 层面的体现。
子命令 = 枚举
子命令天然对应枚举,每个变体带自己的参数:
use clap::{Parser, Subcommand};
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
/// 构建项目
Build {
#[arg(long)]
release: bool,
},
/// 部署到目标环境
Deploy {
/// 目标环境
target: String,
#[arg(long, default_value_t = false)]
dry_run: bool,
},
}
fn main() {
match Cli::parse().command {
Command::Build { release } => build(release),
Command::Deploy { target, dry_run } => deploy(&target, dry_run),
}
}
match 是穷尽的——加一个新子命令,编译器会逼你处理它。CLI 的分发逻辑因此永远不会漏分支。
校验与枚举值
用类型约束取值,而不是运行时 if:
use clap::ValueEnum;
#[derive(Clone, ValueEnum)]
enum Format { Json, Yaml, Toml }
#[derive(Parser)]
struct Cli {
#[arg(long, value_enum, default_value_t = Format::Json)]
format: Format,
}
传 --format xml 会被 clap 直接拒绝并提示合法取值,无需手写校验。
体验细节
#[arg(env = "RIE_TOKEN")]:参数可从环境变量回退,方便 CI 与本地共用。#[command(version)]:自动接--version,从Cargo.toml取版本号。clap_complete:生成 bash/zsh/fish 补全脚本。clap_mangen:生成 man page。
下一步
- 把输出做漂亮:indicatif 进度条 + console 彩色文本。
- 做交互式全屏界面:ratatui。
- 给 CLI 写端到端测试:assert_cmd 直接断言子进程的 stdout / 退出码。
clap derive 的价值不只是少写代码,而是把"参数协议"编码进类型系统——帮助文本、校验、补全全都从同一个真相来源生成,不会随时间漂移。
登录
选择一种方式继续
登录即表示你同意我们的服务条款和隐私政策
搜索
输入关键词开始搜索 · 支持中英文 · 按 ⌘K 随时打开