Search code examples
vimviemu

How to select a rectangular area in visual block mode (Ctrl+v) in empty file (vim)?


I can easily select a rectangular area in a file provided this area contains text or spaces (or anything). I do it with visual block mode and motion keys. But when I try to create such area in a new file (or any file without text) I can't. Is there a way to 'expand' this area by automatically filling it with spaces for example? Or am I going in wrong direction?

The reason I want this:

I create a new file with vim and then would like to create a comment block similar to this:

##############################################
#                                            #
#  My comment goes here                      #
#                                            #
##############################################

I can do it over existing text using Ctrl+v+motion keys, then r# to create an area filled with pounds. Then similarly to cut out inner rectangle with spaces.

How do I use this technique on a new file?

Thanks.


Solution

  • Apart from the (very good) answer from Brian Rasmussen, the only way I know of to do almost exactly what you're asking is to use virtualedit mode. This won't let you edit on non-existent lines, but it will let you edit beyond the end of existing lines. Therefore, to turn the current line into a load of # symbols, you could do this:

    :set virtualedit=all
    v50lr#
    

    To make a 50x5 block, you could create 4 new blank lines and then do the same:

    :set virtualedit=all
    4o<ESC>
    <C-V>4k50lr#
    

    (where <C-V> means press Ctrl+V and <ESC> means press Esc).

    I believe there are some plugins for various file types that make it much easier to create comment blocks like this, but I'm not sure which is best.

    You could just do something like:

    50i#<ESC>yyo#<ESC>48a<SPACE><ESC>a#<ENTER>#<SPACE><SPACE>My comment goes here<ESC>:exe<SPACE>'normal'<SPACE>(49-getpos('.')[2]).'a<SPACE>'<ENTER>a#<ENTER>#<ESC>48a<SPACE><ESC>a#<ESC>p
    

    But maybe that's just me being silly! I'll leave it as an exercise for the reader to figure out what's going on there if you're interested (:help is your friend).

    How about this as a slightly more serious alternative: bung the following in your vimrc or in a file in the plugins directory of the vim runtime folder (e.g. ~/.vim/plugins on Unix)

    nmap <F4> :InsertCommentBlock<CR>
    command! InsertCommentBlock call InsertCommentBlock()
    function! InsertCommentBlock()
        let linelength = 50
        let linelist = []
    
        call add(linelist, repeat('#', linelength))
        call add(linelist, '#' . repeat(' ', linelength-2) . '#')
        let comment = input('Please enter a comment: ')
        call add(linelist, '#  ' . comment . repeat(' ', linelength - (4+len(comment))) . '#')
        call add(linelist, '#' . repeat(' ', linelength-2) . '#')
        call add(linelist, repeat('#', linelength))
    
        call append(line('.'), linelist)
    endfunction
    

    See:

    :help function
    :help 'virtualedit'
    :help command
    :help nmap
    :help repeat()
    :help append()
    :help add()
    :help getpos()
    :help :exe
    

    etc...