From a16d271eb057fb1fa01086a11c2cf5b60aeadf3d Mon Sep 17 00:00:00 2001 From: RumovZ Date: Sun, 15 Nov 2020 12:00:20 +0100 Subject: [PATCH] Extend tests for new search parsing (Also fix indentation) --- rslib/src/search/parser.rs | 43 +++++++++++++++++++++++++++++++---- rslib/src/search/sqlwriter.rs | 14 ++++++------ 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/rslib/src/search/parser.rs b/rslib/src/search/parser.rs index b8312b281..6c3a35f07 100644 --- a/rslib/src/search/parser.rs +++ b/rslib/src/search/parser.rs @@ -592,7 +592,7 @@ mod test { })] ); - // partially quoted text should handle escaping the same way + // escaping is independent of quotation assert_eq!( parse(r#""field:va\"lue""#)?, vec![Search(SingleField { @@ -602,13 +602,44 @@ mod test { })] ); assert_eq!(parse(r#""field:va\"lue""#)?, parse(r#"field:"va\"lue""#)?,); + assert_eq!(parse(r#""field:va\"lue""#)?, parse(r#"field:va\"lue"#)?,); - // any character should be escapable in quotes + // only \":()*_ are escapable + assert!(parse(r"\").is_err()); + assert!(parse(r"\a").is_err()); + assert!(parse(r"\%").is_err()); assert_eq!( - parse(r#""re:\btest""#)?, - vec![Search(Regex(r"\btest".into()))] + parse(r#"\\\"\:\(\)\*\_"#)?, + vec![Search(UnqualifiedText(r#"\\":()*\_"#.into())),] ); + // escaping parentheses is optional (only) inside quotes + assert_eq!(parse(r#""\)\(""#), parse(r#"")(""#)); + assert!(parse(")(").is_err()); + + // escaping : is optional if it is preceded by another : + assert!(parse(":test").is_err()); + assert!(parse(":").is_err()); + assert_eq!(parse("field:val:ue"), parse(r"field:val\:ue")); + assert_eq!(parse(r#""field:val:ue""#), parse(r"field:val\:ue")); + assert_eq!(parse(r#"field:"val:ue""#), parse(r"field:val\:ue")); + + // any character should be escapable on the right side of re: + assert_eq!( + parse(r#""re:\btest\%""#)?, + vec![Search(Regex(r"\btest\%".into()))] + ); + + // no exceptions for escaping " + assert_eq!( + parse(r#"re:te\"st"#)?, + vec![Search(Regex(r#"te"st"#.into()))] + ); + assert!(parse(r#"re:te"st"#).is_err()); + + // spaces are optional if node separation is clear + assert_eq!(parse(r#"a"b"(c)"#)?, parse("a b (c)")?); + assert_eq!(parse("added:3")?, vec![Search(AddedInDays(3))]); assert_eq!( parse("card:front")?, @@ -636,6 +667,10 @@ mod test { vec![Search(NoteType(Text("basic".into())))] ); assert_eq!(parse("tag:hard")?, vec![Search(Tag("hard".to_string()))]); + // wildcards in tags don't match whitespace + assert_eq!(parse("tag:ha_d")?, vec![Search(Tag(r"ha\Sd".to_string()))]); + assert_eq!(parse("tag:h*d")?, vec![Search(Tag(r"h\S*d".to_string()))]); + assert_eq!( parse("nid:1237123712,2,3")?, vec![Search(NoteIDs("1237123712,2,3".into()))] diff --git a/rslib/src/search/sqlwriter.rs b/rslib/src/search/sqlwriter.rs index 3354342ee..9afbca0cd 100644 --- a/rslib/src/search/sqlwriter.rs +++ b/rslib/src/search/sqlwriter.rs @@ -192,15 +192,15 @@ impl SqlWriter<'_> { if s.contains(" ") { write!(self.sql, "false").unwrap(); } else { - match s.as_str() { - "none" => write!(self.sql, "n.tags = ''").unwrap(), - r"\S*" => write!(self.sql, "true").unwrap(), - _ => { - write!(self.sql, "n.tags regexp ?").unwrap(); - self.args.push(format!("(?i).* {} .*", s)); + match s.as_str() { + "none" => write!(self.sql, "n.tags = ''").unwrap(), + r"\S*" => write!(self.sql, "true").unwrap(), + _ => { + write!(self.sql, "n.tags regexp ?").unwrap(); + self.args.push(format!("(?i).* {} .*", s)); + } } } - } Ok(()) }