Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I expand a range into a list in vimscript?

Tags:

vim

vi

I'd like to automatically take a visually selected block of text, such as 51-100, and have it expanded into 51,52,53,...,99,100.

Is there an easy way to do this in vimscript?

like image 766
merlin2011 Avatar asked Jan 25 '12 03:01

merlin2011


1 Answers

Let me propose the following implementation.

vnoremap <silent> <leader># :<c-u>call ExpandRange()<cr>
function! ExpandRange()
    norm! gvy
    let n = matchlist(@", '\(\d\+\)\s*-\s*\(\d\+\)')[1:2]
    if len(n) != 2 || +n[0] > +n[1]
        return
    end
    exe 'norm! gvc' . join(range(n[0], n[1]), ',')
endfunction

If it is guaranteed by the range notation that there is no whitespace around numbers, the second statement of ExpandRange() can be simplified by using the split() function,

    let n = split(@", '-')

Note that the text denoting a range is put into the unnamed register. If it is preferable to leave the register untouched, modify ExpandRange() to save its state beforehand and restore it afterwards.

function! ExpandRange()
    let [qr, qt] = [getreg('"'), getregtype('"')]
    norm! gvy
    let n = matchlist(@", '\(\d\+\)\s*-\s*\(\d\+\)')[1:2]
    call setreg('"', qr, qt)
    if len(n) != 2 || +n[0] > +n[1]
        return
    end
    exe 'norm! gv"_c' . join(range(n[0], n[1]), ',')
endfunction
like image 198
ib. Avatar answered Oct 02 '22 12:10

ib.