Reputation: 769
I am trying to have a CLI tool that redacts files in a folder according to some specified regexes.
In debugging, as an example:
cargo run -- folder ./tests/test_files -t emails ip -r
which means to redact all files in folder path = ./tests/test_files
and -r
means to do so recursively.
Below is a list of structs that attempted to achieve this:
use clap::{Parser, Subcommand, Args};
#[derive(Debug, Parser)]
#[clap(author, version, about, name = "raf")]
pub struct Opts {
#[clap(subcommand)]
pub cmd: FileOrFolder,
}
#[derive(Debug, Subcommand)]
pub enum FileOrFolder {
#[clap(name = "folder")]
Folder(FolderOpts),
#[clap(name = "file")]
File(FileOpts),
}
#[derive(Args, Debug)]
pub struct FolderOpts {
/// `path` of the directory in which all files should be redacted, e.g. ./tests/test_files
#[clap(parse(from_os_str), required = true)]
pub path: std::path::PathBuf,
/// The type of redaction to be applied to the files, e.g. -t sgNRIC emails
#[clap(short, long, required = true, multiple_values = true)]
pub types: Vec<String>,
#[clap(short, long, required = false, takes_value = false)]
pub recursive: Option<bool>,
}
This is the error that occurs during runtime:
Finished dev [unoptimized + debuginfo] target(s) in 45.31s
Running `target\debug\raf.exe folder ./tests/test_files -t sgNRIC email -r`
error: The argument '--recursive <RECURSIVE>' requires a value but none was supplied
For more information try --help
error: process didn't exit successfully: `target\debug\raf.exe folder ./tests/test_files -t sgNRIC email -r` (exit code: 2)
My question is, how do I write the struct FolderOpts
such that if -r
is present in as a parameter in the CLI arguments, it is parsed as .recursive
= true
and if it is absent, .recursive
= false
?
Upvotes: 5
Views: 2328
Reputation: 276
In clap you can set it like this:
use clap::{ArgAction, Parser};
/// Test
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Clean database
#[arg(short, long, action(ArgAction::SetTrue))]
clean: bool,
}
or use abbreviations
use clap::Parser;
/// Test
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Clean database
#[arg(short, long, action)]
clean: bool,
}
Cause default action is SetTrue
in clap ArgAction.
pub enum ArgAction {
Set,
Append,
SetTrue,
SetFalse,
Count,
Help,
HelpShort,
HelpLong,
Version,
}
If the user provides the --clean
parameter, this args.clean
value will become true
.
Upvotes: 1
Reputation: 222318
bool
options don't need to be wrapped in Option
to be optional. They are set to false
by default and true
if their name is passed as argument. This should work:
#[clap(short, long)]
pub recursive: bool,
Upvotes: 8