I have 50 lines of code

private const CODE = 0;
private const DESC = 1;
// ... 
private const TRIM = 19; // instead of 24
private const SMURF = 35; // instead of 25
private const DOG = 31; // instead of 26
// ... 
private const CAT = 49;
private const AMOUNT = 50;

As you can see, numbers are not sorted right. I'd like to rewrite them so that I get the following instead:

private const CODE = 0;
private const DESC = 1;
// ... 
private const TRIM = 24;
private const SMURF = 25;
private const DOG = 26;
// ... 
private const CAT = 49;
private const AMOUNT = 50;
  • @klaus thx, done – smarber Apr 15 '19 at 6:45
  • @klaus yeah that's I meant :D – smarber Apr 15 '19 at 6:56
  • I and several others have added answers, check them out. But if you're trying to set up a set of constants in C, I would advise using enumerations to do that. Just do, enum { CODE, DESC, .... , TRIM, SMURF, DOG, ... , CAT, AMOUNT } This is AFAIK the preferred way of setting up a set of related constants. I am a little hazy on the Java aspect though. But I can vaguely remember Java also having enums to do the same. You need to check out stackoverflow for this. Both for Java and C/CPP. – klaus Apr 15 '19 at 7:34
  • 1
    @klaus most of the C-like langs have enums (java, c#) – D. Ben Knoble Apr 15 '19 at 13:10
  • OP, is it acceptable to rearrange the lines instead of changing the number? – D. Ben Knoble Apr 15 '19 at 13:10

Assume there has no negative numbers.

let @"=-1 | global /\v\w+\s*\=\s*\d+\s*;/ exec("normal! f;bviwp\<c-a>yiw")
  • let @"=-1 set register " to -1
  • global /\v\w+\s*\=\s*\d+\s*;/ find all line that need to be changed
    • \w+\s*\=\s* match "CODE = " in "CODE = 0;"
    • \d+\s*; match "0;" in "CODE = 0;"
  • exec("normal! f;bviwp\<c-a>yiw") execute a tiny script on each matched line:
    • f;b locate cursor at number before ;
    • viwp replace current number with register "
    • \<c-a> increase current number
    • yiw set register " to current number

What you can do is the following.

Prepare: Execute :set virtualedit=block. This allows visual block selection (<Ctrl-V>) beyond the end of line.

  1. Visually select the lines and execute :'<,'>s/=.*$// (this also deletes all trailing comments!)
  2. Go to the end of the first line and hit <C-V> and move down over all 50 lines and to the right, so the right side of the visual box is behind all variable names.
  3. Enter A= 0;<esc>, to append the text = 0; to all lines.
  4. Go to the second line and move to the 0.
  5. Hit <C-V> again and move down to the last line. You have now one column visually selected.
  6. Hit g<Ctrl-A>. This will replace the 0s with a increasing sequence of numbers.
  • What if the variable names are so long that you can't use visual-block-mode properly. And if the variable names contain integers then g<Ctrl-A> would also edit the variable names. – klaus Apr 15 '19 at 7:29
  • @klaus 1. With virtualedit=block you can do blockselect beyond the end of line. So the A = 0;<esc> will insert text beyond all variable names. 2. When using g<Ctrl-A> you only have the column with the 0s selected (steps 4 to 6). – Ralf Apr 15 '19 at 7:42
  1. At first make every digit zero:

    :%s/\vprivate const .* = \zs\d*\ze;/0/g
  2. Then goto the first line with gg

  3. Then start recording. Just press q twice, i.e. qq. The first q will start the recording and the second q will define in which register (:reg q) the recording will be stored.
  4. Goto the digit before ; by pressing t;
  5. Yank the integer with yiw
  6. Go one line below, goto before ; and put the integer in place of the zero there and increment. The whole process should be done by j0t;viw"0p<Ctrl-A>
  7. Stop recording by pressing q once.
  8. Perform the task from 4 to 7 with 50@q
  • 1
    1. make them zero, 2. visually select lines needed, 3. g<C-a> – Maxim Kim Apr 15 '19 at 7:16
  • 1
    I didn't know you can use :h v_g_CTRL-A with visual lines. I knew it was applicable only for visual-block-mode! Thanks. – klaus Apr 15 '19 at 7:20
  • That's true, but I doubt his/her constants have any numbers in names. In that case try to select blockwise excluding those names :) – Maxim Kim Apr 15 '19 at 7:27
  • Thanks, never know :h v_g_CTRL-A – dedowsdi Apr 15 '19 at 7:29
  • @MaximKim, I didn't use g<C-a> even though I knew I can use it in visual-block-mode, because there is a chance that some variable names are just too long. In that case, you can't use visual-block-mode to visually select all the integers. It's unlikely that's the case though. By the way, I think OP should use enumerations to achieve what s/he is trying to do, shouldn't s/he? – klaus Apr 15 '19 at 7:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.