A blazing-fast, VSCode-like find and replace plugin for Neovim, powered by ripgrep.
- π Blazing Fast: Powered by ripgrep for lightning-fast project-wide search
- π¨ VSCode-like UI: Familiar vertical sidebar interface with toggle support
- β¨οΈ Interactive Input Fields: Tab navigation between search, replace, include, and exclude fields
- π΄π’ Visual Diff Preview: ast-grep style diff display with
-(red) and+(green) markers - β‘ Live Updates: Debounced search as you type (configurable delay)
- π― Smart Navigation: Jump directly to results with
<CR> - π§ Highly Configurable: Extensive configuration options for UI and search behavior
- π¦ Zero Config Required: Works out of the box with sensible defaults
- π Full Regex Support: Leverage ripgrep's powerful regex engine
- π Multiple Search Modes: Search word under cursor, visual selection, or custom patterns
π§ Demo GIF coming soon
- Neovim 0.9+
- ripgrep - Installation Guide
- nui.nvim - Automatically installed as a dependency
# macOS
brew install ripgrep
# Ubuntu/Debian
apt install ripgrep
# Arch Linux
pacman -S ripgrep
# Windows (Chocolatey)
choco install ripgrep
# Windows (Scoop)
scoop install ripgrep{
'utkayd/wherewolf.nvim',
dependencies = {
'MunifTanjim/nui.nvim', -- Required dependency
},
cmd = 'Wherewolf', -- Lazy load on command
keys = {
{ '<leader>fw', '<Plug>(WherewolfSearch)', desc = 'Wherewolf: Search' },
{ '<leader>fr', '<Plug>(WherewolfToggle)', desc = 'Wherewolf: Toggle' },
{ '<leader>fW', '<Plug>(WherewolfSearchWord)', desc = 'Wherewolf: Search word' },
{ '<leader>fw', '<Plug>(WherewolfSearchVisual)', mode = 'v', desc = 'Wherewolf: Search selection' },
},
opts = {
ui = {
position = "right", -- or "left"
width = 50, -- or "30%"
},
},
}use {
'utkayd/wherewolf.nvim',
requires = { 'MunifTanjim/nui.nvim' },
config = function()
require('wherewolf').setup()
end
}Plug 'MunifTanjim/nui.nvim'
Plug 'utkayd/wherewolf.nvim'For more installation options, see INSTALL.md.
-
Open the sidebar:
:Wherewolf toggle
-
Type your search pattern in the Pattern field
-
Use Tab/Shift-Tab to navigate between fields
-
Press Enter on a result to jump to it
-
Type replacement text and press
Rto apply all replacements
:Wherewolf toggle " Toggle sidebar
:Wherewolf open " Open sidebar
:Wherewolf close " Close sidebar
:Wherewolf search <pattern> " Search for pattern
:Wherewolf replace <pattern> <text> " Search and set replacementwherewolf.nvim provides <Plug> mappings that you can map to your preferred keys:
-- Recommended mappings
vim.keymap.set('n', '<leader>fw', '<Plug>(WherewolfSearch)')
vim.keymap.set('n', '<leader>fr', '<Plug>(WherewolfToggle)')
vim.keymap.set('n', '<leader>fW', '<Plug>(WherewolfSearchWord)')
vim.keymap.set('v', '<leader>fw', '<Plug>(WherewolfSearchVisual)')Available <Plug> mappings:
<Plug>(WherewolfToggle)- Toggle sidebar<Plug>(WherewolfOpen)- Open sidebar<Plug>(WherewolfClose)- Close sidebar<Plug>(WherewolfSearch)- Start search<Plug>(WherewolfSearchWord)- Search word under cursor<Plug>(WherewolfSearchVisual)- Search visual selection<Plug>(WherewolfReplace)- Apply replacements
When the wherewolf sidebar is focused, these keymaps are available:
| Key | Action |
|---|---|
<Tab> |
Next input field |
<S-Tab> |
Previous input field |
<CR> |
Jump to result under cursor |
q / <Esc> |
Close sidebar |
R |
Apply all replacements |
<C-c> |
Clear all input fields |
<C-r> |
Refresh search |
a |
Toggle advanced fields (include/exclude) |
require('wherewolf').setup({
search_engine = "ripgrep",
case_sensitive = false,
multiline = false,
max_results = 1000,
debounce_ms = 150,
ui = {
position = "right", -- "left" or "right"
width = 50, -- number or percentage string "30%"
show_include_exclude = false, -- Show advanced fields by default
auto_focus = true, -- Auto focus when opening
},
rg = {
extra_args = {}, -- Additional ripgrep arguments
respect_gitignore = true, -- Respect .gitignore files
hidden = false, -- Search hidden files
},
})| Option | Type | Default | Description |
|---|---|---|---|
search_engine |
string | "ripgrep" |
Search engine (currently only ripgrep supported) |
case_sensitive |
boolean | false |
Use case-sensitive search |
multiline |
boolean | false |
Enable multiline pattern matching |
max_results |
number | 1000 |
Maximum number of results to display |
debounce_ms |
number | 150 |
Debounce delay for live search (milliseconds) |
| Option | Type | Default | Description |
|---|---|---|---|
ui.position |
string | "right" |
Sidebar position: "left" or "right" |
ui.width |
number/string | 50 |
Width in columns or percentage (e.g., "30%") |
ui.show_include_exclude |
boolean | false |
Show include/exclude fields by default |
ui.auto_focus |
boolean | true |
Auto focus sidebar when opening |
| Option | Type | Default | Description |
|---|---|---|---|
rg.extra_args |
table | {} |
Additional ripgrep command-line arguments |
rg.respect_gitignore |
boolean | true |
Respect .gitignore files |
rg.hidden |
boolean | false |
Search hidden files and directories |
require('wherewolf').setup({
ui = {
position = "left",
width = "40%",
},
})Search Hidden Files and Respect No Ignore Files
require('wherewolf').setup({
rg = {
hidden = true,
respect_gitignore = false,
extra_args = { '--no-ignore' },
},
})require('wherewolf').setup({
debounce_ms = 50, -- Update results after 50ms
max_results = 500, -- Limit results for better performance
})- Input Detection: As you type in the Pattern field, changes are detected via
TextChangedautocmd - Debouncing: Changes are debounced (default 150ms) to avoid excessive searches
- Ripgrep Execution: ripgrep is executed asynchronously via
vim.fn.jobstart() - Output Parsing: Results are parsed from ripgrep's
--vimgrepformat - UI Update: Results are displayed with syntax highlighting and diff markers
- State Management: All state is tracked for restoration and navigation
- Pattern Matching: Uses the search pattern you've defined
- File Grouping: Results are grouped by file for efficient processing
- Content Replacement: Files are read, pattern is replaced using Lua's
string.gsub() - File Writing: Modified content is written back to disk
- Refresh: Search is automatically refreshed to show updated results
- Async Operations: All I/O operations are non-blocking
- Extmarks: Virtual text and highlights are implemented using Neovim's extmark API
- Buffer Management: Custom buffer with
buftype=nofilefor the UI - State Persistence: UI state is preserved across toggles
- Flag Validation: Dangerous ripgrep flags are blacklisted for safety
wherewolf.nvim uses the following ripgrep flags by default:
rg --vimgrep --no-heading --color=never --smart-caseAdditional flags based on configuration:
--smart-case(when not case_sensitive)--case-sensitive(when case_sensitive = true)--multiline(when multiline = true)--max-count=N(based on max_results)--no-ignore(when respect_gitignore = false)--hidden(when hidden = true)
For safety and compatibility, these ripgrep flags are blacklisted:
--binary,--json,--null-data,--null,-0--files,--files-with-matches,--files-without-match,-l,-L
These flags would break the output parsing or change behavior unexpectedly.
- Open wherewolf:
:Wherewolf toggle - Type:
TODOin Pattern field - Navigate results with
j/k, jump with<CR>
- Open wherewolf:
:Wherewolf toggle - Pattern:
oldFunctionName - Replace:
newFunctionName - Review results (shows
-old,+new) - Press
Rto apply all replacements
- Open wherewolf
- Pattern:
your_pattern - Press
ato show advanced fields - Files:
*.lua *.vim - Results update automatically
- Open wherewolf
- Pattern:
function\s+\w+\((finds function declarations) - View all matches across your project
- Open wherewolf
- Pattern:
search_term - Press
afor advanced fields - Exclude:
test/* spec/* node_modules/*
Run Neovim's health check to verify your installation:
:checkhealth wherewolfThis will check:
- β Neovim version (0.9+)
- β ripgrep installation
- β nui.nvim dependency
- β Configuration validity
You can customize the appearance by overriding these highlight groups:
vim.api.nvim_set_hl(0, 'WherewolfTitle', { fg = '#89b4fa', bold = true })
vim.api.nvim_set_hl(0, 'WherewolfInputLabel', { fg = '#f38ba8' })
vim.api.nvim_set_hl(0, 'WherewolfMatchFile', { fg = '#94e2d5' })
vim.api.nvim_set_hl(0, 'WherewolfDiffAdd', { bg = '#1e3a28', fg = '#a6e3a1' })
vim.api.nvim_set_hl(0, 'WherewolfDiffDelete', { bg = '#3c1f1e', fg = '#f38ba8' })
vim.api.nvim_set_hl(0, 'WherewolfDiffAddSign', { fg = '#a6e3a1', bold = true })
vim.api.nvim_set_hl(0, 'WherewolfDiffDeleteSign', { fg = '#f38ba8', bold = true })Available highlight groups:
WherewolfTitle- Sidebar titleWherewolfBorder- Border elementsWherewolfInputLabel- Input field labelsWherewolfInputField- Input field contentWherewolfInputActive- Active input fieldWherewolfMatchFile- File names in resultsWherewolfMatchLine- Line numbersWherewolfMatchText- Matched textWherewolfDiffAdd- Added lines (green background)WherewolfDiffDelete- Deleted lines (red background)WherewolfDiffAddSign-+signWherewolfDiffDeleteSign--signWherewolfSeparator- UI separatorsWherewolfInfo- Info messagesWherewolfWarning- Warning messagesWherewolfError- Error messages
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Clone the repository
- Make your changes
- Test locally by adding to your Neovim config:
{ dir = '~/path/to/wherewolf.nvim', dependencies = { 'MunifTanjim/nui.nvim' }, opts = {}, } - Run health check:
:checkhealth wherewolf - Submit a PR
- Replacement feature is currently basic and doesn't support regex capture groups (coming soon)
- Advanced fields (include/exclude) toggle is not yet fully implemented
- Single replacement (per result) is not yet implemented
- Support for ast-grep as an alternative search engine
- Regex capture groups in replacements
- Per-result replacement (not just all)
- Search history
- Save/load search profiles
- Replace preview with undo capability
- Quickfix integration
- Telescope integration
- Help documentation (
:help wherewolf)
MIT License - see LICENSE file for details
- ripgrep - The amazing search tool that powers this plugin
- nui.nvim - UI component library
- grug-far.nvim - Inspiration for find/replace UI
- telescope.nvim - Inspiration for ripgrep integration
- grug-far.nvim - Find and replace with buffer-based UI
- telescope.nvim - Fuzzy finder with search capabilities
- nvim-spectre - Search and replace panel
Made with β€οΈ for the Neovim community