Say how many notes a search matched, and why each one is there - #112
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #35.
The count existed and was thrown away
NotesView.matchedis computed in Rust and crosses the bridge, and was read inexactly one place — to decide
view.matched === 0. It now shows in the searchfield, 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() !== nulland not a truthiness check. Zero is the answer thatmatters 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
helmon a notewhose 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::viewnow answers where it matched and quotes the line: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.
SearchFieldhas no
Titlevariant so the case cannot be forgotten, and "matched on the title"is a variant of
SearchMatchthat 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 inthe 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_countsand
apply_global_defaults, and for the same reason: the notes becomeDisplayNotes insidebuild_sections, and threading a second value through itwould 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
highlightLinesinto[innerHTML], so wrapping matches in<mark>meanscomposing with the highlighter's output, never a
replaceover already-taggedHTML.
One trap found on the way
07-checklistsfailed on a canvas holding a single card.own tests before its nested suites, so a
describeblock is the last thing inits 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 test967 passing,cargo testall green,cargo clippy --all-targets --all-features -D warningsandcargo fmt --checkclean,npm run lintclean,npm run test:e2e15/15 in 4:03.🤖 Generated with Claude Code