mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-08-03 21:51:58 -07:00
Compare commits
6 Commits
grep-cli-0
...
globset-0.
Author | SHA1 | Date | |
---|---|---|---|
|
61733f6378 | ||
|
7227e94ce5 | ||
|
341a19e0d0 | ||
|
fed4fea217 | ||
|
053a1669bb | ||
|
31d3f16254 |
@@ -38,6 +38,8 @@ Bug fixes:
|
|||||||
Fix bug when using inline regex flags with `-e/--regexp`.
|
Fix bug when using inline regex flags with `-e/--regexp`.
|
||||||
* [BUG #2523](https://github.com/BurntSushi/ripgrep/issues/2523):
|
* [BUG #2523](https://github.com/BurntSushi/ripgrep/issues/2523):
|
||||||
Make executable searching take `.com` into account on Windows.
|
Make executable searching take `.com` into account on Windows.
|
||||||
|
* [BUG #2574](https://github.com/BurntSushi/ripgrep/issues/2574):
|
||||||
|
Fix bug in `-w/--word-regexp` that would result in incorrect match offsets.
|
||||||
|
|
||||||
|
|
||||||
13.0.0 (2021-06-12)
|
13.0.0 (2021-06-12)
|
||||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -119,7 +119,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.11"
|
version = "0.4.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"bstr",
|
"bstr",
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.11" #:version
|
version = "0.4.13" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Cross platform single glob and glob set matching. Glob set matching is the
|
Cross platform single glob and glob set matching. Glob set matching is the
|
||||||
|
@@ -736,7 +736,7 @@ impl Tokens {
|
|||||||
// It is possible to have an empty set in which case the
|
// It is possible to have an empty set in which case the
|
||||||
// resulting alternation '()' would be an error.
|
// resulting alternation '()' would be an error.
|
||||||
if !parts.is_empty() {
|
if !parts.is_empty() {
|
||||||
re.push('(');
|
re.push_str("(?:");
|
||||||
re.push_str(&parts.join("|"));
|
re.push_str(&parts.join("|"));
|
||||||
re.push(')');
|
re.push(')');
|
||||||
}
|
}
|
||||||
@@ -1276,6 +1276,7 @@ mod tests {
|
|||||||
toregex!(re32, "/a**", r"^/a.*.*$");
|
toregex!(re32, "/a**", r"^/a.*.*$");
|
||||||
toregex!(re33, "/**a", r"^/.*.*a$");
|
toregex!(re33, "/**a", r"^/.*.*a$");
|
||||||
toregex!(re34, "/a**b", r"^/a.*.*b$");
|
toregex!(re34, "/a**b", r"^/a.*.*b$");
|
||||||
|
toregex!(re35, "{a,b}", r"^(?:b|a)$");
|
||||||
|
|
||||||
matches!(match1, "a", "a");
|
matches!(match1, "a", "a");
|
||||||
matches!(match2, "a*b", "a_b");
|
matches!(match2, "a*b", "a_b");
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
use serde::{
|
use serde::{
|
||||||
de::{Error, Visitor},
|
de::{Error, SeqAccess, Visitor},
|
||||||
{Deserialize, Deserializer, Serialize, Serializer},
|
{Deserialize, Deserializer, Serialize, Serializer},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Glob;
|
use crate::{Glob, GlobSet, GlobSetBuilder};
|
||||||
|
|
||||||
impl Serialize for Glob {
|
impl Serialize for Glob {
|
||||||
fn serialize<S: Serializer>(
|
fn serialize<S: Serializer>(
|
||||||
@@ -16,7 +16,7 @@ impl Serialize for Glob {
|
|||||||
|
|
||||||
struct GlobVisitor;
|
struct GlobVisitor;
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for GlobVisitor {
|
impl<'de> Visitor<'de> for GlobVisitor {
|
||||||
type Value = Glob;
|
type Value = Glob;
|
||||||
|
|
||||||
fn expecting(
|
fn expecting(
|
||||||
@@ -42,11 +42,43 @@ impl<'de> Deserialize<'de> for Glob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GlobSetVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for GlobSetVisitor {
|
||||||
|
type Value = GlobSet;
|
||||||
|
|
||||||
|
fn expecting(
|
||||||
|
&self,
|
||||||
|
formatter: &mut std::fmt::Formatter,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
formatter.write_str("an array of glob patterns")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut builder = GlobSetBuilder::new();
|
||||||
|
while let Some(glob) = seq.next_element()? {
|
||||||
|
builder.add(glob);
|
||||||
|
}
|
||||||
|
builder.build().map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for GlobSet {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<Self, D::Error> {
|
||||||
|
deserializer.deserialize_seq(GlobSetVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::Glob;
|
use crate::{Glob, GlobSet};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn glob_deserialize_borrowed() {
|
fn glob_deserialize_borrowed() {
|
||||||
@@ -85,4 +117,12 @@ mod tests {
|
|||||||
let de: Glob = serde_json::from_str(&ser).unwrap();
|
let de: Glob = serde_json::from_str(&ser).unwrap();
|
||||||
assert_eq!(test_glob, de);
|
assert_eq!(test_glob, de);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn glob_set_deserialize() {
|
||||||
|
let j = r#" ["src/**/*.rs", "README.md"] "#;
|
||||||
|
let set: GlobSet = serde_json::from_str(j).unwrap();
|
||||||
|
assert!(set.is_match("src/lib.rs"));
|
||||||
|
assert!(!set.is_match("Cargo.lock"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,7 @@ pub const DEFAULT_TYPES: &[(&[&str], &[&str])] = &[
|
|||||||
(&["cs"], &["*.cs"]),
|
(&["cs"], &["*.cs"]),
|
||||||
(&["csharp"], &["*.cs"]),
|
(&["csharp"], &["*.cs"]),
|
||||||
(&["cshtml"], &["*.cshtml"]),
|
(&["cshtml"], &["*.cshtml"]),
|
||||||
|
(&["csproj"], &["*.csproj"]),
|
||||||
(&["css"], &["*.css", "*.scss"]),
|
(&["css"], &["*.css", "*.scss"]),
|
||||||
(&["csv"], &["*.csv"]),
|
(&["csv"], &["*.csv"]),
|
||||||
(&["cuda"], &["*.cu", "*.cuh"]),
|
(&["cuda"], &["*.cu", "*.cuh"]),
|
||||||
|
@@ -128,6 +128,9 @@ impl WordMatcher {
|
|||||||
// The reason why we cannot handle the ^/$ cases here is because we
|
// The reason why we cannot handle the ^/$ cases here is because we
|
||||||
// can't assume anything about the original pattern. (Try commenting
|
// can't assume anything about the original pattern. (Try commenting
|
||||||
// out the checks for ^/$ below and run the tests to see examples.)
|
// out the checks for ^/$ below and run the tests to see examples.)
|
||||||
|
//
|
||||||
|
// NOTE(2023-07-31): After fixing #2574, this logic honestly still
|
||||||
|
// doesn't seem correct. Regex composition is hard.
|
||||||
let input = Input::new(haystack).span(at..haystack.len());
|
let input = Input::new(haystack).span(at..haystack.len());
|
||||||
let mut cand = match self.regex.find(input) {
|
let mut cand = match self.regex.find(input) {
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
@@ -136,8 +139,17 @@ impl WordMatcher {
|
|||||||
if cand.start() == 0 || cand.end() == haystack.len() {
|
if cand.start() == 0 || cand.end() == haystack.len() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let (_, slen) = bstr::decode_utf8(&haystack[cand]);
|
// We decode the chars on either side of the match. If either char is
|
||||||
let (_, elen) = bstr::decode_last_utf8(&haystack[cand]);
|
// a word character, then that means the ^/$ matched and not \W. In
|
||||||
|
// that case, we defer to the slower engine.
|
||||||
|
let (ch, slen) = bstr::decode_utf8(&haystack[cand]);
|
||||||
|
if ch.map_or(true, regex_syntax::is_word_character) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let (ch, elen) = bstr::decode_last_utf8(&haystack[cand]);
|
||||||
|
if ch.map_or(true, regex_syntax::is_word_character) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
let new_start = cand.start() + slen;
|
let new_start = cand.start() + slen;
|
||||||
let new_end = cand.end() - elen;
|
let new_end = cand.end() - elen;
|
||||||
// This occurs the original regex can match the empty string. In this
|
// This occurs the original regex can match the empty string. In this
|
||||||
|
@@ -1173,3 +1173,18 @@ rgtest!(r2480, |dir: Dir, mut cmd: TestCommand| {
|
|||||||
cmd.args(&["--only-matching", "-e", "(?i)notfoo", "-e", "bar", "file"]);
|
cmd.args(&["--only-matching", "-e", "(?i)notfoo", "-e", "bar", "file"]);
|
||||||
cmd.assert_err();
|
cmd.assert_err();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// See: https://github.com/BurntSushi/ripgrep/issues/2574
|
||||||
|
rgtest!(r2574, |dir: Dir, mut cmd: TestCommand| {
|
||||||
|
dir.create("haystack", "some.domain.com\nsome.domain.com/x\n");
|
||||||
|
let got = cmd
|
||||||
|
.args(&[
|
||||||
|
"--no-filename",
|
||||||
|
"--no-unicode",
|
||||||
|
"-w",
|
||||||
|
"-o",
|
||||||
|
r"(\w+\.)*domain\.(\w+)",
|
||||||
|
])
|
||||||
|
.stdout();
|
||||||
|
eqnice!("some.domain.com\nsome.domain.com\n", got);
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user