0

I'm new to Vim and cursed coming from atom multi-cursor operation.

I can't seem an easy way to change the variable names. Say I needed to replace bad_var only in the function - How would you do it?

bad_var = 2 # must not be changed def best_function_in_the_universe(bad_var): x = bad_var + 1 print("hello") return bad_var 
3
  • I've been trying the "autoc-compelte cgn" example here, and it looks like it's what I need. However, I don't follow the guide. Could you someone explain it in depth for a total beginner? medium.com/@schtoeffel/… Commented Mar 13, 2023 at 11:16
  • Could you give use more information about what you mention as "autoc-compelte cgn"? Maybe some additional description or link may help. Commented Mar 13, 2023 at 13:31
  • vi.stackexchange.com/q/27812/10604 Commented Mar 13, 2023 at 17:29

3 Answers 3

3

On cgn

There are two concepts at play here: the change operator c and the motion or text-object it accepts. You may know that cw changes the text covered by the motion w, so roughly "change to the next word." (Change in this context means "delete and start Insert mode"; such a change is ended when you exit Insert mode with Escape.)

The argument to c in this case is the text-object gn, which is a rather special object that selects the next occurrence of the current search. So if you've searched /foo, cgn will jump to the next foo, delete it, and leave you in Insert mode. This is kind of like how n jumps to the match.

This is particularly handy for refactoring in a single file, because * searches the word under the cursor. So *cgnbar<Esc> when the cursor is on foo changes the next occurrence of foo to bar. And when you repeat the change with ., the next occurrence is changed in the same way, and so on.

Other Approaches

One draw back is that the search is buffer-specific, so if you're changing an exported name *cgn is slightly less convenient. You'll need to load the files that contain that name (say, in to the arg list or buffer list), and use :argdo normal! 9999. or some such hackery.

Instead, you might want to try :grep foo and :cdo substitute/foo/bar or similar (alternatives include :vimgrep, :cfdo with :%substitute, the /g or /c flags, or even just :cnext with . as appropriate).

Having unit tests or a compiler available to check the changes helps with the feedback loop, especially if you've already got :make working. This makes yet another approach: make the initial change to the export, then :make and use the quickfix list as before to correct the errors. Repeat until finished.

2

Without any plugin and using just the power of vim itself, I would do a visual selection of the lines that should be affected and replace any occurrence of a pattern with what I want to have.

In your example, I'd place the cursor on the line with def best_function_in_the_universe, do V} to visually select everything until the next blank line. Then use the :help substitute command to replace :'<,'>s/bad_var/good_var/ (vim will fill in the cryptic stuff between ":" and "s", it means to operate on the selected lines only).

Next steps:

If bad_var were to be present as part of another word, e.g. not_a_bad_var and I would not want to replace it, I'd add word boundaries like so :'<,'>s/\<bad_var\>/good_var/.

You might also be interested in replacing more than one match per line by appending g. Or confirm every replacement by appending c. Command would look like this: :'<,'>s/\<bad_var\>/good_var/gc.

1

The answer of @Friedrich is the 'right' (Vim) one.

But here are three alternative that could be worth considering.

Vim-Visual-Multi

But coming from Atom you could be interested by the Vim-Visual-Multi plugin that offers support for multiple cursor.

LSP Rename

An alternative for your use case is to use the support of the language server. Using the Coc plugin with the coc-pyright extension (:CocInstall pyright) you could use the rename functionality (rn in normal mode) to rename a variable.

LSP Select

If you have the Coc plugin installed the vaf keystrokes let you select the entire method in one go before you apply a substitution ('<,'>s/\C\<bad_var\>/good_var/gc)

1
  • Thank you for the praise. By the way, I've been in the business long enough to accept that whatever works is the "right" solution :) Commented Mar 15, 2023 at 7:17

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.