I trying to build cli which should take <command_name>
as first argument, <path_to_file>
as last argument and options in between, so call in console would look like this:
programm command_one --option True file.txt
I have setup like this:
// ./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)}
_ => {}
}
But here is the problem which i am failing to solve:
In reality in branches of match i will call some functions with obtained args;
However i need to do preparation common for all commands, e.g. read file from path
So before matching expression i need to extract file
attribute:
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)}
_ => {}
}
I can not do that in a way like commented.
And I can not add position argument to Cli
struct because then interface would look like: programm <POSITIONAL ARG> command_one ...
I have assumptions that I should use generics, but I do not know how.