From e506446224fb5ec778b773c69d84b50552f88fbe Mon Sep 17 00:00:00 2001 From: llama Date: Sat, 13 Sep 2025 17:45:30 +0800 Subject: [PATCH 1/2] feat: add support for `tag:nc:...` searches --- rslib/src/search/parser.rs | 5 +++++ rslib/src/search/sqlwriter.rs | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) 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}(::| ).*")); } } From 61664762f360f9560611edffe192303cc73e06a5 Mon Sep 17 00:00:00 2001 From: llama Date: Wed, 17 Sep 2025 19:11:44 +0800 Subject: [PATCH 2/2] add test --- pylib/tests/test_find.py | 3 +++ 1 file changed, 3 insertions(+) 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