我正在尝试构建一个命令行界面,它应该将<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 ...
我有一些假设应该使用泛型,但我不知道如何使用。