News for hackers. Stuff that matters.
Re:A Vim Guide for Advanced Users by OskarS on Saturday February 27, 2021 @10:21AM (#26285372)
The article mentions ”gn” in passing, but it doesn’t give it enough credit: this is an enormously useful motion, almost more useful on its own than the rest of the article.

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!

Re:A Vim Guide for Advanced Users by orlp on Saturday February 27, 2021 @10:48AM (#26285551)
This has one huge shortcoming: when the next match is off-screen, pressing . jumps immediately to the next match and replaces it, before you had the opportunity to review whether you want that.

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

Re:A Vim Guide for Advanced Users by bxparks on Saturday February 27, 2021 @12:36PM (#26286450)
That's a good point about previewing. So instead of "cgn", it looks like you can do "gns", which highlights the match, then enters into substitution mode, and you type the replacement, then hit <ESC>. Then you can hit "n." "n." "n." repeatedly, where the "n" goes to the next match so that you can preview, and the "." applies the replacement. Not quite as efficient as a single ".", but the "n." sequence is a familiar one.
Re:A Vim Guide for Advanced Users by ThrustVectoring on Saturday February 27, 2021 @04:28PM (#26288336)
IMO the "correct" way to handle this is with vanilla vim's built-in macros. Find the next match, record a macro making the edit you want, then find the next match and finish recording the macro. The macro starts with the cursor over the match you want, the edit can be more complex than a simple replacement, and skipping is simply a matter of pressing `n` instead of `@@`.

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.

Re:A Vim Guide for Advanced Users by tasty_freeze on Saturday February 27, 2021 @11:57AM (#26286103)
I'm not sure exactly what your plugin does, but are you aware of the "c" flag to substitute, eg

:%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).

Re:A Vim Guide for Advanced Users by nightcracker on Saturday February 27, 2021 @12:06PM (#26286177)
Yes, I am aware, but it's not nearly as flexible and quick. It doesn't allow me to in the meantime move my cursor around, switch buffers, undo, open/close a fold, etc. It takes complete control of your workflow to temporarily put you in some special 'search/replace mode' in a very non-Vimlike manner. My plugin has a simple operation (if cursor is on a match, replace, regardless jump to next match) that gets repeated with ., combined with nN and u and you have complete control while also rapidly doing search/replace.

And you would still need some nice mappings to substitute the word/selection underneath the cursor with :%s///gc.

Re:A Vim Guide for Advanced Users by chrismorgan on Saturday February 27, 2021 @03:06PM (#26287693)
If using the [c] flag and you want to interrupt it, a convenient way of continuing where you left off (and not touching previous lines, which may have new matches, depending on the nature of the replacement) may be :.,$&&<Enter>, which means “operating on the range current line (.) to end of file ($), execute the last substitution (&) with the same flags as last time (&)”.

(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 '>).)

Re:A Vim Guide for Advanced Users by coliveira on Saturday February 27, 2021 @12:36PM (#26286440)
You can just type n, followed by ., to view the next match before changing it.
Re:A Vim Guide for Advanced Users by nightcracker on Saturday February 27, 2021 @01:23PM (#26286875)
I used to do that but my brain messes up "n." for replace, "n" for skip, whereas "." for replace, "n" for skip is really easy.
Re:A Vim Guide for Advanced Users by tvrg on Saturday February 27, 2021 @12:37PM (#26286460)
Is this much different from searching with * or :s for a match and use something like "ciwReplacement<Esc>", then "n." or just "n" if I don't want to change the match? I can imagine that the plugin works in more complicated cases, but most of the time I probably just want to replace a word with ciw or ciW.
Re:A Vim Guide for Advanced Users by nightcracker on Saturday February 27, 2021 @01:19PM (#26286839)
Well, assuming you already have a plugin or mapping that makes * search your visual selection, it's similar.

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.

Re:A Vim Guide for Advanced Users by ABitMoreDepth on Sunday February 28, 2021 @06:19AM (#26292551)
Can't you just press n to jump to the next match without substituting, then if you're happy to continue, press . and it'll replace it? I use n and p with cgn all the time.

Works a treat!

Re:A Vim Guide for Advanced Users by thomastjeffery on Saturday February 27, 2021 @04:44PM (#26288450)
But if you're not sure you wanted it, you can just press u to undo and n to skip.

Since Vim keeps an undo tree, you are guaranteed not to lose anything anyway.

Re:A Vim Guide for Advanced Users by lucb1e on Saturday February 27, 2021 @03:18PM (#26287781)
I used to do n.n.n.n. to do the same (i.e. /search something, then do the replacing with something like cw or 3s or ct' or whatever you want, and then hit n for next result and . to repeat the change). Using cgn is less flexible and you need to learn another thing (you know about n and . already by the time you get to cgn), and maybe it's just me but hitting n. repeatedly is practically equally fast as just hitting the dot.

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.

Re:A Vim Guide for Advanced Users by Skunkleton on Saturday February 27, 2021 @03:28PM (#26287865)
This might be the right audience for this little vimrc tidbit:

    "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.
Re:A Vim Guide for Advanced Users by lucb1e on Saturday February 27, 2021 @03:43PM (#26287963)
> like * but leaves your cursor where it is

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!

Re:A Vim Guide for Advanced Users by revscat on Saturday February 27, 2021 @04:19PM (#26288278)
This is useful enough that I wonder why you chose not to just map it to *. Is there a reason you did not?
Re:A Vim Guide for Advanced Users by Skunkleton on Saturday February 27, 2021 @07:18PM (#26289471)
Because <space> is even easier to hit :)

Edit: also because I try and keep my keybinds as close to default as I can, and <space> is oddly underused.

Re:A Vim Guide for Advanced Users by CGamesPlay on Saturday February 27, 2021 @11:32PM (#26290691)
> But perhaps it's a bug in Vim since it works when I run * on the lowercase variant.

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>
Re:A Vim Guide for Advanced Users by RMPR on Saturday February 27, 2021 @10:36AM (#26285477)
Awesome, that's definitely something I'll add to my bag of tricks. But

> 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

Re:A Vim Guide for Advanced Users by thesteamboat on Saturday February 27, 2021 @10:51AM (#26285579)
I too wish to add this to my repertoire. I don't think it will replace :s, but occasionally I find myself copying a line to use as a template. When I go to change each line I'm changing a particular part to different things. Assuming I remember, this trick seems like a good approach.
Re:A Vim Guide for Advanced Users by asicsp on Saturday February 27, 2021 @10:32AM (#26285449)
Ooh, sounds interesting. I'll have to look up the details. I currently do this after a search with / and regex (if it is a bit complicated)

    :%s//replace/gc
Re:A Vim Guide for Advanced Users by stjohnswarts on Saturday February 27, 2021 @01:56PM (#26287147)
This is what I do, I use regex's so often it's easier for me to read this even if it's a little bit more typing
Re:A Vim Guide for Advanced Users by edanm on Sunday February 28, 2021 @02:02AM (#26291260)
Yes, and here's my favorite vim trick I ever invented - you can do use this after changing a word.

What 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.
Re:A Vim Guide for Advanced Users by aaimtts on Saturday February 27, 2021 @12:35PM (#26286437)
This is very useful, thank you! How would you go about pasting the "replace" part though?

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?

Re:A Vim Guide for Advanced Users by tvrg on Saturday February 27, 2021 @12:44PM (#26286527)
You can slightly simplify your workflow using the yank register 0.

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.

Re:A Vim Guide for Advanced Users by petepete on Saturday February 27, 2021 @01:23PM (#26286874)
So I've been using vim for nearly twenty years and didn't know this. I also never touch visual mode make any advanced use of buffers or marks. I feel like some kind of caveman now.
Re:A Vim Guide for Advanced Users by johncoltrane on Saturday February 27, 2021 @02:52PM (#26287597)
Maybe you will like these little gems I came up with back when the gn patch was merged:

nnoremap <key> *``cgn

nnoremap <key> #``cgN

Hit <key> to change the current word and ... to repeat on the next occurrences.

Re:A Vim Guide for Advanced Users by mushishi on Saturday February 27, 2021 @11:20AM (#26285792)
Just tried this. Note for others: between 2. and 3. you need to get back to normal mode (which is kinda obvious but...)

Thank you for the tip.

Re:A Vim Guide for Advanced Users by sanderjd on Saturday February 27, 2021 @05:37PM (#26288811)
That does sound useful, but I do this with `:s/foo/bar/gc`, then I press `y` each time, which is pretty similar to pressing `.` each time in your example. I do like that the `cgn` approach works better for something you searched for without knowing a priori that you were going to do a replacement on it.
Re:A Vim Guide for Advanced Users by u801e on Saturday February 27, 2021 @07:05PM (#26289368)
I've done this by setting the / register with * as you mentioned, but I still use the :s command, type / and then use the ctrl-r / key combination to paste the contents of the / register, then type the second / and then the replacement.

The g and z set of commands are pretty useful in vim.

Re:A Vim Guide for Advanced Users by erostrate on Saturday February 27, 2021 @11:56AM (#26286086)
Thank you so much! I've been using Vim for 5 years and I always thought :s was one of the major pain points.
Re:A Vim Guide for Advanced Users by hpfr on Saturday February 27, 2021 @04:12PM (#26288224)
The author does mention this in an in-depth article on search: https://thevaluable.dev/vim-search-find-replace/

It's pretty comprehensive. Personally I'd just install Doom Emacs though :)

Re:A Vim Guide for Advanced Users by simias on Saturday February 27, 2021 @11:33AM (#26285891)
Oh man, I knew there had to be a way to do that but I couldn't find it, so I always resorted to counting the number of characters in the match and then use cl<num> to replace it if there was no convenient motion like some kind of barbarian.
Re:A Vim Guide for Advanced Users by bobbyi_settv on Saturday February 27, 2021 @11:48AM (#26286010)
The non-barbarian way to avoid counting characters when there's no convenient motion is visual mode. Hit v, then hit l until you've highlighted the part you want to change, then hit c to start changing it.
Re:A Vim Guide for Advanced Users by simias on Saturday February 27, 2021 @01:37PM (#26286989)
Oh I never thought about that either. Thank you.
Re:A Vim Guide for Advanced Users by bobbyi_settv on Saturday February 27, 2021 @02:32PM (#26287464)
I rarely actually do it because f and t motions, possibly with a number, can usually handle these cases. For example, c3tA to change up to but not including the third capital A after the current position
Re:A Vim Guide for Advanced Users by tasuki on Saturday February 27, 2021 @05:43PM (#26288854)
If it's more than one 'A' I'd use visual mode. I'm always impressed people can accurately count up to like three ;)
Re:A Vim Guide for Advanced Users by gnubison on Saturday February 27, 2021 @10:02PM (#26290292)
c<num>l is equivalent to <num>s (unless you've installed a plugin that binds s to something else).
Re:A Vim Guide for Advanced Users by nandkeypull on Sunday February 28, 2021 @03:23PM (#26296707)
Nice, it works in evil-mode on emacs as well! Although for emacs I would just use query-replace, which does the same thing with y/n confirmation, and it can also be run on just a selected region if desired.
Re:A Vim Guide for Advanced Users by thanato0s on Saturday February 27, 2021 @11:28AM (#26285839)
Yeah I know the trick and I explain it a bit more in another article on my blog.

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

Re:A Vim Guide for Advanced Users by typon on Saturday February 27, 2021 @11:31AM (#26285880)
I'm paranoid and I like seeing exactly what I'm replacing. In that case I still use :s but I always end it with :s/foo/bar/gc. Although I do see the appeal of cgn for simple replacements.
Re:A Vim Guide for Advanced Users by thanato0s on Saturday February 27, 2021 @12:02PM (#26286150)
If you use Neovim, you can set the option inccommand:

set inccommand=nosplit

It will display the substitute directly in the buffer.

Re:A Vim Guide for Advanced Users by trigoman on Saturday February 27, 2021 @02:14PM (#26287305)
I was looking on how do this exact thing! Thank you! In IntelliJ I press Alt+j to add to selection then I can edit all matches. You just described how to do the same effect in Vim
Re:A Vim Guide for Advanced Users by usmannk on Saturday February 27, 2021 @10:31AM (#26285439)
Why is this preferable to :%s?
Re:A Vim Guide for Advanced Users by simias on Saturday February 27, 2021 @11:35AM (#26285913)
It composes better if you were searching for something and then want to replace it IMO. You basically just have to remember the search syntax and then you can reuse it for replacing.

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.

Re:A Vim Guide for Advanced Users by kadonoishi on Saturday February 27, 2021 @02:20PM (#26287361)
It allows you to use a full Turing machine rather than restricting yourself to a Finite State Machine.
Re:A Vim Guide for Advanced Users by RMPR on Saturday February 27, 2021 @10:39AM (#26285499)
I find it more intuitive, and for a small number of iterations it's definitely faster.
Re:A Vim Guide for Advanced Users by throwoutttt on Saturday February 27, 2021 @10:31AM (#26285435)
As someone who uses this regularly, it's still not as convenient as multi cursors that most modern ides give you.

There's a vim extension for multiple cursors but it's a little buggy.

Re:A Vim Guide for Advanced Users by OskarS on Saturday February 27, 2021 @10:36AM (#26285475)
I dunno, I’ve also used both, and I keep coming back to the Vim/gn way of doing it, I just like it more. I see how people can feel otherwise, though.
Re:A Vim Guide for Advanced Users by boogies on Saturday February 27, 2021 @11:19AM (#26285788)
Yeah, not everyone is the same, but there are definitely people interested in multi-cursor modal editors, enough to build their own, eg. vis⁰ — a light, fast, and simple text editor with a pretty standard vim normal mode but sam’s structural regex command language¹ for creating and procedurally editing selections in command mode², and kakoune³ — known for switching vi’s word order from verb noun to noun verb, so typical normal mode commands work by first creating one or more selections with motions (no need to press v), and only then operating on them. And of course Emacs has multi-selection modes and AFAIK they’re compatible with evil.

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

Re:A Vim Guide for Advanced Users by lucb1e on Saturday February 27, 2021 @03:28PM (#26287858)
As someone who never used a multi-cursor IDE (I've seen other use it but not in a convincing way): what's something that you use this for that you don't think vim can do?

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