On 4/21/06, Meino Christian Cramer <[EMAIL PROTECTED]> wrote:
> Hi,
>
>  (sorry for that "cryptical" subject...English isn't my mother's
>  tongue... :)
>
>  There is one feature of certain editors (for example Emacs with
>  cua.el loaded) I would die for:
>
>  With Emacs+cua.el it is possible to mark a rectangular shape of text.
>  Then, when text is entered and that rectangle is still highlighted
>  the other text of that file jumps letter by letter to the right to
>  make room for the newly entered text. This happens on by-character
>  basis.
>
>  (This is NO critc and NO "looks how bad vim is compared to Emacs". I
>  only need to describe the opposite to explain what I mean... !!! :)
>
>  With vim I can mark a rectangle in block-visual mode, then enter text
>  with "I" which appears in one line only, press <ESC> and then --
>  after a short pause -- is copied into all marked colomns.
>
>  Especially when it comes to handling of text based tables
>  this "live insertion" feature is a good help.
>
>  Is there anything like that in vim or is there any script available
>  to do so ?
>
>  Keep hacking!
>  mcc
>


I'm not sure I understand exactly what Emacs is doing, but here's something.

This will shift open a window of blanks inside the area selected via
visual-block-mode.  It's really just a shortcut for using ">" in
visual mode, but it's nicer because it shifts according to the input
length.

"i" and "a" are mapped such that they both "insert", but with
different methods.  "a" doesn't really "append".




" ----------------------------------------------------------------------
"
" This shifts keystroke by keystroke, but doesn't do all the standard input
" mode stuff, see Visual_block_shift_insert_start()
"
"

function! Visual_block_shift_insert()

    let save_shiftwidth = &shiftwidth
    let &shiftwidth = 1

    let inp_all = ''

    call Visual_block_normalize()

    while 1
        redraw
        let inp = getchar()
        let inp = ( nr2char( inp ) == "" ? inp : nr2char( inp ) )

        if inp =~ "\\(\<C-C>\\|\<ESC>\\)"
            break
        elseif inp =~ "\\(\<C-H>\\|\<BS>\\)"
            if strlen( inp_all ) > 0
                let inp_all = strpart( inp_all, 0, strlen( inp_all ) - 1 )
                exe "silent normal! gv<\<esc>"
                exe "silent normal! " . ( strlen( inp_all ) + 1 ) .
"s" . inp_all . "\<esc>"
                let b:visual_cols = strlen( inp_all )
                call Visual_block_set( b:visual_line_start,
b:visual_col_start, b:visual_lines, b:visual_cols )
            endif
        else
            let inp_all .= inp
            exe "silent normal! gv>\<esc>R" . inp_all
            let b:visual_cols = strlen( inp_all )
            call Visual_block_set( b:visual_line_start,
b:visual_col_start, b:visual_lines, b:visual_cols )
        endif
    endwhile
    let &shiftwidth = save_shiftwidth
endfunction

" ----------------------------------------------------------------------
"
" Alternate method to Visual_block_shift_insert() which uses the standard input
" mode where completion, <C-R>, etc are available:
"
function! Visual_block_shift_insert_start()
    inoremap <silent> <esc> <esc>:call Visual_block_shift_insert_end()<CR>
    inoremap <silent> <c-c> <esc>:call Visual_block_shift_insert_end()<CR>
    call Visual_block_normalize()
    exe "normal! \<esc>"
    normal! g`<
    startinsert
endfunction


function! Visual_block_shift_insert_end()
    iunmap <esc>
    iunmap <c-c>

    exe "normal! \<esc>"
    normal! `]y`[
    normal! u

    let save_shiftwidth = &shiftwidth
    let &shiftwidth = 1

    exe "silent normal! gv" . strlen( @" ) . ">\<esc>"
    exe "silent normal! \<esc>g`<R" . @" . "\<esc>"

    let &shiftwidth = save_shiftwidth

    let b:visual_cols = strlen( @" )
    call Visual_block_set( b:visual_line_start, b:visual_col_start,
b:visual_lines, b:visual_cols )
endfunction



function! Visual_block_normalize()
    " ------------------------------------------------------------
    " Normalize start and end positions to top-left and bottom-right
    silent normal! g`<
    let b:visual_line_start = line(".")
    let b:visual_col_start = col(".")

    silent normal! g`>
    let b:visual_lines = b:visual_line_start - line(".")
    let b:visual_cols = b:visual_col_start - col(".")
    if b:visual_lines < 0 | let b:visual_lines = -1 * b:visual_lines | endif
    if b:visual_cols < 0 | let b:visual_cols = -1 * b:visual_cols | endif
    let b:visual_lines += 1
    let b:visual_cols += 1

    " Position in top left:
    exe "silent normal! \<esc>gvdu"

    let b:visual_line_start = line(".")
    let b:visual_col_start = col(".")

    call Visual_block_set( b:visual_line_start, b:visual_col_start,
b:visual_lines, b:visual_cols )
endfunction




function! Visual_block_set( line, col, lines, cols )
    call cursor( a:line, a:col )
    exe "silent normal! \<C-V>"
    if a:lines > 1
        exe "silent normal! " . ( a:lines - 1 ) . "j"
    endif
    if a:cols > 1
        exe "silent normal! " . ( a:cols - 1 ) . "l"
    endif
endfunction




" ----------------------------------------------------------------------

" I don't think 'i' or 'a' are used for anything, but if I'm wrong, use
" some other chars.  BTW, 'a' doesn't really append.
"
" P.S. remember  gv
"
vnoremap <silent> i <esc>:call Visual_block_shift_insert()<cr>
vnoremap <silent> a <esc>:call Visual_block_shift_insert_start()<cr>

Reply via email to