0

Is it possible to delete the current visual block selection and all other occurences from the current buffer?

  • 2
    It is possible, but can be tricky (and it certainly involves vimscript). One would have to transform the block selection into a regular expression that takes into account each row of the selection, so that you would have to have each row matched, in turn, in consecutive lines; what might be tricky is the requirement of strict column alignment matching, if that too is desired. – VanLaser Nov 13 '16 at 11:44
1

It's probably not completely reliable, but you could try this:

xno <silent> mbc :<C-U>call <SID>move_blocks(1)<CR>
xno <silent> mbd :<C-U>call <SID>move_blocks(0)<CR>

fu! s:move_blocks(clean_them_only) abort
    let view  = winsaveview()
    let block = s:get_its_text()

    call cursor(1,1)
    while s:you_find_a(block)
        let orig_pos = getpos('.')
        call s:remove_it(block, a:clean_them_only)
        call setpos('.', orig_pos)
    endwhile

    if !a:clean_them_only
        sil! exe "keepj keepp %s/\<C-A>//g"
    endif

    call winrestview(view)
endfu

fu! s:get_its_text() abort

    let unnamed_reg_contents = getreg('"')
    let unnamed_reg_type     = getregtype('"')

    sil norm! gvy
    let block = split(@", "\n")

    call setreg('"', unnamed_reg_contents, unnamed_reg_type)

    return block
endfu

fu! s:you_find_a(block) abort
    let block                = a:block
    let pattern_first_line   = '\V'.escape(block[0],'\')
    let found_its_first_line = search(pattern_first_line, 'cW')

    while found_its_first_line

        let orig_pos      = getpos('.')
        let idx_line      = line('.')+1
        let start_col     = col('.')
        let rest_of_block = block[1:]

        if !s:is_complete(rest_of_block, idx_line, start_col)
            let found_its_first_line = search(pattern_first_line, 'W')
            continue
        endif

        call setpos('.', orig_pos)
        return 1
    endwhile

    return 0
endfu

fu! s:is_complete(rest_of_block, idx_line, start_col) abort
    let orig_pos          = getpos('.')
    let idx_line          = a:idx_line
    let start_col         = a:start_col
    let rest_of_block     = a:rest_of_block
    let rest_is_there_too = 1

    for text in rest_of_block
        let pattern_subsequent_line = '\V\%'.idx_line.'l\%'.start_col.'c'.
                                    \ escape(text,'\')

        if !search(pattern_subsequent_line, 'W')
            let rest_is_there_too = 0
            break
        endif

        let idx_line += 1
    endfor

    call setpos('.', orig_pos)
    return rest_is_there_too
endfu

fu! s:remove_it(block, clean_them_only) abort
    let block     = a:block
    let idx_line  = line('.')
    let start_col = col('.')

    for text in block
        let pattern_block_line = '\V\%'.idx_line.'l\%'.start_col.'c'.escape(text,'\')
        let replacement        = '\=repeat("'.
                                            \ (a:clean_them_only?' ':"\<C-A>").
                                            \ '",'.len(text).')'

        sil! exe 'keepj keepp '.idx_line.
                 \ 's/'.pattern_block_line.'/'.replacement.'/'

        let idx_line += 1
    endfor
endfu

It installs 2 mappings in visual mode triggered by the mbc and mbd key sequences. To use it, you would have to visually select the block you want to remove and hit mbc to replace all occurrences with spaces, or hit mbd to remove them entirely.

I didn't test it very long, and only on this sample text:

debitis  Elit  sit distinctio  saepe debitis  voluptatibus eveniet.  Pariatur accusantium
Eius     cumque hic eligendi magnam? Eius     ducimus  maxime fugiat sed eum. Earum at cumque
quisquam at quia nulla Nihil porro   quisquam impedit est?

Elit  sit distinctio  saepe debitis  voluptatibus eveniet.  Pariatur accusantium
cumque hic eligendi magnam? Eius     ducimus  maxime fugiat sed eum. Earum at cumque
at quia nulla Nihil porro   quisquam impedit est?

Elit  sit distinctio  saepe debitis  voluptatibus eveniet.  Pariatur accusantium
cumque hic eligendi magnam?          ducimus  maxime fugiat debitis sed eum. Earum at cumque
debitis  at quia nulla Nihi quisquam impedit est?           Eius    
Eius                                                        quisquam
quisquam Elit  sit distinctio  saepe  debitis  voluptatibus eveniet.  Pariatur accusantium
cumque hic eligendi debitis   magnam? Eius     ducimus  maxime fugiat sed eum. Earum at cumque
at quia nulla Nihil Eius      porro   quisquam impedit est?
                    quisquam
Elit  sit distinctio  saepe debitis  voluptatibus eveniet.  Pariatur accusantium     debitis 
cumque hic eligendi magnam? Eius     ducimus  maxime fugiat sed eum. Earum at cumque Eius    
at quia nulla Nihil porro   quisquam impedit est?                                    quisquam

I tried to remove this block:

debitis 
Eius    
quisquam

It seemed to work: enter image description here

But there may be cases where it won't, I don't know.

  • Not sure if I'm doing wrong but I don't get it working. Also, e.g. vic does nothing for me, at least not visible :D – criztovyl Apr 7 '17 at 17:19
0

You could do something like

visual around the block you want to delete, hit y to yank, and then do :%s/<C-R>"// to replace all instances of it with empty text.

  • Have you tried this? If you did, you would see that it won't work. – Karl Yngve Lervåg Nov 13 '16 at 6:25
  • Yes, I did. It worked on my install. – Wolfie Nov 14 '16 at 17:34
  • 2
    Ok. Well, If you select a visual block with <c-v> that spans multiple rows, then your suggestion will not work. – Karl Yngve Lervåg Nov 14 '16 at 21:14

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.