docs/internal/search-next-occurrence.md
GitHub Issue #489: Allow searching for the next occurrence of the currently selected text using a keyboard shortcut, without opening the find panel.
VSCode has two related but distinct features:
Ctrl+F3 (editor.action.nextSelectionMatchFindAction):
Ctrl+D (editor.action.addSelectionToNextFindMatch):
Ctrl+Shift+L (editor.action.selectHighlights):
quick_add_next): Selects word under cursor, then finds/selects next occurrenceImplement a "quick find" feature that searches for the current selection without opening the find panel. The search term integrates with the existing search system so subsequent F3/Shift+F3 navigation works seamlessly.
| Shortcut | Action | Description |
|---|---|---|
| Ctrl+F3 | find_selection_next | Find next occurrence of selection |
| Ctrl+Shift+F3 | find_selection_previous | Find previous occurrence of selection |
These shortcuts align with Visual Studio, VS Code, and the user's expectations mentioned in the issue.
User selects text → Presses Ctrl+F3 → Cursor jumps to next occurrence
→ Selection text becomes search term
→ Status bar shows "Match X of Y"
| Condition | Behavior |
|---|---|
| Has selection | Use selected text as search term |
| No selection, cursor on word | Auto-expand to word under cursor (like Ctrl+D in VSCode) |
| No selection, cursor on whitespace/punctuation | Show status message "No text to search" |
The quick find should use sensible defaults that differ from the search panel:
| Option | Default for Ctrl+F3 | Rationale |
|---|---|---|
| Case Sensitive | OFF | Most "quick find" use cases are case-insensitive |
| Whole Word | OFF | User selected exactly what they want to find |
| Regex | OFF | Literal text search (escape special chars) |
| Wrap | ON | Seamless navigation through document |
Note: If the user had previously used the search panel with specific options (e.g., case-sensitive ON), those options should be preserved. Ctrl+F3 only sets the search term, not the options.
After using Ctrl+F3:
SearchState.querySearchState.matchesF3 and Shift+F3 continue to navigate through matchesCtrl+F opens the find panel pre-filled with the search termThis matches the behavior described in the feature request:
"once you searched a 'selection occurrence', the text of the selection will be treated as if you searched for text regularly"
| Action | Cursor Position | Selection |
|---|---|---|
| Find next (Ctrl+F3) | Start of match | Match is selected |
| Find previous (Ctrl+Shift+F3) | Start of match | Match is selected |
Selecting the match allows the user to:
| Scenario | Behavior |
|---|---|
| Selection contains newlines | Use full selection (multi-line search) |
| Selection is empty string | Treat as "no selection" - expand to word |
| No matches found | Show "No matches for 'text'" in status bar |
| Single match (the selection itself) | Show "This is the only match" |
| Very long selection (>100 chars) | Still search, but truncate in status messages |
Searching... (brief, during search)
Match 3 of 15 (normal navigation)
Match 1 of 15 (wrapped) (wrapped around)
No matches for 'searchterm' (no results)
This is the only match (single occurrence)
No text to search (no selection/word)
// In src/input/keybindings.rs - Action enum
FindSelectionNext, // Ctrl+F3
FindSelectionPrevious, // Ctrl+Shift+F3
// In src/app/render.rs or similar
/// Finds next occurrence of current selection or word under cursor
fn find_selection_next(&mut self) {
// 1. Get search text from selection or word-at-cursor
// 2. Escape regex special characters (literal search)
// 3. Call perform_search() with the text
// 4. Call find_next() to move to next match
// 5. Select the match
}
/// Finds previous occurrence of current selection or word under cursor
fn find_selection_previous(&mut self) {
// Similar to above, but calls find_previous()
}
The implementation should reuse existing search infrastructure:
SearchState - Store the query and matches (already exists)perform_search() - Compute all matches (already exists)find_next() / find_previous() - Navigate matches (already exists)update_search_highlights() - Visual feedback (already exists)The only new code needed is:
default.jsonAdd to /keymaps/default.json:
{
"comment": "Quick find - search selection next",
"key": "F3",
"modifiers": ["ctrl"],
"action": "find_selection_next",
"args": {},
"when": "normal"
},
{
"comment": "Quick find - search selection previous",
"key": "F3",
"modifiers": ["ctrl", "shift"],
"action": "find_selection_previous",
"args": {},
"when": "normal"
}
Fresh already has Ctrl+D bound to add_cursor_next_match (multi-cursor). The proposed Ctrl+F3 is complementary:
| Shortcut | Action | Multi-cursor? |
|---|---|---|
| Ctrl+D | Add cursor at next match | Yes (cumulative) |
| Ctrl+F3 | Jump to next match | No (navigation only) |
Both features are useful:
This design provides: