mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-05-19 01:30:21 -07:00
args: refactor to permit adding other engines
This is in preparation for adding a new --engine flag which is intended to eventually supplant --auto-hybrid-regex. While there are no immediate plans to add more regex engines to ripgrep, this is intended to make it easier to maintain a patch to ripgrep with an additional regex engine. See #1488 for more details.
This commit is contained in:
parent
1856cda77b
commit
aab3d80374
@ -576,58 +576,77 @@ impl ArgMatches {
|
|||||||
///
|
///
|
||||||
/// If there was a problem building the matcher (e.g., a syntax error),
|
/// If there was a problem building the matcher (e.g., a syntax error),
|
||||||
/// then this returns an error.
|
/// then this returns an error.
|
||||||
#[cfg(feature = "pcre2")]
|
|
||||||
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
|
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
|
||||||
if self.is_present("pcre2") {
|
if self.is_present("pcre2") {
|
||||||
let matcher = self.matcher_pcre2(patterns)?;
|
self.matcher_engine("pcre2", patterns)
|
||||||
Ok(PatternMatcher::PCRE2(matcher))
|
|
||||||
} else if self.is_present("auto-hybrid-regex") {
|
} else if self.is_present("auto-hybrid-regex") {
|
||||||
let rust_err = match self.matcher_rust(patterns) {
|
self.matcher_engine("auto", patterns)
|
||||||
Ok(matcher) => return Ok(PatternMatcher::RustRegex(matcher)),
|
|
||||||
Err(err) => err,
|
|
||||||
};
|
|
||||||
log::debug!(
|
|
||||||
"error building Rust regex in hybrid mode:\n{}",
|
|
||||||
rust_err,
|
|
||||||
);
|
|
||||||
let pcre_err = match self.matcher_pcre2(patterns) {
|
|
||||||
Ok(matcher) => return Ok(PatternMatcher::PCRE2(matcher)),
|
|
||||||
Err(err) => err,
|
|
||||||
};
|
|
||||||
Err(From::from(format!(
|
|
||||||
"regex could not be compiled with either the default regex \
|
|
||||||
engine or with PCRE2.\n\n\
|
|
||||||
default regex engine error:\n{}\n{}\n{}\n\n\
|
|
||||||
PCRE2 regex engine error:\n{}",
|
|
||||||
"~".repeat(79),
|
|
||||||
rust_err,
|
|
||||||
"~".repeat(79),
|
|
||||||
pcre_err,
|
|
||||||
)))
|
|
||||||
} else {
|
} else {
|
||||||
let matcher = match self.matcher_rust(patterns) {
|
self.matcher_engine("default", patterns)
|
||||||
Ok(matcher) => matcher,
|
|
||||||
Err(err) => {
|
|
||||||
return Err(From::from(suggest_pcre2(err.to_string())));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(PatternMatcher::RustRegex(matcher))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the matcher that should be used for searching.
|
/// Return the matcher that should be used for searching using engine
|
||||||
|
/// as the engine for the patterns.
|
||||||
///
|
///
|
||||||
/// If there was a problem building the matcher (e.g., a syntax error),
|
/// If there was a problem building the matcher (e.g., a syntax error),
|
||||||
/// then this returns an error.
|
/// then this returns an error.
|
||||||
#[cfg(not(feature = "pcre2"))]
|
fn matcher_engine(
|
||||||
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
|
&self,
|
||||||
if self.is_present("pcre2") {
|
engine: &str,
|
||||||
return Err(From::from(
|
patterns: &[String],
|
||||||
|
) -> Result<PatternMatcher> {
|
||||||
|
match engine {
|
||||||
|
"default" => {
|
||||||
|
let matcher = match self.matcher_rust(patterns) {
|
||||||
|
Ok(matcher) => matcher,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(From::from(suggest(err.to_string())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(PatternMatcher::RustRegex(matcher))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "pcre2")]
|
||||||
|
"pcre2" => {
|
||||||
|
let matcher = self.matcher_pcre2(patterns)?;
|
||||||
|
Ok(PatternMatcher::PCRE2(matcher))
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "pcre2"))]
|
||||||
|
"pcre2" => Err(From::from(
|
||||||
"PCRE2 is not available in this build of ripgrep",
|
"PCRE2 is not available in this build of ripgrep",
|
||||||
));
|
)),
|
||||||
|
"auto" => {
|
||||||
|
let rust_err = match self.matcher_rust(patterns) {
|
||||||
|
Ok(matcher) => {
|
||||||
|
return Ok(PatternMatcher::RustRegex(matcher));
|
||||||
|
}
|
||||||
|
Err(err) => err,
|
||||||
|
};
|
||||||
|
log::debug!(
|
||||||
|
"error building Rust regex in hybrid mode:\n{}",
|
||||||
|
rust_err,
|
||||||
|
);
|
||||||
|
|
||||||
|
let pcre_err = match self.matcher_engine("pcre2", patterns) {
|
||||||
|
Ok(matcher) => return Ok(matcher),
|
||||||
|
Err(err) => err,
|
||||||
|
};
|
||||||
|
Err(From::from(format!(
|
||||||
|
"regex could not be compiled with either the default \
|
||||||
|
regex engine or with PCRE2.\n\n\
|
||||||
|
default regex engine error:\n{}\n{}\n{}\n\n\
|
||||||
|
PCRE2 regex engine error:\n{}",
|
||||||
|
"~".repeat(79),
|
||||||
|
rust_err,
|
||||||
|
"~".repeat(79),
|
||||||
|
pcre_err,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
_ => Err(From::from(format!(
|
||||||
|
"unrecognized regex engine '{}'",
|
||||||
|
engine
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
let matcher = self.matcher_rust(patterns)?;
|
|
||||||
Ok(PatternMatcher::RustRegex(matcher))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a matcher using Rust's regex engine.
|
/// Build a matcher using Rust's regex engine.
|
||||||
@ -1676,22 +1695,41 @@ impl ArgMatches {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inspect an error resulting from building a Rust regex matcher, and if it's
|
||||||
|
/// believed to correspond to a syntax error that another engine could handle,
|
||||||
|
/// then add a message to suggest the use of the engine flag.
|
||||||
|
fn suggest(msg: String) -> String {
|
||||||
|
if let Some(pcre_msg) = suggest_pcre2(&msg) {
|
||||||
|
return pcre_msg;
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
|
||||||
/// Inspect an error resulting from building a Rust regex matcher, and if it's
|
/// Inspect an error resulting from building a Rust regex matcher, and if it's
|
||||||
/// believed to correspond to a syntax error that PCRE2 could handle, then
|
/// believed to correspond to a syntax error that PCRE2 could handle, then
|
||||||
/// add a message to suggest the use of -P/--pcre2.
|
/// add a message to suggest the use of -P/--pcre2.
|
||||||
#[cfg(feature = "pcre2")]
|
fn suggest_pcre2(msg: &str) -> Option<String> {
|
||||||
fn suggest_pcre2(msg: String) -> String {
|
#[cfg(feature = "pcre2")]
|
||||||
if !msg.contains("backreferences") && !msg.contains("look-around") {
|
fn suggest(msg: &str) -> Option<String> {
|
||||||
msg
|
if !msg.contains("backreferences") && !msg.contains("look-around") {
|
||||||
} else {
|
None
|
||||||
format!(
|
} else {
|
||||||
"{}
|
Some(format!(
|
||||||
|
"{}
|
||||||
|
|
||||||
Consider enabling PCRE2 with the --pcre2 flag, which can handle backreferences
|
Consider enabling PCRE2 with the --pcre2 flag, which can handle backreferences
|
||||||
and look-around.",
|
and look-around.",
|
||||||
msg
|
msg
|
||||||
)
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "pcre2"))]
|
||||||
|
fn suggest(_: &str) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
suggest(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_multiline(msg: String) -> String {
|
fn suggest_multiline(msg: String) -> String {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user