> >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 ======================================

Reply via email to