summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpierrenn <git@pnn.sh>2020-02-28 00:47:34 +0900
committerAndrew Gallant <jamslam@gmail.com>2020-03-15 09:24:28 -0400
commitaab3d80374d5ba4a926d2928ccd476f99846b312 (patch)
treedaeb46887bd3289f6c82ab0290e8253ca81bb63d
parent1856cda77be5bd4cd505e63f32816e4cb14be8cc (diff)
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.
-rw-r--r--crates/core/args.rs136
1 files changed, 87 insertions, 49 deletions
diff --git a/crates/core/args.rs b/crates/core/args.rs
index d99e777d..17f08b9f 100644
--- a/crates/core/args.rs
+++ b/crates/core/args.rs
@@ -576,58 +576,77 @@ impl ArgMatches {
///
/// If there was a problem building the matcher (e.g., a syntax error),
/// then this returns an error.
- #[cfg(feature = "pcre2")]
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
if self.is_present("pcre2") {
- let matcher = self.matcher_pcre2(patterns)?;
- Ok(PatternMatcher::PCRE2(matcher))
+ self.matcher_engine("pcre2", patterns)
} else if self.is_present("auto-hybrid-regex") {
- 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_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,
- )))
+ self.matcher_engine("auto", patterns)
} else {
- let matcher = match self.matcher_rust(patterns) {
- Ok(matcher) => matcher,
- Err(err) => {
- return Err(From::from(suggest_pcre2(err.to_string())));
- }
- };
- Ok(PatternMatcher::RustRegex(matcher))
+ self.matcher_engine("default", patterns)
}
}
- /// 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),
/// then this returns an error.
- #[cfg(not(feature = "pcre2"))]
- fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
- if self.is_present("pcre2") {
- return Err(From::from(
+ fn matcher_engine(
+ &self,
+ engine: &str,
+ 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",
- ));
+ )),
+ "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.
@@ -1677,21 +1696,40 @@ 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
/// believed to correspond to a syntax error that PCRE2 could handle, then
/// add a message to suggest the use of -P/--pcre2.
-#[cfg(feature = "pcre2")]
-fn suggest_pcre2(msg: String) -> String {
- if !msg.contains("backreferences") && !msg.contains("look-around") {
- msg
- } else {
- format!(
- "{}
+fn suggest_pcre2(msg: &str) -> Option<String> {
+ #[cfg(feature = "pcre2")]
+ fn suggest(msg: &str) -> Option<String> {
+ if !msg.contains("backreferences") && !msg.contains("look-around") {
+ None
+ } else {
+ Some(format!(
+ "{}
Consider enabling PCRE2 with the --pcre2 flag, which can handle backreferences
and look-around.",
- msg
- )
+ msg
+ ))
+ }
}
+
+ #[cfg(not(feature = "pcre2"))]
+ fn suggest(_: &str) -> Option<String> {
+ None
+ }
+
+ suggest(msg)
}
fn suggest_multiline(msg: String) -> String {