1

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;
5
  • @klaus thx, done
    – smarber
    Apr 15, 2019 at 6:45
  • @klaus yeah that's I meant :D
    – smarber
    Apr 15, 2019 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.
    – 3N4N
    Apr 15, 2019 at 7:34
  • 1
    @klaus most of the C-like langs have enums (java, c#)
    – D. Ben Knoble
    Apr 15, 2019 at 13:10
  • OP, is it acceptable to rearrange the lines instead of changing the number?
    – D. Ben Knoble
    Apr 15, 2019 at 13:10

3 Answers 3

2

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
2

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.
2
  • 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.
    – 3N4N
    Apr 15, 2019 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, 2019 at 7:42
2
  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
6
  • 1
    1. make them zero, 2. visually select lines needed, 3. g<C-a>
    – Maxim Kim
    Apr 15, 2019 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.
    – 3N4N
    Apr 15, 2019 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, 2019 at 7:27
  • Thanks, never know :h v_g_CTRL-A
    – dedowsdi
    Apr 15, 2019 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?
    – 3N4N
    Apr 15, 2019 at 7:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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