Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim macro: Incrementing numbers on non-consecutive lines

Tags:

vim

yaml

macros

I'm working with a YAML file that has an integer as ID which appears every 4-6 lines. I'm looking to add a record in the middle of this file (for readability) that keeps the sequential numbering intact.

File format below. Any ideas?

- id: 1
  type: string
  option: diff_string
  other: alt_string   // note: 'other' option does not appear for all records

- id: 2
  type: string
  option: diff_string

//new record would go here as id: 3, increasing id: # of all following records by 1

- id: 3
  type: string
  option: diff_string
  other: alt_string
like image 696
Lumen Avatar asked Jan 18 '12 16:01

Lumen


3 Answers

I believe you can achieve what you want with setting a counter (here: variable g:I) to 1:

let g:I=1

And then execute a substitution on each line that matches ^- id: \d\+$:

%g/^- id: \d\+$/ s/\d\+/\=g:I/|let g:I=g:I+1

The substition uses the \= thingy (see :help sub-replace-expression) to substitue \d\+ with the actual value of g:I. After the substition, the counter is incremented (let g:I=g:I+1).

With the g/^- id: \d\+$/ you ensure that the substition is only performed on lines matching ^- id: \d\+.

Edit If you want to have a map for it, you can place the following snippet into your .vimrc:

nnoremap resync :let g:I=1<CR>:%g/^- id: \d\+$/ s/\d\+/\=g:I/\|let g:I=g:I+1<CR>

which allows to resync your ids by typing resync in normal mode.

Note the escaping of the | with the \ and the use of <CR> where you would press enter.

like image 197
René Nyffenegger Avatar answered Sep 28 '22 04:09

René Nyffenegger


in order to increment all subsequent ids from cursor line + 1:

:.+1,$g/^- id: \d\+$/exec 'normal! 0' . nr2char(1)

(nr2char(1) is like keying CTRL-A in).

You can also do:

:.+1,$g/^- id: \d\+$/normal! 0^A

Where you enter ^A typing CTRL-V then CTRL-A. Note that I prefer the first version: you can copy-paste it around, there is no literal control character in the code.

Detail:

  • .+1,$ is the range from next line till end of file. :help range.
  • :g command operates on all lines obeying to a pattern. The opposite is :v. :help :g
  • /^- id: \d\+$/ matches - id: at the start of a line, followed by 1 or more digits and then end of line (:help pattern)
  • :normal! plays normal commands: 0 to go to start of line, CTRL-A to increment next number.

If you want a mapping:

nnoremap <F1> :.+1,$g/^- id: \d\+$/exec 'normal! 0' . nr2char(1)<enter>

Put that in your vimrc, and now enjoy pressing F1 in normal mode, and watch all ids below cursor line incrementing.

like image 45
Benoit Avatar answered Sep 28 '22 04:09

Benoit


I would use the following short and straightforward substitution command.

:,$s/^- id: \zs\d\+/\=submatch(0)+1/
like image 29
ib. Avatar answered Sep 28 '22 03:09

ib.