joefromct
joefromct

Reputation: 1556

increment numbers in visual vertical block selection in emacs evil

I have been using https://github.com/vim-scripts/increment.vim--Avadhanula for vim for years.

How could i leverage functionality similarly in emacs?

The idea be something like this:

given a list such as the following:

the_array[0] 
the_array[0] 
the_array[0] 

I want to be able to select all the zeros, issue a command, and have the text replaced with this:

the_array[0] 
the_array[1] 
the_array[2] 

I am using emacs evil-mode if it matters, hoping to do the equivelent of a block select for the region of numbers i want to increment.

Thanks,

Upvotes: 4

Views: 2752

Answers (2)

Gordon Gustafson
Gordon Gustafson

Reputation: 41209

Say you start with this text in your buffer:

the_array[0]
the_array[0]
the_array[0]

Move the cursor to the first 0 and use C-v 2 j d to delete all the zeros. C-v } F 0 d will work for an arbitrary number of lines as long as the last the_array[0] line is at the end of a paragraph, but note that it requires (setq evil-cross-lines t) in your config.

Regardless of how you delete the 0's, you should now have this in your buffer:

the_array[]
the_array[]
the_array[]

Select all the ending ]'s in the same way you selected the 0's. Now press C-u C-x r N 0 <Enter> <Backspace> <Enter>. C-x r N runs rectangle-number-lines, which prompts for a starting number and format string when invoked with a prefix argument (C-u). We specify that it should start and 0 and insert only the numbers (<Backspace> removes a trailing space in this case).

Your buffer should now contain this:

the_array[1]
the_array[2]
the_array[3]

Upvotes: 6

Steve Vinoski
Steve Vinoski

Reputation: 20014

One approach is to set a region on the numbers you want to increment, then narrow to that region (typically bound to C-x n n), and then use replace-regexp with some elisp to generate the replacement text. Something like the following will work, where the text shown in keyboard font is what you enter, the text shown in code font is what emacs prompts you with, and you're expected to hit enter after each line:

M-x replace-regexp
Replace regexp: [0-9]+
Replace regexp [0-9]+ with: \,(1- (line-number-at-pos (point)))

The \,( ... ) construct used for the replacement is elisp that replace-regexp executes to generate the replacement text. In this case, the elisp gets the line number of each match to be replaced, subtracts 1 from it (since our narrowed region starts with line 1), and returns the resulting value as the replacement text. If you want the array indices to start with something other than 0, modify the math accordingly.

Upvotes: 1

Related Questions