简介
clap-rs
是类似于 Python 标准库中argparse
的一个命令行解析,参数和子命令解析器。
安装
- 使用
cargo
安装clap-rs
cargo add clap
- 或者可以在
Cargo.toml
中手动添加
clap = "3.2"
用法
clap-rs
提供派生(derive
)和生成器(builder)两种使用方式。
派生
使用派生时,可以通过结构体(struct
)创建命令行应用。
需要添加使用
derive
特性。
- 使用
cargo
添加clap
时,带上需要的特性。cargo add clap --features derive
- 或者在
Cargo.toml
中添加。clap = { version = "3.2", features = ["derive"]}
use std::path::PathBuf;
use clap::{Parser, Subcommand};
/// 这里clap配置省略了作者、版本等信息
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
struct Cli {
// 使用Option表示这个参数是可选的,value_parser表示解析方式
#[clap(value_parser)]
name: Option<String>,
// short和long表示命令选项,有-c和-config两种方式。
// value_name可以指定在帮助提示中,参数值的显示名称:
// --config <FILE>
#[clap(short, long, value_parser, value_name = "FILE")]
config: Option<PathBuf>,
// 这里绑定了解析命令,可以计算参数出现的次数
#[clap(short, long, action = clap::ArgAction::Count)]
debug: u8,
// 子命令
#[clap(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Test {
// 测试列举
#[clap(short, long, action)]
list: bool,
},
}
fn main() {
let cli = Cli::parse();
// 用if let检测选项或者参数
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());
}
// 可以显示选项出现的次数
// 比如-dd对应2,输出Debug mode is on
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"),
}
// 检测子命令,注意bool型这里的解引用。
match &cli.command {
Some(Commands::Test { list }) => {
if *list {
println!("Printing testing lists...");
} else {
println!("Not printing testing lists...");
}
}
None => {}
}
}
生成器
生成器方式是clap
里默认的方式,不需要导入其他特性。
跟派生不同的是,生成器使用链式函数和宏命令生成应用。
匹配参数和解析部分大致相同,不再赘述。
use std::path::PathBuf;
use clap::{arg, command, value_parser, ArgAction, Command};
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("author <email@xxx.com>")
.about("Does awesome things")
.arg(arg!([name] "Optional name to operate on"))
.arg(
arg!(
-c --config <FILE> "Sets a custom config file"
)
// 通过required表示是否可选
.required(false)
.value_parser(value_parser!(PathBuf)),
)
.arg(
arg!(
-d --debug "Turn debugging information on"
)
.action(ArgAction::Count),
)
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "lists test values").action(ArgAction::SetTrue)),
)
.get_matches();
if let Some(name) = matches.get_one::<String>("name") {
println!("Value for name: {}", name);
}
if let Some(config_path) = matches.get_one::<PathBuf>("config") {
println!("Value for config: {}", config_path.display());
}
match matches
.get_one::<u8>("debug")
.expect("Count's are defaulted")
{
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"),
}
if let Some(matches) = matches.subcommand_matches("test") {
// 运行myapp test
if *matches.get_one::<bool>("list").expect("defaulted by clap") {
// 运行myapp test -l时
println!("Printing testing lists...");
} else {
println!("Not printing testing lists...");
}
}
}
更多,更详细的内容建议参考官方的文档。用法和示例都比较详细。