diff options
-rw-r--r-- | autoload/paste_insert.vim | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/autoload/paste_insert.vim b/autoload/paste_insert.vim index d8585c6..421c3a2 100644 --- a/autoload/paste_insert.vim +++ b/autoload/paste_insert.vim @@ -53,6 +53,14 @@ let s:cancel = get(g:, 'paste_insert_cancel', ['<C-C>', '<Esc>']) " mapped them let s:maps = {} +" Function to abstract over shortcomings in Vim older than 7.3.032 in yielding +" incomplete map information; return as much as we can in the same structure +" as Vim after this patchlevel does with the {dict} parameter TRUE; +" unfortunately, this is just the mapping's right hand side. We should be +" able to figure out the <buffer> flag too, but that's it. The documentation +" for this plugin points out this unfortunate caveat, and suggests +" a workaround. +" function! s:MapArg(key, mode) abort if v:version > 703 || v:version == 703 && has('patch-32') return maparg(a:key, a:mode, 0, 1) @@ -69,48 +77,92 @@ endfunction " Start the paste: save each cancel key's prior function, remap it, set " 'paste' function! s:Start() abort + + " Collect and remove existing mappings for this key, replacing with a global + " map that cancels the pending paste operation + " for key in s:cancel let maps = [] + + " We might need to stop partway through this try + + " Collect first mapping, perhaps a buffer-local mapping, since maparg() + " yields those first let map = s:MapArg(key, 'n') if !empty(map) call add(maps, s:MapArg(key, 'n')) endif execute 'nunmap <buffer> '.key + + " Since we got here, the `:nunmap <buffer>` command must have worked, + " and there might be one more global map to collect let map = s:MapArg(key, 'n') if !empty(map) call add(maps, s:MapArg(key, 'n')) endif execute 'nunmap '.key + catch + " Ignore it endtry + + " If we collected two mappings, the first one must have been buffer-local, + " and Vim before 7.3.032 won't have told us that if len(maps) == 2 let maps[0]['buffer'] = 1 endif + + " Add the collected maps to this key's cache let s:maps[key] = maps + + " Set up our map to cancel the pending paste execute 'nnoremap '.key \.' :<C-U>doautocmd paste_insert User Cancel<CR>' endfor + + " Let's go! set paste + endfunction " Stop the paste: unset 'paste', restore prior function of cancel key function! s:Stop() abort + + " Let's stop! set nopaste + + " Now we need to remove our temporary maps, and restore the user's for key in s:cancel + + " Start by getting read of our map; there should now be none at all execute 'nunmap '.key + + " Iterate through any cached maps for this key for map in reverse(s:maps[key]) + + " Start building the command to restore the mapping; assume this is + " a nonrecursive map unless flagged otherwise let command = !has_key(map, 'noremap') || map['noremap'] \ ? ['nnoremap'] \ : ['nmap'] + + " Restore any flags for the mapping as we know them for flag in ['buffer', 'expr', 'nowait', 'silent'] if has_key(map, flag) && map[flag] call add(command, '<'.flag.'>') endif endfor + + " Add the key and right hand call extend(command, [key, map['rhs']]) execute join(command) + endfor + + " Clear the map cache for this key, now that we've restored them unlet s:maps[key] + endfor + endfunction |