Multi-word AND search + path-segment matching + substring highlight#84
Merged
Conversation
Extends `matchesNormalizedSearchQuery(_:)` to split search queries by whitespace and require ALL terms to match (AND semantics). Single-term queries degenerate to the v0.4.5 single-contains behavior on each of name / path / path-segments; multi-term queries combine them so "Documents foo" matches `/tmp/work/Documents/foo.txt` via "Documents" segment + "foo" substring of name. Path-segment awareness: term matches if it equals (case-insensitively) any `/`-split segment, NOT as a contiguous substring across segments — so "xDoc" correctly does NOT match `/tmp/Doc/file.txt` even though it's a substring of the joined path string. Substring highlight in result rows rendered via a new `HighlightedText` SwiftUI View struct (Sources/StorageScope/Support/HighlightedText.swift). Extracted as its own struct because the inline ternary `? AnyShapeStyle(.tint) : ...` on matched vs unmatched runs was tripping Swift type-checker timeouts inside the long HStack bodies; matches the established FileTypeRowLabel pattern in TypeBreakdownView.swift, which the v0.5.0 TypeBreakdownView focus work proved out. Wired into StorageItemRow (StorageItemTable.swift) and TreeNodeRow (TreeExplorerView.swift) via store.filters.searchText. Reads zero from FilterStore state other than `.searchText`. FilterStore chip invariants (query / fileTypeFocus mutual exclusivity, searchText didSets instant-clearing query on empty, selectedView auto-clears fileTypeFocus) untouched. New `searchHighlightRanges(for:)` API on StorageItem returns matched String.Index ranges in `name` per term — used for highlighting now, reserved for S2/S4 result-count-badge / Cmd+G find-next navigation work later in v0.5.0. 12 new tests in StorageItemSearchQueryTests.swift cover backward compat, single-term name / path / segment matching, multi-word AND positive + negative, path-segment negative (no substring-across-segments), case-insensitive matching, highlight-range empty / single / multi-term cases. Co-Authored-By: NCode <noreply@noumena.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.
Summary
First Search slice of v0.5.0.
StorageItem.matchesNormalizedSearchQuery(_:)to split queries by whitespace and require ALL terms to match (AND semantics). Single-term queries degenerate to v0.4.5 behavior; multi-term queries combine name / path / path-segments./-split segment — NOT as a contiguous substring across segments."xDoc"correctly does NOT match/tmp/Doc/file.txteven though it's a substring of the joined path string.StorageItemRow(StorageItemTable.swift) andTreeNodeRow(TreeExplorerView.swift) via a newHighlightedTextSwiftUI view struct (Sources/StorageScope/Support/HighlightedText.swift). Extracted because inline? AnyShapeStyle(.tint) : Colorternaries trip Swift type-checker timeouts inside long HStack bodies — same pattern as the establishedFileTypeRowLabelinTypeBreakdownView.swift.Critical invariants preserved
query↔fileTypeFocusmutual exclusivity (untouched)searchText.didSetinstant-clearsqueryon empty (untouched)selectedViewauto-clearsfileTypeFocuson non-applicable views (untouched)matchesNormalizedSearchQuerysignature stays(_ query: String) -> Boolso existing call sites in FilterStore.swift:218, ScanStore.swift:777, ScanStore.swift:1136 keep workingNew API
StorageItem.searchHighlightRanges(for query: String) -> [Range<String.Index>]— matched ranges innameper term. Used for highlighting now; reserved for S2 (search result count badge) and S4 (Cmd+G find-next navigation) later in v0.5.0.Test plan
swift test— 66 tests in 6 suites pass (54 prior + 12 new S1 cases)swift buildsucceeds./script/public_upload_audit.shpassesManual E2E (visual highlight)
Run
bash ./script/build_and_run.sh --fixture-scan, type a multi-word query like"foo bar"into the search field — matched substrings in the file list should render in accent color. Switch to Folder Tree view — same behavior.🤖 Generated with NCode