diff --git a/pylib/tests/test_find.py b/pylib/tests/test_find.py index 236096572..72e7fdb8a 100644 --- a/pylib/tests/test_find.py +++ b/pylib/tests/test_find.py @@ -32,6 +32,7 @@ def test_find_cards(): note = col.newNote() note["Front"] = "cat" note["Back"] = "sheep" + note.tags.append("conjunção größte") col.addNote(note) catCard = note.cards()[0] m = col.models.current() @@ -68,6 +69,8 @@ def test_find_cards(): col.tags.bulk_remove(col.db.list("select id from notes"), "foo") assert len(col.find_cards("tag:foo")) == 0 assert len(col.find_cards("tag:bar")) == 5 + assert len(col.find_cards("tag:conjuncao tag:groste")) == 0 + assert len(col.find_cards("tag:nc:conjuncao tag:nc:groste")) == 1 # text searches assert len(col.find_cards("cat")) == 2 assert len(col.find_cards("cat -dog")) == 1 diff --git a/rslib/src/search/parser.rs b/rslib/src/search/parser.rs index cbdba3d9f..5928bf486 100644 --- a/rslib/src/search/parser.rs +++ b/rslib/src/search/parser.rs @@ -392,6 +392,11 @@ fn parse_tag(s: &str) -> ParseResult<'_, SearchNode> { tag: unescape_quotes(re), mode: FieldSearchMode::Regex, } + } else if let Some(nc) = s.strip_prefix("nc:") { + SearchNode::Tag { + tag: unescape(nc)?, + mode: FieldSearchMode::NoCombining, + } } else { SearchNode::Tag { tag: unescape(s)?, diff --git a/rslib/src/search/sqlwriter.rs b/rslib/src/search/sqlwriter.rs index 95249276c..f6237d6fd 100644 --- a/rslib/src/search/sqlwriter.rs +++ b/rslib/src/search/sqlwriter.rs @@ -311,8 +311,19 @@ impl SqlWriter<'_> { } s if s.contains(' ') => write!(self.sql, "false").unwrap(), text => { - write!(self.sql, "n.tags regexp ?").unwrap(); - let re = &to_custom_re(text, r"\S"); + let text = if mode == FieldSearchMode::Normal { + write!(self.sql, "n.tags regexp ?").unwrap(); + Cow::from(text) + } else { + write!( + self.sql, + "coalesce(process_text(n.tags, {}), n.tags) regexp ?", + ProcessTextFlags::NoCombining.bits() + ) + .unwrap(); + without_combining(text) + }; + let re = &to_custom_re(&text, r"\S"); self.args.push(format!("(?i).* {re}(::| ).*")); } }