14

I often use visual block then inserting on multiple lines when for example commenting out a lot of code. This is great for inserting text in the same position on multiple lines but I can't figure out how to delete this text later using visual block mode, Backspace, Del and d all don't work. I am using MacVim.

henry.oswald
  • 5,304
  • 13
  • 51
  • 73
  • 1
    Although the accepted answer is correct I just want to point out an important command you can use in combination with it to make it quite easier to use. The dot command! Enter block visual mode, select multiple lines, hit x, now press `.` as many times as needed. – aderchox Aug 03 '20 at 17:16

3 Answers3

24

You're looking for x:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh

Then visual-block-select, x:

root:/root:/bin/bash
daeaemon:/usr/sbin:/bin/sh
bin/bin:/bin/sh
sys/dev:/bin/sh

I use this frequently, for exactly the same reason -- commenting and uncommenting large blocks of code.

sarnold
  • 102,305
  • 22
  • 181
  • 238
6

This isn't directly answering the question (sarnold has already done so), but I would suggest there are more efficient ways of (un-)commenting code blocks. I have a CommentToggle function which either comments or uncomments the current line, depending on whether or not it begins with the "comchar".

function! CommentToggle(comchar)
    let firstchar = matchstr(getline("."),"[^ ]")
    if firstchar == a:comchar
        sil exe 'normal ^xx'
    else 
        sil exe 'normal ^i' . a:comchar . ' '
    endif
endfunction

So, for perl files you can map:

nnoremap <silent> <leader>c :call CommentToggle('#')<CR>

and pressing 3 \ c (un-)comments three lines from the cursor position.

You can also write a visual-mode mapping:

vnoremap <silent> <leader>c :call CommentToggle('#')<CR>

allowing you to select a visual region and press \c to (un-)comment them all.

This particular function only works for one-character comments ("#", "%", etc.), but it is straightforward to extend it to longer strings (e.g. "//"), and even more complex replacements, such as HTML comments.

Hope this helps.

Prince Goulash
  • 15,295
  • 2
  • 46
  • 47
  • 1
    I agree for the "better methods" However, there are even better methods: plugins dedicated to comments *toggling* -> EnhancedCommentify, NERDCommenter, tComment (I'm not sure about the last one; I've been using the first one for a decade now) – Luc Hermitte Jul 25 '11 at 21:41
1

Prince Goulash's answer doesn't work in lines with leading tabs.

I changed it, adding the tab character to the pattern, although lines lose their indent after comment and uncomment.

function! CommentToggle( comchar )
        let firstchar = matchstr( getline( "." ), "[^ \t]" )
        if firstchar == a:comchar
                sil exe 'normal ^2x'
        else
                sil exe 'normal ^i' . a:comchar . ' '
        endif
endfunction

I like more adding the comment char to first position in line, this modification to Prince Goulash's function does the trick:

function! CommentToggle( comchar )
        let firstchar = matchstr( getline( "." ), "[^ \t]" )
        if firstchar == a:comchar
                sil exe 'normal ^2x'
        else
                sil exe 'normal gI' . a:comchar . ' '
        endif
endfunction
Birei
  • 35,723
  • 2
  • 77
  • 82
  • 1
    Be careful with replying to answers with further answers -- once someone notices, they're typically gone in a few minutes :) -- but this is a good answer once it is less directed at Prince Goulash and more directed at solving beck's problem. :) – sarnold Jul 06 '11 at 00:04