Project-wide search-and-replace with ripgrep, an interactive picker (fzf-lua or Telescope), live preview, and precise application of changes.
- Features
- Roadmap
- Usage
- Installation
- Configuration
- Safety & Notes
- Development
- License
- Disclaimer
- Feedback
:Replace {old} {new} {scope?} {All?}Parameters:
old required literal (or regex if configured) text to search for
new required replacement text; empty string deletes matches
scope optional: one of:
→ % current buffer (file-backed)
→ cwd current working directory
→ . alias for cwd
→ <path> explicit file or directory
All optional: token; when present, runs non-interactive “replace all” (no picker)
Arguments can now include quotes or escaped quotes:
:Replace "foo bar" "baz qux" %
:Replace \"test\" ok %
:Replace \"test\" \'test\' %These examples demonstrate that:
- Quoted tokens are parsed as single arguments.
- Escaped quotes (
\"or\') are recognized both inside and outside quoted tokens. - Literal quote characters can be searched and replaced.
After picker opened:
fzf-lua:
- Enter: apply to the currently selected entries
- Tab: toggle selection
- Ctrl-A: replace all matches at once (confirmation depends on
confirm_all) - r: replace selected match
Telescope:
- Enter: apply to the highlighted entry
- Tab: toggle selection
- Ctrl-A: replace all matches at once (confirmation depends on
confirm_all) - r: replace selected match
- Project-wide search using ripgrep
--jsonfor precise match coordinates - Interactive selection via either
fzf-luaortelescope.nvim - Live context preview around each match
- Replace only the selected occurrences; or replace all at once
- Handles multiple matches per line robustly (each occurrence selectable)
- Bottom-up in-buffer edits to avoid offset shift bugs
- Literal mode by default; Regex mode opt-in
- Optional write-to-disk on apply (or keep changes unsaved)
- Configurable syntax highlighting in Telescope preview
- Strong EmmyLua annotations and type hints for LuaLS
- Clean, modular code layout (search, apply, pickers, command, config)
- Supports escaped quotes and backslashes in command arguments
- Non-interactive “All” mode via
:Replace ... All - Backend switch:
engine = "fzf"or"telescope" - Confirm-all guard and write/no-write switch
- Quote and escape support for command arguments
- Multiple occurrences per line handled correctly
- Configurable highlighting for Telescope previews
- fzf-lua highlight parity
- vimgrep implementation
- Optional diff-style preview (before/after)
- Built-in help
:help replacer - Health-Module to provide
:checkhealth-usercommand
Requirements:
- Neovim 0.9 or newer
- ripgrep (
rg) inPATH - One picker:
nvim-telescope/telescope.nvim(+nvim-lua/plenary.nvim) (default)ibhagwan/fzf-lua
{
"StefanBartl/replacer",
name = "replacer.nvim",
main = "replacer",
opts = {
engine = "telescope", -- "fzf" | "telescope"
write_changes = true, -- write buffers after replace
confirm_all = true, -- ask before replacing all
hidden = true, -- include dotfiles
git_ignore = true, -- respect .gitignore
exclude_git_dir = true, -- skip .git/ explicitly
literal = true, -- fixed-strings by default
smart_case = true, -- ripgrep -S
fzf = { -- extra fzf-lua options (optional)
winopts = { width = 0.85, height = 0.70 },
},
telescope = { -- extra telescope options (optional)
layout_config = { width = 0.85, height = 0.70 },
},
},
}Available Options:
| Option | Type | Description |
|---|---|---|
| engine | string | Picker backend: "fzf" / "telescope" |
| write_changes | boolean | Write modified buffers on apply (true) or keep unsaved (false) |
| confirm_all | boolean | Ask confirmation before replacing all matches at once |
| preview_context | integer | Context lines shown in preview around the hit |
| preview_marker | string | Custom marker/prefix in preview highlighting |
| hidden | boolean | Include dotfiles (--hidden) |
| git_ignore | boolean | Respect .gitignore (false → --no-ignore) |
| exclude_git_dir | boolean | Exclude .git directory explicitly (--glob !.git) |
| literal | boolean | Literal search (--fixed-strings); set false for regex mode |
| smart_case | boolean | Smart-case (-S) |
| fzf | table? | Extra options for fzf-lua (merged into picker opts) |
| telescope | table? | Extra options for Telescope picker (theme/layout) |
Minimal:
require("replacer").setup({})Full example:
require("replacer").setup({
engine = "telescope",
write_changes = false,
confirm_all = true,
hidden = true,
git_ignore = true,
exclude_git_dir = true,
literal = true,
smart_case = true,
telescope = { layout_config = { width = 0.9, height = 0.8 } },
})- Edits are applied bottom-up per file to avoid index shift issues.
- Each occurrence is verified against the original text before editing; mismatches are skipped and reported.
- When
write_changes = false, buffers stay modified—review and:writemanually or use VCS hunk staging. - Literal mode is the default; for regex, set
literal = falseand provide proper patterns. - ripgrep must be installed and discoverable via
PATH.
- Repository layout follows standard
lua/<plugin_name>/...convention for Lazy.nvim. - Type hints use EmmyLua; LuaLS-friendly stubs are provided where helpful.
- Local hacking via
dir = "/path/to/replacer". - Typical debug flow:
:Replace foo bar cwd- In picker, inspect preview; Tab to select specific hits; Enter to apply
- Ctrl-A to replace all with confirmation
- Set
write_changes=falseto review changes before writing
ℹ️ This plugin is under active development – some features are planned or experimental. Expect changes in upcoming releases.
Your feedback is very welcome!
Please use the GitHub issue tracker to:
- Report bugs
- Suggest new features
- Ask questions about usage
- Share thoughts on UI or functionality
For general discussion, feel free to open a GitHub Discussion.
If you find this plugin helpful, consider giving it a ⭐ on GitHub — it helps others discover the project.