官方参考: https://docs.rs/clap/4.5.1/clap/_derive/_tutorial/chapter_2
附加参数
- Postitionals, 位置参数
- Options, 选项参数
- Flags, 标志参数
- Subcommands, 子命令
- Defaults, 默认值
位置参数
你可以让用户按其在命令行上的位置指定值:
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.as_deref());
}
$ 03_03_positional_derive --help
用法: 03_03_positional_derive[EXE] [名称]
参数:
[名称]
选项:
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_03_positional_derive
name: None
$ 03_03_positional_derive bob
name: Some("bob")
需要注意默认的参数动作是设置(Set)。如果要接受多个值,则可以通过使用 Append 动作并通过 Vec 类型进行重写:
use clap::Parser;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
name: Vec<String>,
}
fn main() {
let cli = Cli::parse();
println!("name: {:?}", cli.name);
}
$ 03_03_positional_mult_derive --help
用法: 03_03_positional_mult_derive[EXE] [名称]...
参数:
[名称]...
选项:
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_03_positional_mult_derive
name: []
$ 03_03_positional_mult_derive bob
name: ["bob"]
$ 03_03_positional_mult_derive bob john
name: ["bob", "john"]
选项参数
你可以使用标志为参数命名:
- 顺序不重要
- 可选的
- 意图清晰
要为参数指定标志,可以在字段上使用 #[arg(short = 'n')]
和(或) #[arg(long = "name")]
属性。当没有给出值时(例如 #[arg(short)]
),标志将从字段的名称推断。
use clap::Parser;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
#[arg(short, long)]
name: Option<String>,
}
fn main() {
let cli = Cli::parse();
println!("name: {:?}", cli.name.as_deref());
}
$ 03_02_option_derive --help
用法: 03_02_option_derive[EXE] [选项]
选项:
-n, --name <名称>
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_02_option_derive
name: None
$ 03_02_option_derive --name bob
name: Some("bob")
$ 03_02_option_derive --name=bob
name: Some("bob")
$ 03_02_option_derive -n bob
name: Some("bob")
$ 03_02_option_derive -n=bob
name: Some("bob")
$ 03_02_option_derive -nbob
name: Some("bob")
需要注意默认的参数动作是设置(Set)。如果要接受多个值,则可以通过使用 Append 动作并通过 Vec 类型进行重写:
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);
}
$ 03_02_option_mult_derive --help
用法: 03_02_option_mult_derive[EXE] [选项]
选项:
-n, --name <名称>
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_02_option_mult_derive
name: []
$ 03_02_option_mult_derive --name bob
name: ["bob"]
$ 03_02_option_mult_derive --name=bob
name: ["bob"]
$ 03_02_option_mult_derive -n bob
name: ["bob"]
$ 03_02_option_mult_derive -n=bob
name: ["bob"]
$ 03_02_option_mult_derive -nbob
name: ["bob"]
标志参数
标志参数也可以是开关,可以是开或关:
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);
}
$ 03_01_flag_bool_derive --help
用法: 03_01_flag_bool_derive[EXE] [选项]
选项:
-v, --verbose
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_01_flag_bool_derive
verbose: false
$ 03_01_flag_bool_derive --verbose
verbose: true
$ 03_01_flag_bool_derive --verbose --verbose
? 失败
错误:参数 '--verbose' 不能多次使用
用法: 03_01_flag_bool_derive[EXE] [选项]
获取更多信息,请尝试 '--help'。
请注意,默认的 ArgAction
对于 bool
字段是 SetTrue
。要
接受多个标志,请通过 Count
来重写 action
属性:
use clap::Parser;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
}
fn main() {
let cli = Cli::parse();
println!("verbose: {:?}", cli.verbose);
}
$ 03_01_flag_count_derive --help
用法: 03_01_flag_count_derive[EXE] [选项]
选项:
-v, --verbose...
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_01_flag_count_derive
verbose: 0
$ 03_01_flag_count_derive --verbose
verbose: 1
$ 03_01_flag_count_derive --verbose --verbose
verbose: 2
这还表明任何 Arg
方法都可以用作属性。
子命令
子命令使用 #[derive(Subcommand)]
派生,通过在使用该类型的字段上使用 #[command(subcommand)]
属性添加。每个 Subcommand
实例都可以有自己的版本、作者、参数,甚至可以有自己的子命令。
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// 添加文件到 myapp
Add { name: Option<String> },
}
fn main() {
let cli = Cli::parse();
// 你可以检查是否存在子命令,并在找到时使用它们的匹配,就像处理顶级命令一样
match &cli.command {
Commands::Add { name } => {
println!("'myapp add' 被使用,名称是: {name:?}")
}
}
}
我们使用了结构体变体来定义 add
子命令。或者,你也可以使用结构体来定义子命令的参数:
use clap::{Args, Parser, Subcommand};
#[derive(Parser)]
#[command(version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// 添加文件到 myapp
Add(AddArgs),
}
#[derive(Args)]
struct AddArgs {
name: Option<String>,
}
fn main() {
let cli = Cli::parse();
// 你可以检查是否存在子命令,并在找到时使用它们的匹配,就像处理顶级命令一样
match &cli.command {
Commands::Add(name) => {
println!("'myapp add' 被使用,名称是: {:?}", name.name)
}
}
}
$ 03_04_subcommands_derive help
用法: 03_04_subcommands_derive[EXE] <命令>
命令:
add 添加文件到 myapp
help 打印此消息或给定子命令的帮助信息
选项:
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_04_subcommands_derive help add
添加文件到 myapp
用法: 03_04_subcommands_derive[EXE] add [名称]
参数:
[名称]
选项:
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_04_subcommands_derive add bob
'myapp add' 被使用,名称是: Some("bob")
当指定命令时,它们是必需的。或者,你可以使用 command: Option<Commands>
来使其可选。
$ 03_04_subcommands_derive
? 失败
用法: 03_04_subcommands_derive[EXE] <命令>
命令:
add 添加文件到 myapp
help 打印此消息或给定子命令的帮助信息
选项:
-h, --help 打印帮助信息
-V, --version 打印版本号
由于我们指定了 #[command(propagate_version = true)]
,因此 --version
标志在所有子命令中都可用:
$ 03_04_subcommands_derive --version
clap [..]
$ 03_04_subcommands_derive add --version
clap-add [..]
默认值
我们之前展示了参数可以是 required
或可选的。当可选时,你可以使用 Option
并且可以 unwrap_or
。或者,你可以设置 #[arg(default_value_t)]
。
use clap::Parser;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli
{
#[arg(default_value_t = 2020)]
port: u16,
}
fn main() {
let cli = Cli::parse();
println!("port: {:?}", cli.port);
}
$ 03_05_default_values_derive --help
用法: 03_05_default_values_derive[EXE] [端口]
参数:
[端口] [默认值: 2020]
选项:
-h, --help 打印帮助信息
-V, --version 打印版本号
$ 03_05_default_values_derive
port: 2020
$ 03_05_default_values_derive 22
port: 22