use std::path::PathBuf;
use ::clap::Parser;
use ::regex::Regex;
#[derive(Parser, Debug)]
#[command(
name = "grab",
about = "Filter lines by regular expression, keeping only the matching capture group."
)]
pub struct GrabArgs {
#[arg(value_parser = valid_regex)]
pub pattern: String,
#[arg(short = 'i', long)]
pub input: Option<String>,
#[arg(short = 'p', long, conflicts_with = "input")]
pub path: Option<PathBuf>,
#[arg(short = 'f', long = "first-match-only")]
pub first_match_only: bool,
#[arg(short = '1', long)]
pub first_capture_only: bool,
#[arg(short = 'k', long)]
pub keep_unmatched: bool,
#[arg(short = 'n', long)]
pub max_lines: Option<u32>,
#[arg(short = 'e', long)]
pub expect_match: bool,
#[arg(short = 'E', long)]
pub expect_no_match: bool,
#[arg(short = 'c', long)]
pub case_sensitive: bool,
#[arg(short = 'q', long)]
pub quiet: bool,
}
fn valid_regex(inp: &str) -> Result<String, String> {
Regex::new(inp).map_err(|err| format!("invalid regex: {}", err))?;
Ok(inp.to_owned())
}
impl GrabArgs {
pub fn build_regex(&self) -> Regex {
if self.case_sensitive {
Regex::new(&self.pattern)
} else {
Regex::new(&format!("(?i){}", &self.pattern))
}.expect("invalid grab regex but should have been validated by cli")
}
}
impl Default for GrabArgs {
fn default() -> Self {
GrabArgs {
pattern: ".*".to_owned(),
input: None,
path: None,
first_match_only: false,
first_capture_only: false,
keep_unmatched: false,
max_lines: None,
expect_match: false,
expect_no_match: false,
case_sensitive: false,
quiet: false,
}
}
}
#[async_std::test]
async fn test_cli_args() {
GrabArgs::try_parse_from(&["cmd", "-f1kn", "5", "^.{5}$"]).unwrap();
}