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>