我正在尝试构建 cli,它应该将
<command_name>
作为第一个参数,<path_to_file>
作为最后一个参数和介于两者之间的选项,因此在控制台中调用将如下所示:
programm command_one --option True file.txt
我有这样的设置:
// ./src/main.rs
use clap::{Args, Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Args, Debug)]
struct CommandOneArgs {
file: String,
#[arg(short, long)]
option_for_one: Option<String>,
}
#[derive(Args, Debug)]
struct CommandTwoArgs {
file: String,
#[arg(short, long)]
option_for_two: Option<String>,
}
#[derive(Subcommand, Debug)]
enum Commands {
CmdOne(CommandOneArgs)
CmdTwo(CommandTwoArgs)
}
fn main() {
let args = Cli::parse();
match &args.command {
Commands::CmdOne(cmd_args) => {println!({:?}, cmd_args)}
Commands::CmdTwo(cmd_args) => {println!({:?}, cmd_args)}
_ => {}
}
但这是我未能解决的问题:
实际上,在匹配的分支中,我会用获得的参数调用一些函数;
但是我需要为所有命令做通用的准备工作,例如从路径读取文件
所以在匹配表达式之前我需要提取
file
属性:
fn main() {
let args = Cli::parse();
/// something like that
// let file_path = args.command.file;
// println!("reading from: {}", file_path)
match &args.command {
Commands::CmdOne(cmd_args) => {println!({:?}, cmd_args)}
Commands::CmdTwo(cmd_args) => {println!({:?}, cmd_args)}
_ => {}
}
我不能像评论那样那样做。
而且我不能将位置参数添加到
Cli
结构,因为接口看起来像:programm <POSITIONAL ARG> command_one ...
将检索
file
参数的值的逻辑抽象为 Commands
和 Cli
上的方法是否适合您?像这样的东西:
use clap::{Args, Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
impl Cli {
fn file(&self) -> &str {
self.command.file()
}
}
#[derive(Args, Debug)]
struct CommandOneArgs {
file: String,
#[arg(short, long)]
option_for_one: Option<String>,
}
#[derive(Args, Debug)]
struct CommandTwoArgs {
file: String,
#[arg(short, long)]
option_for_two: Option<String>,
}
#[derive(Subcommand, Debug)]
enum Commands {
CmdOne(CommandOneArgs),
CmdTwo(CommandTwoArgs),
}
impl Commands {
fn file(&self) -> &str {
match self {
Self::CmdOne(args) => &args.file,
Self::CmdTwo(args) => &args.file,
}
}
}
fn main() {
let args = Cli::parse();
let file_path = args.file();
println!("{file_path}");
}
打印
hello
如果我运行cargo run -- cmd-one hello
.