I’d like to change a sequence of the same characters in multiple places within a file.
Ideally I would select the characters, highlight all the matches (with an indicator to show how many matches) and then change the sequence, in part or in full
Example: I’d like to change mutliple occurances of ./bin/test with clojure -X:env/test:test/run (which can also be in a register after cutting from elsewhere)
I am aware I can do :/s/patern/replacement/gn but that does mean typing the initial pattern rather than selection.
Any other approaches?
is there an equivalent neovim plugin for https://github.com/victorhge/iedit ?
If i understand the requirement correctly, you want to do a replace in a selection? In that case maybe doing a visual-line select of the area and then doing the search replace would work? Neovim should also preview the replacement as you type
Try this (replace hello with world and c means that you will go one-by-one):
:%s/hello/world/gc
Then press y to replace each occurence and n to skip
when replacing in a selection, the command would look something like :'<,'>s/foo/bar/gc
The '<,'> would be put automatically when you hit : in visual mode
What I would do in this simple example:
* select text I want to replace using visual mode
* press * to search for other occurrences
* run substitution :%s//new-text
note the substitute command uses the latest search pattern when left empty (the one started with *)
Registers are available in command-line mode via CTRL-R , so with the cursor on what you'd like to replace, doing :%s/ CTRL-R CTRL-A /new-text will pull the WORD under the cursor into the ex command. CTRL-R CTRL-W for word under the cursor, and if you're using evil-mode, CTRL-R CTRL-O for symbol under the cursor, which is really handy for clojure. Little bit more control than @nbardiuk’s suggestion, which I also like.
This sounds great, although in my particular example * is not matching the whole sequence, it stops when it gets to / character.
The same issue with / occurs when entering the replacement text, as I assume Vim command line thinks its a command or something other than the text to replace.
Without the / in the search and replace characters, then this is a very useful tip, thanks.
/ is arbitrary. You can do :%s#foo#bar (or any char you like) [edit: not sure I understood you correctly, but maybe a useful tip anyway]
You can also escape / by typing \/ 🤷
As, so for replace I can use any character as a separator, so long as its not in the sequence of characters that are the replacement text.
I havent figured out how to select past a / character using * yet..
Closest I have come is as @rahul080327 mentioned, select all the text and do a substitute command, using # as a separator character
:'<,'>s#./bin/test#clojure -X:env/test:test/run
Not as simple as iedit in Emacs, but good to know. Thanks everyone.what do you get by doing :set iskeyword ? in neovim I see it includes / for lisps, but not in vim. You can add a / by doing :set iskeyword+=/
There is also cdo , can do a search to find it in the “project”, and then cdo to update them… see this post https://chrisarcand.com/vims-new-cdo-command/
also, if you have already searched for the match, you can do a :'<,'>s##clojure -X:env/test:test/run and leave the search empty and it will use the last search
I have the following in place:
1. * and # are overridden with the https://vim.fandom.com/wiki/Search_for_visually_selected_text#Advanced
2. I have set inccommand=nosplit set so that when I type a replacement it shows it in the buffer.
3. I visually highlight what I want to replace and hit *, and this shows me a count in the command area.
4. I run :%s//replacement/g to do the replacement.
a. I can optionally add a c for confirmation
b. Sometimes between the first two // I do [ctrl-r]/ which will fill in the search, fully escaped thanks to the mapping in #1
Setting set inccommand=split will pop up a window at the bottom showing matches and updating as you type the replacement.
1. v<movement> - select the text I'd like to replace
2. * - search for selection (with the "advanced mappings" that @nate mentioned)
3. gv - reselect last selection
4. c<new-text><Esc> -
5. Go n.n.n.... for each search match
This is far less elegant than the other solutions, but has a few advantages:
• Working on a selection is much more reliable to me, than trying to get the search pattern right in cmd-mode. Especially when there are special chars involved that need to be escaped. (Name spaced keywords have /s too 😓)
• You can use full insert mode to create your replacement text. This is handy when (e.g.) you want to replace text with something long and auto-completable.
• You have the same one-at-a-time semantics as with :s//c. I find that I often don't want to replace all occurrences, especially when doing sub-word replacements.
Steps 3+4 are actually just a lazy way to do c<n><Space>. This could also be replaced with any other motion or text object, like cw, cE (vim-sexp), or even cif (vim-sexp). This turns your selection into a search-and-replace starting point, rather than the entire search pattern. It's also .-repeatable, but you probably need vim-repeat for some of them.
This is super useful if, e.g., you have a bunch of similar forms that share a search pattern, and you'd like to replace all content in each of those forms.
When I do use cmd-mode :s (if there are many replacement sites), I usually still do visual selection first, and then insert it in cmd-mode from the / register with <C-r>/. This affords you the opportunity to edit customize the search pattern. Otherwise it's equivalent to :s//.