Repository navigation
Prioritize full command palette title matches - #6498
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds a word-normalized title representation ( ChangesSearch Word Normalization and Emoji-Prefixed Title Ranking
Sequence DiagramsequenceDiagram
participant IndexInit as Index Creation
participant SearchFn as Word Extraction
participant Candidate
participant Scorer as Scoring Engine
participant FuzzyMatcher as Fuzzy Matcher
participant TitleWordScore as Title Word Score
participant Result as Ranked Results
IndexInit->>SearchFn: Extract words from title
SearchFn-->>Candidate: Store search_title (alphanumeric words)
FuzzyMatcher->>Scorer: Prepared query
Scorer->>FuzzyMatcher: Score fuzzy matches
Scorer->>TitleWordScore: Normalize title word text
TitleWordScore->>TitleWordScore: Match exact or prefix
TitleWordScore-->>Scorer: Award token + scaled bonus
Scorer->>Scorer: max(fuzzyScore, titleScore, wordScore)
Scorer-->>Result: Highest-scoring entries first
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 23✅ Passed checks (23 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryFixes command palette ranking for emoji-prefixed entries by introducing
Confidence Score: 5/5Safe to merge: the new scoring tier is additive, the guard restricts the bonus to entries where stripping emoji segments actually changes the text, and all three regression scenarios are covered by both package and app-target tests. The logic is self-contained, the reference scorer mirrors the production implementation exactly, and the tests exercise the precise failure modes that prompted the fix. No actor isolation, blocking primitive, or source-control issues are introduced. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["weightedScore(preparedQuery, entry)"] --> B{fuzzyScore non-nil?}
B -- No --> Z[return nil]
B -- Yes --> C{preparedTitle non-nil AND titleScore non-nil?}
C -- No --> R1[return fuzzyScore]
C -- Yes --> D["max(fuzzyScore, titleScore+2000, commandPaletteTitleWordScore??Int.min)"]
D --> E[commandPaletteTitleWordScore]
E --> F{query empty OR titleSearchWordText == titleNormalizedText?}
F -- Yes --> G[return nil]
F -- No --> H{titleSearchWordText == normalizedTokenText?}
H -- Yes exact --> I["exactTokenScore + 2000 x tokenCount"]
H -- No --> J{titleSearchWordText hasPrefix normalizedTokenText?}
J -- Yes prefix --> K["prefixTokenScore + 2000 x tokenCount"]
J -- No --> L[return nil]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["weightedScore(preparedQuery, entry)"] --> B{fuzzyScore non-nil?}
B -- No --> Z[return nil]
B -- Yes --> C{preparedTitle non-nil AND titleScore non-nil?}
C -- No --> R1[return fuzzyScore]
C -- Yes --> D["max(fuzzyScore, titleScore+2000, commandPaletteTitleWordScore??Int.min)"]
D --> E[commandPaletteTitleWordScore]
E --> F{query empty OR titleSearchWordText == titleNormalizedText?}
F -- Yes --> G[return nil]
F -- No --> H{titleSearchWordText == normalizedTokenText?}
H -- Yes exact --> I["exactTokenScore + 2000 x tokenCount"]
H -- No --> J{titleSearchWordText hasPrefix normalizedTokenText?}
J -- Yes prefix --> K["prefixTokenScore + 2000 x tokenCount"]
J -- No --> L[return nil]
Reviews (3): Last reviewed commit: "Prioritize full command palette title ma..." | Re-trigger Greptile |
| return exactTokenScore + commandPaletteScaledTitleMatchBonus(tokenCount: preparedQuery.tokens.count) | ||
| } | ||
|
|
||
| guard preparedTitle.normalizedSearchWordText.hasPrefix(preparedQuery.normalizedText) else { |
There was a problem hiding this comment.
Character-level prefix check can give false prefix matches mid-word
hasPrefix compares characters with no word-boundary awareness. A title whose normalizedSearchWordText is "command palettist" would satisfy hasPrefix("command palette"), earning the same prefix-tier bonus as "command palette archive". In practice this is unlikely to cause a visible mis-ranking (both are reasonable prefix results and they'd share the same score, deferring to rank/title tiebreak), but it is a latent gotcha if titles with words that merely start with a query token start accumulating the prefix bonus in unexpected ways.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| if !candidate.search_title.is_empty() | ||
| && state | ||
| .atom_score(&query.exact, &candidate.search_title) | ||
| .is_some() | ||
| { | ||
| return Some(TITLE_EXACT_TOKEN_SCORE * token_count); | ||
| } | ||
| if state.atom_score(&query.prefix, &candidate.title).is_some() { | ||
| return Some(TITLE_PREFIX_TOKEN_SCORE * token_count); | ||
| } | ||
| if !candidate.search_title.is_empty() | ||
| && state | ||
| .atom_score(&query.prefix, &candidate.search_title) | ||
| .is_some() | ||
| { | ||
| return Some(TITLE_PREFIX_TOKEN_SCORE * token_count); | ||
| } | ||
| None |
There was a problem hiding this comment.
search_title casing is not normalized before atom_score comparison
title_search_word_text preserves the original casing of the title (e.g. "Command Palette"), so search_title is stored in mixed case. atom_score uses Nucleo's smart-case / case-insensitive matching so a lowercase query like "command palette" still matches "Command Palette" — this works correctly. However, note that if atom_score's case-folding behaviour ever changed or the atom was created with case-sensitive mode, the search_title check would start failing while the raw title check would also fail for emoji-prefixed entries, silently dropping the whole title-literal bonus for those rows. Worth a brief inline comment documenting that search_title relies on Nucleo case folding.
8c02517 to
599a0e1
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 599a0e1. Configure here.
599a0e1 to
f330ee0
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Native/CommandPaletteNucleoFFI/src/lib.rs`:
- Around line 685-706: The `is_title_word_boundary` function used in
`title_search_word_text` is treating backslash as a word boundary in Rust, but
Swift's `tokenBoundaryChars` does not include backslash, causing ranking
inconsistency. Review the `is_title_word_boundary` function to identify the
boundary character set it uses and either remove the backslash character from
the Rust implementation to match Swift, or add backslash to Swift's
`tokenBoundaryChars` to match Rust, ensuring both implementations split titles
identically.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 32511209-be47-47d2-bb87-97f4b2c1654e
📒 Files selected for processing (7)
Native/CommandPaletteNucleoFFI/src/lib.rsPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swiftPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchEngine.swiftPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchWordText.swiftPackages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteEmojiTitleSearchTests.swiftPackages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchEngineTests.swiftPackages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchReferenceScoring.swift
| fn title_search_word_text(title: &str) -> String { | ||
| let mut words = Vec::new(); | ||
| let mut current = String::new(); | ||
| for character in title.chars() { | ||
| if is_title_word_boundary(character) { | ||
| append_search_word(&mut words, &mut current); | ||
| continue; | ||
| } | ||
| current.push(character); | ||
| } | ||
| append_search_word(&mut words, &mut current); | ||
| words.join(" ") | ||
| } | ||
|
|
||
| fn append_search_word(words: &mut Vec<String>, current: &mut String) { | ||
| if current.chars().any(char::is_alphanumeric) { | ||
| words.push(std::mem::take(current)); | ||
| } else { | ||
| current.clear(); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Align title-word boundary rules between Rust and Swift.
The new search_title path splits on \ in Rust, but Swift’s tokenBoundaryChars does not. That creates ranking drift between Nucleo FFI and Swift fallback for titles containing backslashes, which breaks the parity this PR is aiming for.
Use the same boundary set in both layers (either add \ in Swift or remove it here) so search_title normalization is identical across implementations.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Native/CommandPaletteNucleoFFI/src/lib.rs` around lines 685 - 706, The
`is_title_word_boundary` function used in `title_search_word_text` is treating
backslash as a word boundary in Rust, but Swift's `tokenBoundaryChars` does not
include backslash, causing ranking inconsistency. Review the
`is_title_word_boundary` function to identify the boundary character set it uses
and either remove the backslash character from the Rust implementation to match
Swift, or add backslash to Swift's `tokenBoundaryChars` to match Rust, ensuring
both implementations split titles identically.
7324e4a to
983c5e3
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
Native/CommandPaletteNucleoFFI/src/lib.rs (1)
685-706:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUnify title-word boundary rules with Swift to avoid ranking drift.
Line 708 treats
\as a word boundary, but Swift’sCommandPaletteFuzzyMatcher.tokenBoundaryChars(Line 44 inPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swift) does not. That makessearch_titlenormalization diverge between Rust FFI and Swift fallback for backslash-delimited titles.Suggested minimal fix (align Rust to current Swift boundary set)
fn is_title_word_boundary(character: char) -> bool { - matches!(character, ' ' | '-' | '_' | '/' | '\\' | '.' | ':') + matches!(character, ' ' | '-' | '_' | '/' | '.' | ':') }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Native/CommandPaletteNucleoFFI/src/lib.rs` around lines 685 - 706, The Rust implementation of title_search_word_text uses the is_title_word_boundary function to determine word boundaries, but it currently treats backslash (\) as a boundary character, which differs from Swift's CommandPaletteFuzzyMatcher.tokenBoundaryChars that does not include backslash. To unify the behavior between Rust FFI and Swift fallback, locate the is_title_word_boundary function and remove backslash from its set of boundary characters so the search title normalization matches the Swift implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@Native/CommandPaletteNucleoFFI/src/lib.rs`:
- Around line 685-706: The Rust implementation of title_search_word_text uses
the is_title_word_boundary function to determine word boundaries, but it
currently treats backslash (\) as a boundary character, which differs from
Swift's CommandPaletteFuzzyMatcher.tokenBoundaryChars that does not include
backslash. To unify the behavior between Rust FFI and Swift fallback, locate the
is_title_word_boundary function and remove backslash from its set of boundary
characters so the search title normalization matches the Swift implementation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a4559706-0c8b-4271-9d1b-871a272a8072
📒 Files selected for processing (7)
Native/CommandPaletteNucleoFFI/src/lib.rsPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swiftPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchEngine.swiftPackages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchWordText.swiftPackages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteEmojiTitleSearchTests.swiftPackages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchEngineTests.swiftPackages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchReferenceScoring.swift
6ed6653 to
55f2056
Compare
55f2056 to
15fd564
Compare
Summary
Testing
command palette, verifiedCommand Paletteranks aboveCommand Palette ArchiveIssues
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Note
Low Risk
Localized search-ranking changes with dual-path parity tests; no auth, data, or network surface—only Cmd+P result ordering.
Overview
Command palette ranking now treats visible title words (alphanumeric segments only, dropping emoji/symbol-only chunks) as a first-class match target, so queries like
command paletteprefer 🧪 Command Palette over Command Palette Archive or rows that only hit hidden keywords.Swift: Corpus entries precompute
normalizedTitleSearchWordText;PreparedQueryaddsnormalizedTokenText(tokens joined with single spaces).CommandPaletteSearchEnginetakes the max of fuzzy score, title fuzzy + bonus, and a new title-word exact/prefix tier keyed offnormalizedTokenText(including repeated spaces in the query). Shared helpercommandPaletteNormalizedSearchWordTextmirrors the Rust word extraction.Rust (Nucleo FFI): Each candidate stores
search_titlefrom the same word-stripping logic;title_literal_scoreapplies exact/prefix atom checks againstsearch_titlewhen the raw title does not match.Reference scoring and regression tests cover Swift engine, Nucleo FFI, and emoji-prefixed / hidden-token ordering cases.
Reviewed by Cursor Bugbot for commit 15fd564. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Prioritize command palette results whose visible title words exactly or prefix-match the query, including emoji-prefixed titles. Full-title matches now outrank partial title prefixes and hidden keyword hits across Swift and
NucleoFFI.normalizedTitleSearchWordTextin Swift andsearch_titlein Rust; use it for exact/prefix title tiers.PreparedQuery.normalizedTokenText(handles repeated spaces).NucleoFFI, and a reference scorer aligned; add regression tests for emoji-prefixed full/prefix matches, repeated-space queries, and cross-FFI ordering.Written for commit 15fd564. Summary will update on new commits.
Summary by CodeRabbit
Release Notes