Implement the prefix r:
to search for raw input
This commit is contained in:
parent
88d66fc939
commit
6e51bad7db
@ -287,6 +287,7 @@ fn search_node_for_text_with_argument<'a>(
|
|||||||
"dupe" => parse_dupes(val)?,
|
"dupe" => parse_dupes(val)?,
|
||||||
"prop" => parse_prop(val)?,
|
"prop" => parse_prop(val)?,
|
||||||
"re" => SearchNode::Regex(unescape_quotes(val)),
|
"re" => SearchNode::Regex(unescape_quotes(val)),
|
||||||
|
"r" => SearchNode::UnqualifiedText(unescape_raw(val)),
|
||||||
"nc" => SearchNode::NoCombining(unescape(val)?),
|
"nc" => SearchNode::NoCombining(unescape(val)?),
|
||||||
"w" => SearchNode::WordBoundary(unescape(val)?),
|
"w" => SearchNode::WordBoundary(unescape(val)?),
|
||||||
// anything else is a field search
|
// anything else is a field search
|
||||||
@ -419,6 +420,12 @@ fn parse_single_field<'a>(key: &'a str, val: &'a str) -> ParseResult<SearchNode<
|
|||||||
text: unescape_quotes(&val[3..]),
|
text: unescape_quotes(&val[3..]),
|
||||||
is_re: true,
|
is_re: true,
|
||||||
}
|
}
|
||||||
|
} else if val.starts_with("r:") {
|
||||||
|
SearchNode::SingleField {
|
||||||
|
field: unescape(key)?,
|
||||||
|
text: unescape_raw(&val[2..]),
|
||||||
|
is_re: false,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SearchNode::SingleField {
|
SearchNode::SingleField {
|
||||||
field: unescape(key)?,
|
field: unescape(key)?,
|
||||||
@ -437,6 +444,21 @@ fn unescape_quotes(s: &str) -> Cow<str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unescape quotes but escape wildcards and \s.
|
||||||
|
fn unescape_raw(s: &str) -> Cow<str> {
|
||||||
|
lazy_static! {
|
||||||
|
static ref RE: Regex = Regex::new(r#"\\"?|\*|_"#).unwrap();
|
||||||
|
}
|
||||||
|
RE.replace_all(&s, |caps: &Captures| match &caps[0] {
|
||||||
|
r"\" => r"\\",
|
||||||
|
"\\\"" => "\"",
|
||||||
|
r"*" => r"\*",
|
||||||
|
r"_" => r"\_",
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unescape chars with special meaning to the parser.
|
||||||
fn unescape(txt: &str) -> ParseResult<Cow<str>> {
|
fn unescape(txt: &str) -> ParseResult<Cow<str>> {
|
||||||
if is_invalid_escape(txt) {
|
if is_invalid_escape(txt) {
|
||||||
Err(ParseError {})
|
Err(ParseError {})
|
||||||
@ -611,12 +633,21 @@ mod test {
|
|||||||
vec![Search(Regex(r"\btest\%".into()))]
|
vec![Search(Regex(r"\btest\%".into()))]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// treat all chars as literals in raw searches
|
||||||
|
assert_eq!(parse(r"r:\*_"), parse(r"\\\*\_"));
|
||||||
|
assert_eq!(parse(r"field:r:\*_"), parse(r"field:\\\*\_"));
|
||||||
|
|
||||||
// no exceptions for escaping "
|
// no exceptions for escaping "
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(r#"re:te\"st"#)?,
|
parse(r#"re:te\"st"#)?,
|
||||||
vec![Search(Regex(r#"te"st"#.into()))]
|
vec![Search(Regex(r#"te"st"#.into()))]
|
||||||
);
|
);
|
||||||
assert!(parse(r#"re:te"st"#).is_err());
|
assert!(parse(r#"re:te"st"#).is_err());
|
||||||
|
assert_eq!(
|
||||||
|
parse(r#"r:te\"st"#)?,
|
||||||
|
vec![Search(UnqualifiedText(r#"te"st"#.into()))]
|
||||||
|
);
|
||||||
|
assert!(parse(r#"r:te"st"#).is_err());
|
||||||
|
|
||||||
// spaces are optional if node separation is clear
|
// spaces are optional if node separation is clear
|
||||||
assert_eq!(parse(r#"a"b"(c)"#)?, parse("a b (c)")?);
|
assert_eq!(parse(r#"a"b"(c)"#)?, parse("a b (c)")?);
|
||||||
|
Loading…
Reference in New Issue
Block a user