Skip to content

Say how many notes a search matched, and why each one is there - #112

Merged
vmillet-dev merged 1 commit into
mainfrom
feat/search-says-how-many-and-why
Sep 14, 2026
Merged

vmillet-dev merged 1 commit into
mainfrom
feat/search-says-how-many-and-why

Conversation

@vmillet-dev

Copy link
Copy Markdown
Owner

Closes #35.

The count existed and was thrown away

NotesView.matched is computed in Rust and crosses the bridge, and was read in
exactly one place — to decide view.matched === 0. It now shows in the search
field, taking the shortcut hint's place: the hint is what you need before you
search, the count is what you need once you have.

⚠️ matched() !== null and not a truthiness check. Zero is the answer that
matters most, and it is the one a falsy test swallows — there is a spec on it.

The excerpt is the real gap

A card's preview was the first lines of the body, so searching helm on a note
whose match sits at line forty gave back lines 1 to 3 and no reason for the card
being there at all. A match in a tag or a checklist item was worse: the preview
never showed either.

Following the rule of the codebase — the back end decides, the front displays —
notes::view now answers where it matched and quotes the line:

matched in the card shows
the body that line, trimmed of its indentation, still syntax-coloured
a tag the tag, as prose — the highlighter would paint its words as keywords
a checklist item the item's text, likewise
the title nothing new — the head of the body, as outside a search

That last row is a decision, not an omission: the title is the biggest thing on a
card, and quoting it back would repeat what the reader is looking at. SearchField
has no Title variant so the case cannot be forgotten, and "matched on the title"
is a variant of SearchMatch that carries nothing.

The excerpt is clipped at 160 characters — a body is free to hold a minified
payload on one line, and without the clip the whole of it would cross the bridge
to be thrown away by overflow. Characters and not bytes: s[..160] panics in
the middle of an é, and there is a test that would have caught it.

The hits are collected while filtering rather than looked for again afterwards,
then applied in a pass of their own — the same shape as apply_attachment_counts
and apply_global_defaults, and for the same reason: the notes become
DisplayNotes inside build_sections, and threading a second value through it
would have cost every section-splitting test an argument.

Not in this one

Highlighting the matched substring inside the excerpt. The ticket names it as a
separate, smaller step and names its trap — the preview goes through
highlightLines into [innerHTML], so wrapping matches in <mark> means
composing with the highlighter's output, never a replace over already-tagged
HTML.

One trap found on the way

07-checklists failed on a canvas holding a single card. ⚠️ Mocha runs a suite's
own tests before its nested suites, so a describe block is the last thing in
its file whatever its position in it — and one process serves the whole run, so
the search my block left in the field was inherited by the next spec file. It
clears up after itself now, and says why.

Checked locally

npm test 967 passing, cargo test all green, cargo clippy --all-targets --all-features -D warnings and cargo fmt --check clean, npm run lint clean,
npm run test:e2e 15/15 in 4:03.

🤖 Generated with Claude Code

NotesView.matched was computed in Rust, crossed the bridge and decided a
single boolean before being thrown away. It is now shown, in the search
field, where it takes the shortcut hint's place.

The excerpt is new. A card's preview was the first lines of the body, so
a note matched at line forty came back with nothing explaining why. The
back end says where it matched and quotes that line — and quotes nothing
for a title match, the card already showing it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vmillet-dev
vmillet-dev merged commit 2e0b47e into main Sep 14, 2026
9 checks passed
@vmillet-dev
vmillet-dev deleted the feat/search-says-how-many-and-why branch September 14, 2026 22:38
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.

Search says neither how many matched nor why

1 participant