I'm trying to develop a simple cli bill manager in rust using clap. I want to let the user add new bills by entering its name and value, remove some bills, and I also want to add undo and redo features. As it is my first project in rust, I called it p1. In the terminal, the user must do like this:
p1 -n bill1 -v 50
And then, the bill will be added or
p1 undo 5
Then, the last 5 actions will be undone. But, because of the usual functioning of clap, at least as far as I understood, this behavior is also accepted:
p1 -n bill2 -v 30 redo 30
And I don't want to allow it. I don't want to let the user use flags and subcommands at the same time. So I made some validation. To make it easier for you to help me I will show the pertinent part of the code.
use clap::{Parser, Subcommand};
use std::{collections::HashMap, path::PathBuf};
use home::home_dir;
use std::fs;
#[derive(Parser, Debug)]
struct Args {
/// The name of the bill
#[clap(short, long, value_parser)]
name: Option<String>,
/// The value of the bill
#[clap(short, long, value_parser)]
value: Option<u32>,
#[clap(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Undo
Undo { undo: Option<u32> },
/// Redo
Redo { redo: Option<u32> },
/// Remove
Remove { remove: Option<String> },
}
fn validate_args(args: Args) -> Result<Args, String> {
match (&args.name, &args.value, &args.command) {
(Some(_), Some(_), None) => Ok(args),
(None, None, Some(_)) => Ok(args),
(None, None, None) => Ok(args),
_ => Err("You can't use options and subcommands at the same time".to_string())
}
}
fn exit_on_error(error: &Result<Args, String>) {
println!("{:?}", error);
panic!("aaaaaaaaaaaaaaaaaa");
}
fn main() {
let args: Result<Args, String> = validate_args(Args::parse());
match args {
Ok(_) => (),
Err(_) => exit_on_error(&args)
};
...
}
Another thing I need help is. When the user do not insert neither flags nor subcommands, just typing "p1" in the terminal, I want to redirect him to the help subcommand as if he had typed
p1 help
How can I do it?
And also, I'm still not used to the rust style of handle with variable possession. The "exit_on_error" function can only receive borrowed results because, apparently, strings cannot implement Copy. This prevents me to unwrap the Err before printing it, which makes it appears with quotation marks in the terminal. What should I do to workaround It?
Please help me and let me know if something isn't clear in my question.