replace regex crate with fancy_regex

This commit is contained in:
Darren Schroeder 2024-12-20 12:23:33 -06:00
parent 039d0a685a
commit ea105e48a7
9 changed files with 181 additions and 125 deletions

3
Cargo.lock generated
View File

@ -3160,6 +3160,7 @@ dependencies = [
"crossterm 0.28.1", "crossterm 0.28.1",
"ctrlc", "ctrlc",
"dirs", "dirs",
"fancy-regex",
"log", "log",
"miette", "miette",
"mimalloc", "mimalloc",
@ -3187,7 +3188,6 @@ dependencies = [
"openssl", "openssl",
"pretty_assertions", "pretty_assertions",
"reedline", "reedline",
"regex",
"rstest", "rstest",
"serde_json", "serde_json",
"serial_test", "serial_test",
@ -3387,7 +3387,6 @@ dependencies = [
"rand", "rand",
"rand_chacha", "rand_chacha",
"rayon", "rayon",
"regex",
"rmp", "rmp",
"roxmltree", "roxmltree",
"rstest", "rstest",

View File

@ -139,7 +139,6 @@ rand_chacha = "0.3.1"
ratatui = "0.26" ratatui = "0.26"
rayon = "1.10" rayon = "1.10"
reedline = "0.37.0" reedline = "0.37.0"
regex = "1.9.5"
rmp = "0.8" rmp = "0.8"
rmp-serde = "1.3" rmp-serde = "1.3"
ropey = "1.6.1" ropey = "1.6.1"
@ -244,7 +243,7 @@ assert_cmd = "2.0"
dirs = { workspace = true } dirs = { workspace = true }
tango-bench = "0.6" tango-bench = "0.6"
pretty_assertions = { workspace = true } pretty_assertions = { workspace = true }
regex = { workspace = true } fancy-regex = { workspace = true }
rstest = { workspace = true, default-features = false } rstest = { workspace = true, default-features = false }
serial_test = "3.2" serial_test = "3.2"
tempfile = { workspace = true } tempfile = { workspace = true }

View File

@ -76,7 +76,6 @@ quick-xml = { workspace = true }
rand = { workspace = true, optional = true } rand = { workspace = true, optional = true }
getrandom = { workspace = true, optional = true } getrandom = { workspace = true, optional = true }
rayon = { workspace = true } rayon = { workspace = true }
regex = { workspace = true }
roxmltree = { workspace = true } roxmltree = { workspace = true }
rusqlite = { workspace = true, features = ["bundled", "backup", "chrono"], optional = true } rusqlite = { workspace = true, features = ["bundled", "backup", "chrono"], optional = true }
rmp = { workspace = true } rmp = { workspace = true }

View File

@ -1,7 +1,7 @@
use crate::parse_date_from_string; use crate::parse_date_from_string;
use fancy_regex::{Regex, RegexBuilder};
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_protocol::PipelineIterator; use nu_protocol::PipelineIterator;
use regex::{Regex, RegexBuilder};
use std::collections::HashSet; use std::collections::HashSet;
use std::sync::LazyLock; use std::sync::LazyLock;
@ -143,7 +143,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
let val_str = val.coerce_str().unwrap_or_default(); let val_str = val.coerce_str().unwrap_or_default();
// step 2: bounce string up against regexes // step 2: bounce string up against regexes
if BOOLEAN_RE.is_match(&val_str) { if BOOLEAN_RE.is_match(&val_str).unwrap_or(false) {
let bval = val_str let bval = val_str
.parse::<bool>() .parse::<bool>()
.map_err(|_| ShellError::CantConvert { .map_err(|_| ShellError::CantConvert {
@ -156,12 +156,12 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
})?; })?;
Ok(Value::bool(bval, span)) Ok(Value::bool(bval, span))
} else if FLOAT_RE.is_match(&val_str) { } else if FLOAT_RE.is_match(&val_str).unwrap_or(false) {
let fval = val_str let fval = val_str
.parse::<f64>() .parse::<f64>()
.map_err(|_| ShellError::CantConvert { .map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(), to_type: "float".to_string(),
from_type: "float".to_string(), from_type: "string".to_string(),
span, span,
help: Some(format!( help: Some(format!(
r#""{val_str}" does not represent a valid floating point value"# r#""{val_str}" does not represent a valid floating point value"#
@ -169,12 +169,12 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
})?; })?;
Ok(Value::float(fval, span)) Ok(Value::float(fval, span))
} else if INTEGER_RE.is_match(&val_str) { } else if INTEGER_RE.is_match(&val_str).unwrap_or(false) {
let ival = val_str let ival = val_str
.parse::<i64>() .parse::<i64>()
.map_err(|_| ShellError::CantConvert { .map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(), to_type: "int".to_string(),
from_type: "int".to_string(), from_type: "string".to_string(),
span, span,
help: Some(format!( help: Some(format!(
r#""{val_str}" does not represent a valid integer value"# r#""{val_str}" does not represent a valid integer value"#
@ -186,15 +186,15 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
} else { } else {
Ok(Value::int(ival, span)) Ok(Value::int(ival, span))
} }
} else if INTEGER_WITH_DELIMS_RE.is_match(&val_str) { } else if INTEGER_WITH_DELIMS_RE.is_match(&val_str).unwrap_or(false) {
let mut val_str = val_str.into_owned(); let mut val_str = val_str.into_owned();
val_str.retain(|x| !['_', ','].contains(&x)); val_str.retain(|x| !['_', ','].contains(&x));
let ival = val_str let ival = val_str
.parse::<i64>() .parse::<i64>()
.map_err(|_| ShellError::CantConvert { .map_err(|_| ShellError::CantConvert {
to_type: "string".to_string(), to_type: "int".to_string(),
from_type: "int".to_string(), from_type: "string".to_string(),
span, span,
help: Some(format!( help: Some(format!(
r#""{val_str}" does not represent a valid integer value"# r#""{val_str}" does not represent a valid integer value"#
@ -206,7 +206,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
} else { } else {
Ok(Value::int(ival, span)) Ok(Value::int(ival, span))
} }
} else if DATETIME_DMY_RE.is_match(&val_str) { } else if DATETIME_DMY_RE.is_match(&val_str).unwrap_or(false) {
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert { let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
to_type: "date".to_string(), to_type: "date".to_string(),
from_type: "string".to_string(), from_type: "string".to_string(),
@ -217,7 +217,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
})?; })?;
Ok(Value::date(dt, span)) Ok(Value::date(dt, span))
} else if DATETIME_YMD_RE.is_match(&val_str) { } else if DATETIME_YMD_RE.is_match(&val_str).unwrap_or(false) {
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert { let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
to_type: "date".to_string(), to_type: "date".to_string(),
from_type: "string".to_string(), from_type: "string".to_string(),
@ -228,7 +228,7 @@ fn process_cell(val: Value, display_as_filesizes: bool, span: Span) -> Result<Va
})?; })?;
Ok(Value::date(dt, span)) Ok(Value::date(dt, span))
} else if DATETIME_YMDZ_RE.is_match(&val_str) { } else if DATETIME_YMDZ_RE.is_match(&val_str).unwrap_or(false) {
let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert { let dt = parse_date_from_string(&val_str, span).map_err(|_| ShellError::CantConvert {
to_type: "date".to_string(), to_type: "date".to_string(),
from_type: "string".to_string(), from_type: "string".to_string(),
@ -372,118 +372,154 @@ mod test {
#[test] #[test]
fn test_float_parse() { fn test_float_parse() {
// The regex should work on all these but nushell's float parser is more strict // The regex should work on all these but nushell's float parser is more strict
assert!(FLOAT_RE.is_match("0.1")); assert!(FLOAT_RE.is_match("0.1").unwrap());
assert!(FLOAT_RE.is_match("3.0")); assert!(FLOAT_RE.is_match("3.0").unwrap());
assert!(FLOAT_RE.is_match("3.00001")); assert!(FLOAT_RE.is_match("3.00001").unwrap());
assert!(FLOAT_RE.is_match("-9.9990e-003")); assert!(FLOAT_RE.is_match("-9.9990e-003").unwrap());
assert!(FLOAT_RE.is_match("9.9990e+003")); assert!(FLOAT_RE.is_match("9.9990e+003").unwrap());
assert!(FLOAT_RE.is_match("9.9990E+003")); assert!(FLOAT_RE.is_match("9.9990E+003").unwrap());
assert!(FLOAT_RE.is_match("9.9990E+003")); assert!(FLOAT_RE.is_match("9.9990E+003").unwrap());
assert!(FLOAT_RE.is_match(".5")); assert!(FLOAT_RE.is_match(".5").unwrap());
assert!(FLOAT_RE.is_match("2.5E-10")); assert!(FLOAT_RE.is_match("2.5E-10").unwrap());
assert!(FLOAT_RE.is_match("2.5e10")); assert!(FLOAT_RE.is_match("2.5e10").unwrap());
assert!(FLOAT_RE.is_match("NaN")); assert!(FLOAT_RE.is_match("NaN").unwrap());
assert!(FLOAT_RE.is_match("-NaN")); assert!(FLOAT_RE.is_match("-NaN").unwrap());
assert!(FLOAT_RE.is_match("-inf")); assert!(FLOAT_RE.is_match("-inf").unwrap());
assert!(FLOAT_RE.is_match("inf")); assert!(FLOAT_RE.is_match("inf").unwrap());
assert!(FLOAT_RE.is_match("-7e-05")); assert!(FLOAT_RE.is_match("-7e-05").unwrap());
assert!(FLOAT_RE.is_match("7e-05")); assert!(FLOAT_RE.is_match("7e-05").unwrap());
assert!(FLOAT_RE.is_match("+7e+05")); assert!(FLOAT_RE.is_match("+7e+05").unwrap());
} }
#[test] #[test]
fn test_int_parse() { fn test_int_parse() {
assert!(INTEGER_RE.is_match("0")); assert!(INTEGER_RE.is_match("0").unwrap());
assert!(INTEGER_RE.is_match("1")); assert!(INTEGER_RE.is_match("1").unwrap());
assert!(INTEGER_RE.is_match("10")); assert!(INTEGER_RE.is_match("10").unwrap());
assert!(INTEGER_RE.is_match("100")); assert!(INTEGER_RE.is_match("100").unwrap());
assert!(INTEGER_RE.is_match("1000")); assert!(INTEGER_RE.is_match("1000").unwrap());
assert!(INTEGER_RE.is_match("10000")); assert!(INTEGER_RE.is_match("10000").unwrap());
assert!(INTEGER_RE.is_match("100000")); assert!(INTEGER_RE.is_match("100000").unwrap());
assert!(INTEGER_RE.is_match("1000000")); assert!(INTEGER_RE.is_match("1000000").unwrap());
assert!(INTEGER_RE.is_match("10000000")); assert!(INTEGER_RE.is_match("10000000").unwrap());
assert!(INTEGER_RE.is_match("100000000")); assert!(INTEGER_RE.is_match("100000000").unwrap());
assert!(INTEGER_RE.is_match("1000000000")); assert!(INTEGER_RE.is_match("1000000000").unwrap());
assert!(INTEGER_RE.is_match("10000000000")); assert!(INTEGER_RE.is_match("10000000000").unwrap());
assert!(INTEGER_RE.is_match("100000000000")); assert!(INTEGER_RE.is_match("100000000000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000_000_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("1_000_000_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000_000_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("10_000_000_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000_000_000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("100_000_000_000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("100,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("100,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("100,000,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("100,000,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000,000,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("1,000,000,000").unwrap());
assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000,000,000")); assert!(INTEGER_WITH_DELIMS_RE.is_match("10,000,000,000").unwrap());
} }
#[test] #[test]
fn test_bool_parse() { fn test_bool_parse() {
assert!(BOOLEAN_RE.is_match("true")); assert!(BOOLEAN_RE.is_match("true").unwrap());
assert!(BOOLEAN_RE.is_match("false")); assert!(BOOLEAN_RE.is_match("false").unwrap());
assert!(!BOOLEAN_RE.is_match("1")); assert!(!BOOLEAN_RE.is_match("1").unwrap());
assert!(!BOOLEAN_RE.is_match("0")); assert!(!BOOLEAN_RE.is_match("0").unwrap());
} }
#[test] #[test]
fn test_datetime_ymdz_pattern() { fn test_datetime_ymdz_pattern() {
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00Z")); assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00Z").unwrap());
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789Z")); assert!(DATETIME_YMDZ_RE
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01:00")); .is_match("2022-01-01T00:00:00.123456789Z")
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+01:00")); .unwrap());
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01:00")); assert!(DATETIME_YMDZ_RE
assert!(DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-01:00")); .is_match("2022-01-01T00:00:00+01:00")
assert!(DATETIME_YMDZ_RE.is_match("'2022-01-01T00:00:00Z'")); .unwrap());
assert!(DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789+01:00")
.unwrap());
assert!(DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00-01:00")
.unwrap());
assert!(DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789-01:00")
.unwrap());
assert!(DATETIME_YMDZ_RE.is_match("'2022-01-01T00:00:00Z'").unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00")); assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00").unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.")); assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.").unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789")); assert!(!DATETIME_YMDZ_RE
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01")); .is_match("2022-01-01T00:00:00.123456789")
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01:0")); .unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+1:00")); assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00+01").unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+01")); assert!(!DATETIME_YMDZ_RE
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+01:0")); .is_match("2022-01-01T00:00:00+01:0")
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789+1:00")); .unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01")); assert!(!DATETIME_YMDZ_RE
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01:0")); .is_match("2022-01-01T00:00:00+1:00")
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-1:00")); .unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-01")); assert!(!DATETIME_YMDZ_RE
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-01:0")); .is_match("2022-01-01T00:00:00.123456789+01")
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00.123456789-1:00")); .unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789+01:0")
.unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789+1:00")
.unwrap());
assert!(!DATETIME_YMDZ_RE.is_match("2022-01-01T00:00:00-01").unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00-01:0")
.unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00-1:00")
.unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789-01")
.unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789-01:0")
.unwrap());
assert!(!DATETIME_YMDZ_RE
.is_match("2022-01-01T00:00:00.123456789-1:00")
.unwrap());
} }
#[test] #[test]
fn test_datetime_ymd_pattern() { fn test_datetime_ymd_pattern() {
assert!(DATETIME_YMD_RE.is_match("2022-01-01")); assert!(DATETIME_YMD_RE.is_match("2022-01-01").unwrap());
assert!(DATETIME_YMD_RE.is_match("2022/01/01")); assert!(DATETIME_YMD_RE.is_match("2022/01/01").unwrap());
assert!(DATETIME_YMD_RE.is_match("2022-01-01T00:00:00")); assert!(DATETIME_YMD_RE.is_match("2022-01-01T00:00:00").unwrap());
assert!(DATETIME_YMD_RE.is_match("2022-01-01T00:00:00.000000000")); assert!(DATETIME_YMD_RE
assert!(DATETIME_YMD_RE.is_match("'2022-01-01'")); .is_match("2022-01-01T00:00:00.000000000")
.unwrap());
assert!(DATETIME_YMD_RE.is_match("'2022-01-01'").unwrap());
// The regex isn't this specific, but it would be nice if it were // The regex isn't this specific, but it would be nice if it were
// assert!(!DATETIME_YMD_RE.is_match("2022-13-01")); // assert!(!DATETIME_YMD_RE.is_match("2022-13-01").unwrap());
// assert!(!DATETIME_YMD_RE.is_match("2022-01-32")); // assert!(!DATETIME_YMD_RE.is_match("2022-01-32").unwrap());
// assert!(!DATETIME_YMD_RE.is_match("2022-01-01T24:00:00")); // assert!(!DATETIME_YMD_RE.is_match("2022-01-01T24:00:00").unwrap());
// assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:60:00")); // assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:60:00").unwrap());
// assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:00:60")); // assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:00:60").unwrap());
assert!(!DATETIME_YMD_RE.is_match("2022-01-01T00:00:00.0000000000")); assert!(!DATETIME_YMD_RE
.is_match("2022-01-01T00:00:00.0000000000")
.unwrap());
} }
#[test] #[test]
fn test_datetime_dmy_pattern() { fn test_datetime_dmy_pattern() {
assert!(DATETIME_DMY_RE.is_match("31-12-2021")); assert!(DATETIME_DMY_RE.is_match("31-12-2021").unwrap());
assert!(DATETIME_DMY_RE.is_match("01/01/2022")); assert!(DATETIME_DMY_RE.is_match("01/01/2022").unwrap());
assert!(DATETIME_DMY_RE.is_match("15-06-2023 12:30")); assert!(DATETIME_DMY_RE.is_match("15-06-2023 12:30").unwrap());
assert!(!DATETIME_DMY_RE.is_match("2022-13-01")); assert!(!DATETIME_DMY_RE.is_match("2022-13-01").unwrap());
assert!(!DATETIME_DMY_RE.is_match("2022-01-32")); assert!(!DATETIME_DMY_RE.is_match("2022-01-32").unwrap());
assert!(!DATETIME_DMY_RE.is_match("2022-01-01 24:00")); assert!(!DATETIME_DMY_RE.is_match("2022-01-01 24:00").unwrap());
} }
} }

View File

@ -1,5 +1,5 @@
use crate::help::{help_aliases, help_commands, help_modules}; use crate::help::{help_aliases, help_commands, help_modules};
use fancy_regex::Regex; use fancy_regex::{escape, Regex};
use nu_ansi_term::Style; use nu_ansi_term::Style;
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use nu_utils::IgnoreCaseExt; use nu_utils::IgnoreCaseExt;
@ -193,7 +193,7 @@ pub fn highlight_search_string(
string_style: &Style, string_style: &Style,
highlight_style: &Style, highlight_style: &Style,
) -> Result<String, ShellError> { ) -> Result<String, ShellError> {
let escaped_needle = regex::escape(needle); let escaped_needle = escape(needle);
let regex_string = format!("(?i){escaped_needle}"); let regex_string = format!("(?i){escaped_needle}");
let regex = match Regex::new(&regex_string) { let regex = match Regex::new(&regex_string) {
Ok(regex) => regex, Ok(regex) => regex,

View File

@ -1,7 +1,6 @@
use fancy_regex::{escape, Regex};
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use regex::Regex;
#[derive(Clone)] #[derive(Clone)]
pub struct SubCommand; pub struct SubCommand;
@ -182,7 +181,7 @@ fn split_column(
let regex = if args.has_regex { let regex = if args.has_regex {
Regex::new(&args.separator.item) Regex::new(&args.separator.item)
} else { } else {
let escaped = regex::escape(&args.separator.item); let escaped = escape(&args.separator.item);
Regex::new(&escaped) Regex::new(&escaped)
} }
.map_err(|e| ShellError::GenericError { .map_err(|e| ShellError::GenericError {
@ -220,10 +219,12 @@ fn split_column_helper(
let split_result: Vec<_> = match max_split { let split_result: Vec<_> = match max_split {
Some(max_split) => separator Some(max_split) => separator
.splitn(&s, max_split) .splitn(&s, max_split)
.filter_map(|x| x.ok())
.filter(|x| !(collapse_empty && x.is_empty())) .filter(|x| !(collapse_empty && x.is_empty()))
.collect(), .collect(),
None => separator None => separator
.split(&s) .split(&s)
.filter_map(|x| x.ok())
.filter(|x| !(collapse_empty && x.is_empty())) .filter(|x| !(collapse_empty && x.is_empty()))
.collect(), .collect(),
}; };

View File

@ -1,7 +1,6 @@
use fancy_regex::Regex;
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use regex::Regex;
#[derive(Clone)] #[derive(Clone)]
pub struct SubCommand; pub struct SubCommand;
@ -193,7 +192,7 @@ impl Matcher {
Ok(match self { Ok(match self {
Matcher::Regex(regex) => { Matcher::Regex(regex) => {
if let Ok(rhs_str) = rhs.coerce_str() { if let Ok(rhs_str) = rhs.coerce_str() {
regex.is_match(&rhs_str) regex.is_match(&rhs_str).unwrap_or(false)
} else { } else {
false false
} }

View File

@ -1,7 +1,6 @@
use fancy_regex::{escape, Regex};
use nu_engine::command_prelude::*; use nu_engine::command_prelude::*;
use regex::Regex;
#[derive(Clone)] #[derive(Clone)]
pub struct SubCommand; pub struct SubCommand;
@ -158,7 +157,7 @@ fn split_row(
let regex = if args.has_regex { let regex = if args.has_regex {
Regex::new(&args.separator.item) Regex::new(&args.separator.item)
} else { } else {
let escaped = regex::escape(&args.separator.item); let escaped = escape(&args.separator.item);
Regex::new(&escaped) Regex::new(&escaped)
} }
.map_err(|e| ShellError::GenericError { .map_err(|e| ShellError::GenericError {
@ -187,11 +186,35 @@ fn split_row_helper(v: &Value, regex: &Regex, max_split: Option<usize>, name: Sp
match max_split { match max_split {
Some(max_split) => regex Some(max_split) => regex
.splitn(&s, max_split) .splitn(&s, max_split)
.map(|x: &str| Value::string(x, v_span)) .map(|x| match x {
Ok(val) => Value::string(val, v_span),
Err(err) => Value::error(
ShellError::GenericError {
error: "Error with regular expression".into(),
msg: err.to_string(),
span: Some(v_span),
help: None,
inner: vec![],
},
v_span,
),
})
.collect(), .collect(),
None => regex None => regex
.split(&s) .split(&s)
.map(|x: &str| Value::string(x, v_span)) .map(|x| match x {
Ok(val) => Value::string(val, v_span),
Err(err) => Value::error(
ShellError::GenericError {
error: "Error with regular expression".into(),
msg: err.to_string(),
span: Some(v_span),
help: None,
inner: vec![],
},
v_span,
),
})
.collect(), .collect(),
} }
} else { } else {

View File

@ -1,5 +1,5 @@
use fancy_regex::Regex;
use nu_test_support::{nu, playground::Playground}; use nu_test_support::{nu, playground::Playground};
use regex::Regex;
#[test] #[test]
fn record_with_redefined_key() { fn record_with_redefined_key() {
@ -45,7 +45,7 @@ fn test_eval(source: &str, expected_out: ExpectedOut) {
Matches(regex) => { Matches(regex) => {
let compiled_regex = Regex::new(regex).expect("regex failed to compile"); let compiled_regex = Regex::new(regex).expect("regex failed to compile");
assert!( assert!(
compiled_regex.is_match(&actual.out), compiled_regex.is_match(&actual.out).unwrap_or(false),
"eval out does not match: {}\n{}", "eval out does not match: {}\n{}",
regex, regex,
actual.out, actual.out,
@ -55,7 +55,7 @@ fn test_eval(source: &str, expected_out: ExpectedOut) {
Error(regex) => { Error(regex) => {
let compiled_regex = Regex::new(regex).expect("regex failed to compile"); let compiled_regex = Regex::new(regex).expect("regex failed to compile");
assert!( assert!(
compiled_regex.is_match(&actual.err), compiled_regex.is_match(&actual.err).unwrap_or(false),
"eval err does not match: {}", "eval err does not match: {}",
regex regex
); );