From 32ffdfe85530d9569efb58983e5b630bda414d53 Mon Sep 17 00:00:00 2001 From: CreepySkeleton Date: Mon, 20 Apr 2020 13:28:50 +0300 Subject: [PATCH] Correctly handle `-f==a` (value is `=a`) --- src/parse/parser.rs | 9 ++++----- src/util/osstringext.rs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 0d1d1e52..1046bdf3 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1215,7 +1215,7 @@ where p[1].as_bytes() ); let i = p[0].as_bytes().len() + 1; - let val = if !p[1].as_bytes().is_empty() { + let val = if !p[1].is_empty() { debugln!( "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii)", c, @@ -1228,11 +1228,10 @@ where }; // Default to "we're expecting a value later" - let ret = self.parse_opt(val, opt, false, matcher)?; - - return Ok(ret); + return self.parse_opt(val, opt, false, matcher); } else { let arg = format!("-{}", c); + return Err(ClapError::unknown_argument( &*arg, None, @@ -1262,7 +1261,7 @@ where debug!("Parser::parse_opt; Checking for val..."); if let Some(fv) = val { has_eq = fv.starts_with(&[b'=']) || had_eq; - let v = fv.trim_start_matches(b'='); + let v = fv.trim_start_n_matches(1, b'='); if !empty_vals && (v.is_empty() || (needs_eq && !has_eq)) { sdebugln!("Found Empty - Error"); return Err(ClapError::empty_value( diff --git a/src/util/osstringext.rs b/src/util/osstringext.rs index 22d4ee62..f41b7d9b 100644 --- a/src/util/osstringext.rs +++ b/src/util/osstringext.rs @@ -15,6 +15,7 @@ pub(crate) trait OsStrExt2 { fn split_at_byte(&self, b: u8) -> (&OsStr, &OsStr); fn split_at(&self, i: usize) -> (&OsStr, &OsStr); fn trim_start_matches(&self, b: u8) -> &OsStr; + fn trim_start_n_matches(&self, n: usize, ch: u8) -> &OsStr; fn contains_byte(&self, b: u8) -> bool; fn split(&self, b: u8) -> OsSplit; } @@ -75,6 +76,22 @@ impl OsStrExt2 for OsStr { &*self } + // Like `trim_start_matches`, but trims no more than `n` matches + #[inline] + fn trim_start_n_matches(&self, n: usize, ch: u8) -> &OsStr { + let i = self + .as_bytes() + .into_iter() + .take(n) + .take_while(|c| **c == ch) + .enumerate() + .last() + .map(|(i, _)| i + 1) + .unwrap_or(0); + + self.split_at(i).1 + } + fn split_at(&self, i: usize) -> (&OsStr, &OsStr) { ( OsStr::from_bytes(&self.as_bytes()[..i]),