To solve this I wrote a little plugin (that I finished as a plugin yesterday and uploaded just now): https://github.com/orlp/vim-quick-replace
It requires vim-repeat (and a patched one because the current one has an issue): https://github.com/orlp/vim-repeat
The nice thing is that it always jumps to the next match before replacing, and if you choose to replace the current match it immediately jumps to the next one, so that you can evaluate whether you want to replace it.
You can start in two quick ways: using the current word under the cursor or the current visual selection, so it's very flexible. For me replacing a variable name is often just putting my cursor on it, pressing space + r, typing the replacement name and then a couple .'s, n's and if I mess up some u's.
To see it in action: https://i.imgur.com/wEX6O1w.mp4
Vim can also take a command that yields a list of filenames as a launch parameter via something like `vim $(ag -l target_string)`, letting you go through each file with a `:n`, letting you complete large refactors surprisingly quickly.
:%s/debug/dbg/c
vim will show the text which is about to be modified, and you have a prompt to confirm, skip, or quit (and some others).
And you would still need some nice mappings to substitute the word/selection underneath the cursor with :%s///gc.
(This is very unlikely to interest you, but I mention it for the sake of others. I’ve commonly seen people not really know about ranges especially, never stopping and thinking about what the % means (see `:help :%` if you don’t know), beyond possibly having encountered '<,'> by accident when pressing : in Visual mode (for explanation of these, see the help for :', '< and '>).)
You'd have to do *, then N to back to where you just were, then cgn, type your replacement, and then n., n., n., n (skip), n., etc.
With my plugin that just becomes one mapping, type your replacement, ., ., n (skip), ., etc.
It's just very smooth, which I like because I use this operation literally all the time. Hell, I'll even use it when changing a single variable, just to make sure there isn't another sneaky one in the file somewhere.
Works a treat!
Since Vim keeps an undo tree, you are guaranteed not to lose anything anyway.
It also has the downside that it doesn't match what is being shown: when I hit * on "overview" it highlights both "overview" and "Overview" (I have highlight search enabled), but cgn replaces only one of them. When the cursor is on Overview and I run "*cgnexample<esc>..." it will skip all the "Overview"s and only replace "overview".
But perhaps it's a bug in Vim since it works when I run * on the lowercase variant.
"Press space to highlight current word
nnoremap <silent><space>
\ :let @/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
This works just like *, except that it leaves your cursor where it is. You can then use n/p/whatever as normal.Ooooh that is great! I use *# every time and am then annoyed when the n key goes backwards instead of forwards and then I try to remember to do #* instead and pff... ^^ This will solve those issues!
Edit: also because I try and keep my keybinds as close to default as I can, and <space> is oddly underused.
Per the help it's a feature, and it's infuriating! (From :help star)
> 'ignorecase' is used, 'smartcase' is not.
Here's your workaround:
" By default, * and # respect 'ignorecase'. This mapping forces these commands
" to search case sensitively, which is usually what you want when searching
" code with * or #. May be less good for prose.
nnoremap <silent> * /\C\<<C-R>=expand('<cword>')<CR>\><CR>
nnoremap <silent> # ?\C\<<C-R>=expand('<cword>')<CR>\><CR>> This replaces, like, 97% of uses of :s and is a much more convenient way to do search/replace, especially if you use * to search for the word under the cursor. It’s the bee’s knees!
I'm not really sure about that. I can definitely see it replacing :s for a small number of repetitions, but for a large number. I think using :s with a range is quicker.
Edit: typos, punctuation
:%s//replace/gcWhat I mean is: if I'm on a (say) a variable name, and I change it with "cw", then realize I actually need to change it in a few more places, I can use a little shortcut to change it in those places, without even thinking of it beforehand.
The shortcut is:
" Make <leader>. repeat the last "change word" command.
nnoremap <leader>. :let @/=@"<cr>/<cr>cgn<c-r>.<esc>
After any change command, just hit <leader>. to repeat it. You can thereafter hit "." to repeat again.I could only think of this rather awkward sequence:
1. Yank to named register
2. Search
3. "cgn"
4. Ctrl-R to paste from named register
5. Repeat
This is actually the biggest gripe I have with vim, even after almost 10 years of constant use. Vim always seems to overwrite the default register when I don't want it to. This makes replacing multiple bits of text with one pasted value awkward. I feel like I'm missing some essential shortcut or configuration that everybody else knows. It can't just be named registers, right?
1. Yank using y without specifying a register
...
4. CTRL-R 0
Deletes and changes don't touch the 0-register. It always contains your last (unnamed) yank.
nnoremap <key> *``cgn
nnoremap <key> #``cgN
Hit <key> to change the current word and ... to repeat on the next occurrences.
Thank you for the tip.
The g and z set of commands are pretty useful in vim.
It's pretty comprehensive. Personally I'd just install Doom Emacs though :)
Most of the time it's more keystrokes than using :s though, so I'm not a big fan of it. But I see the appeal :)
set inccommand=nosplit
It will display the substitute directly in the buffer.
It's also better if you don't actually want to replace in the whole file and there's no convenient shorthand for the range.
I very rarely use :s myself, I'm always too worry that I'm going to clobber something I didn't mean to, I prefer to search and manually repeat a substitution. s can do it with with the "c" modifier but I find that using normal edit commands is both more flexible and easier to remember.
There's a vim extension for multiple cursors but it's a little buggy.
⁰https://sr.ht/~martanne/vis/ ¹http://doc.cat-v.org/bell_labs/structural_regexps/ ²http://doc.cat-v.org/bell_labs/sam_lang_tutorial/ ³http://kakoune.org/
The main purpose I've seen is basically block mode (like ctrl+v) or (iirc) repeating things on multiple hits (like n. or indeed cgn).
The thing that makes it golden is that it is a motion, and thus combined with a command, it is repeatable! So, like:
1. Search for something (either using / or *).
2. Type ”cgn” in Normal mode (i.e. change next search match) and replace what you searched for with whatever
3. Hammer on ”.” (i.e. repeat last command) to replace other matches.
This replaces, like, 97% of uses of :s and is a much more convenient way to do search/replace, especially if you use * to search for the word under the cursor. It’s the bee’s knees!