From f9e2e2680976c51593178d57004ecb4259112297 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Tue, 9 Apr 2024 19:12:40 +0200 Subject: [PATCH] Parse all valid arguments accepted by GNU diff to request a regular context (with an optional number of lines) --- src/params.rs | 110 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 17 deletions(-) diff --git a/src/params.rs b/src/params.rs index c0fdd32..f5ac0ee 100644 --- a/src/params.rs +++ b/src/params.rs @@ -62,6 +62,8 @@ pub fn parse_params>(opts: I) -> Result\d+)$").unwrap(); + let context_re = + Regex::new(r"^(-[cC](?\d*)|--context(=(?\d*))?|-(?\d+)c)$").unwrap(); let unified_re = Regex::new(r"^(-[uU](?\d*)|--unified(=(?\d*))?|-(?\d+)u)$").unwrap(); while let Some(param) = opts.next() { @@ -106,6 +108,40 @@ pub fn parse_params>(opts: I) -> Result().unwrap()); + } + if param == "-C" { + let next_param = opts.peek(); + if next_param.is_some() { + let next_value = next_param + .unwrap() + .to_string_lossy() + .as_ref() + .parse::(); + if next_value.is_ok() { + context_count = Some(next_value.unwrap()); + opts.next(); + } else { + return Err(format!( + "invalid context length '{}'", + next_param.unwrap().to_string_lossy() + )); + } + } + } + continue; + } if unified_re.is_match(param.to_string_lossy().as_ref()) { if format.is_some() && format != Some(Format::Unified) { return Err("Conflicting output style options".to_string()); @@ -143,25 +179,8 @@ pub fn parse_params>(opts: I) -> Result { - context_count = Some((b - b'0') as usize); - while let Some(b'0'..=b'9') = bit.peek() { - context_count = Some(context_count.unwrap() * 10); - context_count = Some( - context_count.unwrap() + (bit.next().unwrap() - b'0') as usize, - ); - } - } - b'c' => { - if format.is_some() && format != Some(Format::Context) { - return Err("Conflicting output style options".to_string()); - } - format = Some(Format::Context); - } b'e' => { if format.is_some() && format != Some(Format::Ed) { return Err("Conflicting output style options".to_string()); @@ -230,6 +249,63 @@ mod tests { ); } #[test] + fn context_valid() { + for args in [vec!["-c"], vec!["--context"], vec!["--context="]] { + let mut params = vec!["diff"]; + params.extend(args); + params.extend(["foo", "bar"]); + assert_eq!( + Ok(Params { + from: os("foo"), + to: os("bar"), + format: Format::Context, + ..Default::default() + }), + parse_params(params.iter().map(|x| os(x))) + ); + } + for args in [ + vec!["-c42"], + vec!["-C42"], + vec!["-C", "42"], + vec!["--context=42"], + vec!["-42c"], + ] { + let mut params = vec!["diff"]; + params.extend(args); + params.extend(["foo", "bar"]); + assert_eq!( + Ok(Params { + from: os("foo"), + to: os("bar"), + format: Format::Context, + context_count: 42, + ..Default::default() + }), + parse_params(params.iter().map(|x| os(x))) + ); + } + } + #[test] + fn context_invalid() { + for args in [ + vec!["-c", "42"], + vec!["-c=42"], + vec!["-c="], + vec!["-C"], + vec!["-C=42"], + vec!["-C="], + vec!["--context42"], + vec!["--context", "42"], + vec!["-42C"], + ] { + let mut params = vec!["diff"]; + params.extend(args); + params.extend(["foo", "bar"]); + assert!(parse_params(params.iter().map(|x| os(x))).is_err()); + } + } + #[test] fn unified_valid() { for args in [vec!["-u"], vec!["--unified"], vec!["--unified="]] { let mut params = vec!["diff"];