Skip to content

A "quoted phrase" in a search means those words together, in order (#774) - #905

Merged
Ninja-FSE merged 2 commits into
mainfrom
feat/774-a-quoted-phrase-is-a-phrase
Sep 23, 2026
Merged

Ninja-FSE merged 2 commits into
mainfrom
feat/774-a-quoted-phrase-is-a-phrase

Conversation

@chchatzop

Copy link
Copy Markdown
Collaborator

Fixes #774. Stacked on #904 (which is stacked on #903) - merge those first; all three add at the top of the changelog's Unreleased.

What was wrong

Asked by the operator after @find Metal Church answered 6516 results. A search matched a row when every word appeared somewhere on that file's line, in any order, as a substring - so a band named with two common words matched every file holding both: Metallica ... Church, Church Of Heavy Metal, Churchill. A quoted term was no way out: the quotes were searched for literally and matched nothing - which also means the syntax is free to take.

What changed

  • list.split_search_term(): a part in double quotes is a phrase - its words must appear together, in that order, with only a space, _, -, . or * between them (Metal Church, Metal_Church, metal.church; not Metallica - Church, not Church Of ... Metal). It comes back as a tuple inside the same word list, so every caller that passes the list through gets phrases without a signature change; find_matching_entries() compiles each tuple once per list and matches strings exactly as before.
  • Words outside the quotes keep the old rule: @find "Metal Church" 1986 narrows further. A one-word "phrase" is a word; an unpaired quote is dropped rather than searched for.
  • An unquoted term splits exactly as it always did - tested against a copy of the old rule over a corpus (punctuation, separators, non-ASCII, empty).
  • webserver.split_list_search_words() now calls the same function instead of repeating its code, so @find, the dashboard's Search tab and a list's own search cannot drift apart - their docstrings have always claimed one rule.
  • Untouched: the List Browser's filter bar, which already treats typed words as a phrase (* separates phrases, List Browser: group a bot's several lists under one sidebar row, switch between them above the table #399's beta request).
  • A phrase is matched against the file's line, like the words, not the folder it sits in (Neo's note on the issue).
  • Docs: a -help line, the README, both changelogs - each saying it is this bot's rule: the same @find reaches every bot, and one that does not know quotes answers nothing to a quoted term.

Test

tests/test_a_quoted_phrase_is_matched_together.py (14): the split (unquoted identical to the old rule, phrases, words beside a phrase, separators inside quotes, one-word phrase, unpaired quote, the dashboard using the same function); the match against a real list file (unquoted matches as before, quoted matches only the adjacent in-order forms, a word narrows it, two phrases must both be there, empty still matches everything); and @find itself end to end - the quoted search answers the three band files and neither Metallica nor Church Of Heavy Metal, the unquoted one still answers five. Against the old code the helper does not exist and the quoted @find fails; the unquoted @find passes both ways.

Verified

Full suite on the stacked branch: 6445 OK (19 skipped).

🤖 Generated with Claude Code

https://claude.ai/code/session_01AP6LSxkr4n9dMFNSNMogmW

)

@find Metal Church matched 6516 rows: every word anywhere on a file's
line, in any order. A quoted term matched nothing, so the syntax was
free. list.split_search_term(): a part in quotes is a phrase - adjacent,
in order, with only separators between - carried as a tuple in the same
word list, so every caller passing the list through gets it unchanged;
find_matching_entries() compiles each once per list. Words outside the
quotes keep the old rule; an unquoted term splits exactly as before.
webserver.split_list_search_words() calls the same function. -help and
the README say it, and that it is this bot's rule. 14 tests; both
changelogs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AP6LSxkr4n9dMFNSNMogmW
@chchatzop

Copy link
Copy Markdown
Collaborator Author

Rebased onto the rebased #904 (#903 below it was superseded by #909). Code byte-for-byte the same commit; both changelog entries re-inserted by hand at the top of Unreleased. Full suite on the branch: 6446 OK.

@chchatzop
chchatzop force-pushed the feat/774-a-quoted-phrase-is-a-phrase branch from 21c3623 to 00e5a4a Compare September 23, 2026 07:56
@Ninja-FSE
Ninja-FSE changed the base branch from fix/749-scan-locks-live-in-runtime to main September 23, 2026 10:12
# Conflicts:
#	docs/UPDATES-PUBLIC.md
@Ninja-FSE
Ninja-FSE merged commit 76fec2a into main Sep 23, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@find "Metal Church": a quoted phrase matches the words together, not anywhere

2 participants