Fork me on GitHub
#vim
<
2022-11-03
>
practicalli-johnny09:11:46

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 ?

lispyclouds09:11:32

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

Martynas Maciulevičius09:11:07

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

lispyclouds09:11:02

when replacing in a selection, the command would look something like :'<,'>s/foo/bar/gc

lispyclouds09:11:39

The '<,'> would be put automatically when you hit : in visual mode

nbardiuk10:11:21

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 *)

5
tomd11:11:09

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 @U076FM90B’s suggestion, which I also like.

practicalli-johnny14:11:33

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.

tomd14:11:20

/ 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]

Martynas Maciulevičius14:11:44

You can also escape / by typing \/ 🤷

practicalli-johnny14:11:34

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..

practicalli-johnny14:11:27

Closest I have come is as @U7ERLH6JX 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.

tomd14:11:43

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+=/

Proctor15:11:05

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/

Proctor15:11:23

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

nate16:11:47

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

nate16:11:16

Setting set inccommand=split will pop up a window at the bottom showing matches and updating as you type the replacement.

1
1
walterl20:11:04

1. v<movement> - select the text I'd like to replace 2. * - search for selection (with the "advanced mappings" that @U0510902N 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.

walterl20:11:16

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.

walterl20:11:35

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//.