diff options
Diffstat (limited to 'vendor/globset/src/glob.rs')
-rw-r--r-- | vendor/globset/src/glob.rs | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/vendor/globset/src/glob.rs b/vendor/globset/src/glob.rs index 6e35aeec3..d19c70ed2 100644 --- a/vendor/globset/src/glob.rs +++ b/vendor/globset/src/glob.rs @@ -208,6 +208,9 @@ struct GlobOptions { /// Whether or not to use `\` to escape special characters. /// e.g., when enabled, `\*` will match a literal `*`. backslash_escape: bool, + /// Whether or not an empty case in an alternate will be removed. + /// e.g., when enabled, `{,a}` will match "" and "a". + empty_alternates: bool, } impl GlobOptions { @@ -216,6 +219,7 @@ impl GlobOptions { case_insensitive: false, literal_separator: false, backslash_escape: !is_separator('\\'), + empty_alternates: false, } } } @@ -633,6 +637,16 @@ impl<'a> GlobBuilder<'a> { self.opts.backslash_escape = yes; self } + + /// Toggle whether an empty pattern in a list of alternates is accepted. + /// + /// For example, if this is set then the glob `foo{,.txt}` will match both `foo` and `foo.txt`. + /// + /// By default this is false. + pub fn empty_alternates(&mut self, yes: bool) -> &mut GlobBuilder<'a> { + self.opts.empty_alternates = yes; + self + } } impl Tokens { @@ -714,7 +728,7 @@ impl Tokens { for pat in patterns { let mut altre = String::new(); self.tokens_to_regex(options, &pat, &mut altre); - if !altre.is_empty() { + if !altre.is_empty() || options.empty_alternates { parts.push(altre); } } @@ -722,7 +736,7 @@ impl Tokens { // It is possible to have an empty set in which case the // resulting alternation '()' would be an error. if !parts.is_empty() { - re.push('('); + re.push_str("(?:"); re.push_str(&parts.join("|")); re.push(')'); } @@ -1020,6 +1034,7 @@ mod tests { casei: Option<bool>, litsep: Option<bool>, bsesc: Option<bool>, + ealtre: Option<bool>, } macro_rules! syntax { @@ -1059,6 +1074,9 @@ mod tests { if let Some(bsesc) = $options.bsesc { builder.backslash_escape(bsesc); } + if let Some(ealtre) = $options.ealtre { + builder.empty_alternates(ealtre); + } let pat = builder.build().unwrap(); assert_eq!(format!("(?-u){}", $re), pat.regex()); } @@ -1082,6 +1100,9 @@ mod tests { if let Some(bsesc) = $options.bsesc { builder.backslash_escape(bsesc); } + if let Some(ealtre) = $options.ealtre { + builder.empty_alternates(ealtre); + } let pat = builder.build().unwrap(); let matcher = pat.compile_matcher(); let strategic = pat.compile_strategic_matcher(); @@ -1110,6 +1131,9 @@ mod tests { if let Some(bsesc) = $options.bsesc { builder.backslash_escape(bsesc); } + if let Some(ealtre) = $options.ealtre { + builder.empty_alternates(ealtre); + } let pat = builder.build().unwrap(); let matcher = pat.compile_matcher(); let strategic = pat.compile_strategic_matcher(); @@ -1195,13 +1219,23 @@ mod tests { syntaxerr!(err_range2, "[z--]", ErrorKind::InvalidRange('z', '-')); const CASEI: Options = - Options { casei: Some(true), litsep: None, bsesc: None }; + Options { casei: Some(true), litsep: None, bsesc: None, ealtre: None }; const SLASHLIT: Options = - Options { casei: None, litsep: Some(true), bsesc: None }; - const NOBSESC: Options = - Options { casei: None, litsep: None, bsesc: Some(false) }; + Options { casei: None, litsep: Some(true), bsesc: None, ealtre: None }; + const NOBSESC: Options = Options { + casei: None, + litsep: None, + bsesc: Some(false), + ealtre: None, + }; const BSESC: Options = - Options { casei: None, litsep: None, bsesc: Some(true) }; + Options { casei: None, litsep: None, bsesc: Some(true), ealtre: None }; + const EALTRE: Options = Options { + casei: None, + litsep: None, + bsesc: Some(true), + ealtre: Some(true), + }; toregex!(re_casei, "a", "(?i)^a$", &CASEI); @@ -1242,6 +1276,7 @@ mod tests { toregex!(re32, "/a**", r"^/a.*.*$"); toregex!(re33, "/**a", r"^/.*.*a$"); toregex!(re34, "/a**b", r"^/a.*.*b$"); + toregex!(re35, "{a,b}", r"^(?:b|a)$"); matches!(match1, "a", "a"); matches!(match2, "a*b", "a_b"); @@ -1326,6 +1361,9 @@ mod tests { matches!(matchalt11, "{*.foo,*.bar,*.wat}", "test.foo"); matches!(matchalt12, "{*.foo,*.bar,*.wat}", "test.bar"); matches!(matchalt13, "{*.foo,*.bar,*.wat}", "test.wat"); + matches!(matchalt14, "foo{,.txt}", "foo.txt"); + nmatches!(matchalt15, "foo{,.txt}", "foo"); + matches!(matchalt16, "foo{,.txt}", "foo", EALTRE); matches!(matchslash1, "abc/def", "abc/def", SLASHLIT); #[cfg(unix)] @@ -1425,6 +1463,9 @@ mod tests { if let Some(bsesc) = $options.bsesc { builder.backslash_escape(bsesc); } + if let Some(ealtre) = $options.ealtre { + builder.empty_alternates(ealtre); + } let pat = builder.build().unwrap(); assert_eq!($expect, pat.$which()); } |