0

Let's say I have some code:

divide(int x) {
int a = 0;
a += x;
}

subtract(int x) {
int b = 0;
b += x;
}

multiply(int x) {
int c = 0;
c += x;
}

I'm using VIM and I'd like to be able to search and replace each instance of += with {'/=', '-=', '*='} in that order, using the vim command line. I'd like to use :%s/+=/..., but I'm not sure how.

I also thought about using python in vim like this, but I would prefer a simpler solution entirely in VIM, if possible.

Community
  • 1
  • 1
luca590
  • 460
  • 2
  • 5
  • 25

2 Answers2

2

If all of your += occur on different lines:

:let c=0 | g/\m+=/ s!\m+=!\=['/=', '-=', '*='][c%3]! | let c+=1

If there might be more than one += on the same line:

:fu! Cycle() | let c+=1 | return ['/=', '-=', '*='][c%3] | endf
:let c=-1 | %s/\m+=/\=Cycle()/g

References:

  • :h :global
  • :h s/\=
Sato Katsura
  • 3,066
  • 15
  • 21
1

Here is a shorter variant of @SatoKatsura's answer. It first defines a List of replacements, then uses a :help sub-replace-expression to remove the first element of the list.

:let replacements = ['/=', '-=', '*='] | %s#+=#\=remove(replacements, 0)#

If there are more than 3 replacements, and you want repeating of the replacements, use this:

:let replacements = ['/=', '-=', '*='] | %s#+=#\=add(replacements, remove(replacements, 0))[-1]#
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • Ok, so then why does this work exactly? I understand everything up to the first # after %s. – luca590 Oct 15 '16 at 16:49
  • 1
    `remove()` returns the element that is removed from the pre-populated list. So, each substitution removes (and uses) one element from the list. The second variant prevents that the list gets empty by re-adding each element again. – Ingo Karkat Oct 17 '16 at 07:44