> >But it doesn't work everytime.
This was my fault. exec @- did uses the deleted text before this
deletion.
> Why don't you use :imap and :vmap separately ?
Seems to be a working idea.
Now I've managed to get it working.
The trick was to use only one normal command.
============= surround.vim working =============================================
" sourround text with ", ', <>,(),[],{} <tag>/</tag>, ....
" and replace one with another
" TODO: find most inner pair automatically for replacement
" proposed mappings:
vnoremap <m-7> :<c-u>call Surround('v')<cr>
inoremap <m-7> :<c-u>call Surround('i')<cr>
nnoremap <m-7> :<c-u>call Surround('n')<cr>
noremap <m-8> :<c-u>call SubstituteSurrounding()<cr>
" By now these surroundings are availible
" "" '' () )( [] ][ {} }{ <> ><
" should be easy to add your own entries to g:pair_dict or g:pair
let g:pairs=[ ['"', '"'],
\ ['''', ''''],
\ ['(', ')'],
\ ['[', ']'],
\ ['{', '}'],
\ ['$', '$'],
\ ['&', '&'],
\ ['_', '_'],
\ ['<', '>'] ]
" create the dict of form key: [left, right]
" so you enter <mapping><key> to surround current word (or text in visual
" mode) with left,right.
let g:pair_dict = {}
for item in g:pairs
let g:pair_dict[item[0]] = item
let g:pair_dict[item[1]] = [item[1],item[0]]
endfor
" when called from normal/insertmode the word under the cursor will be
" surrounded, when called from visual mode the selected text will be
" surrounded
"
function! SurroundText(left, right, map_mode)
let g:left=a:left
let g:right=a:right
" no matter in which mode we are, select the characters to surround
"if a:map_mode == 'i'
"let norm_cmd = "normal <esc>viw"
"let g:d='i'
"else
if a:map_mode == 'n'
let norm_cmd = "viw"
let g:d='n'
elseif a:map_mode == 'v'
let norm_cmd = 'gv'
let g:d='v'
endif
" gv is necessary to get into visual mode again.. (is there a better way of
" doing this?
" s is used to remove the to be surrounded text and should be inserted again
" with @- which doesn't work
let a = @a
exec 'normal '.norm_cmd.'"as'.a:left."\<c-r>a".a:right
let @a = a
endfun
function! GetPairFromKeyboard()
for k in keys(g:pair_dict)
let max_len = 0
if len(k) > max_len
let max_len = len(k)
endif
endfor
let key = ""
while len(key) < max_len
let c = nr2char(getchar())
let key .= c
if exists('g:pairs["'.substitute(key,'"','\"','').'"]')
return g:pair_dict[key]
endif
endwhile
throw "no known pair given!"
endfunction
function! Surround(map_mode)
let pair = GetPairFromKeyboard()
call SurroundText(pair[0],pair[1],a:map_mode)
endfunction
function! SubstituteSurroundingText(subst, replace_with)
" escape [
let subst = deepcopy(a:subst)
let subst = map(subst,"substitute(v:val,'[','\\\\[','')")
let subst = map(subst,"substitute(v:val,']','\\\\]','')")
let g:subst=deepcopy(subst)
call searchpair(subst[0],'',subst[1],'')
"start visual mode, mark pair
exec "normal v?".subst[0]."\<cr>\<esc>"
let a = @a
let g:d2='normal
gvs'.a:replace_with[0]."\<c-r>=matchstr(@a,'^".subst[0]."\\zs.*\\ze".subst[1]."$')\<cr>".a:replace_with[1]
exec 'normal
gv"as'.a:replace_with[0]."\<c-r>=matchstr(@a,'^".subst[0]."\\zs.*\\ze".subst[1]."$')\<cr>".a:replace_with[1]
let @a=a
endfunction
function! SubstituteSurrounding()
let subst = GetPairFromKeyboard()
let replace_with = GetPairFromKeyboard()
call SubstituteSurroundingText(subst, replace_with)
endfunction
============= surrounding.vim working end ======================================