" unimpaired.vim - Pairs of handy bracket mappings " Maintainer: Tim Pope " Version: 1.1 if exists("g:loaded_unimpaired") || &cp || v:version < 700 finish endif let g:loaded_unimpaired = 1 let s:cpo_save = &cpo set cpo&vim " Next and previous {{{1 function! s:MapNextFamily(map,cmd) let map = 'unimpaired'.toupper(a:map) let end = ' ".(v:count ? v:count : "")' execute 'nmap '.map.'Previous :exe "'.a:cmd.'previous'.end execute 'nmap '.map.'Next :exe "'.a:cmd.'next'.end execute 'nmap '.map.'First :exe "'.a:cmd.'first'.end execute 'nmap '.map.'Last :exe "'.a:cmd.'last'.end execute 'nmap ['. a:map .' '.map.'Previous' execute 'nmap ]'. a:map .' '.map.'Next' execute 'nmap ['.toupper(a:map).' '.map.'First' execute 'nmap ]'.toupper(a:map).' '.map.'Last' endfunction call s:MapNextFamily('a','') call s:MapNextFamily('b','b') call s:MapNextFamily('l','l') call s:MapNextFamily('q','c') function! s:entries(path) let path = substitute(a:path,'[\\/]$','','') let files = split(glob(path."/.*"),"\n") let files += split(glob(path."/*"),"\n") call map(files,'substitute(v:val,"[\\/]$","","")') call filter(files,'v:val !~# "[\\\\/]\\.\\.\\=$"') call filter(files,'v:val[-4:-1] !=# ".swp" && v:val[-1:-1] !=# "~"') return files endfunction function! s:FileByOffset(num) let file = expand('%:p') let num = a:num while num let files = s:entries(fnamemodify(file,':h')) if a:num < 0 call reverse(sort(filter(files,'v:val < file'))) else call sort(filter(files,'v:val > file')) endif let temp = get(files,0,'') if temp == '' let file = fnamemodify(file,':h') else let file = temp while isdirectory(file) let files = s:entries(file) if files == [] " TODO: walk back up the tree and continue break endif let file = files[num > 0 ? 0 : -1] endwhile let num += num > 0 ? -1 : 1 endif endwhile return file endfunction nnoremap unimpairedONext :edit `=FileByOffset(v:count1)` nnoremap unimpairedOPrevious :edit `=FileByOffset(-v:count1)` nmap ]o unimpairedONext nmap [o unimpairedOPrevious " }}}1 " Line operations {{{1 nnoremap unimpairedBlankUp :put!=repeat(nr2char(10),v:count)']+1 nnoremap unimpairedBlankDown :put =repeat(nr2char(10),v:count)'[-1 nmap [ unimpairedBlankUp nmap ] unimpairedBlankDown nnoremap unimpairedMoveUp :exe 'norm m`'exe 'move--'.v:count1`` nnoremap unimpairedMoveDown :exe 'norm m`'exe 'move+'.v:count1`` xnoremap unimpairedMoveUp :exe 'norm m`'exe '''<,''>move--'.v:count1`` xnoremap unimpairedMoveDown :exe 'norm m`'exe '''<,''>move''>+'.v:count1`` nmap [e unimpairedMoveUp nmap ]e unimpairedMoveDown xmap [e unimpairedMoveUp xmap ]e unimpairedMoveDown " }}}1 " Encoding and decoding {{{1 function! s:StringEncode(str) let map = {"\n": 'n', "\r": 'r', "\t": 't', "\b": 'b', "\f": '\f', '"': '"', '\': '\'} return substitute(a:str,"[\001-\033\\\\\"]",'\="\\".get(map,submatch(0),printf("%03o",char2nr(submatch(0))))','g') endfunction function! s:StringDecode(str) let map = {'n': "\n", 'r': "\r", 't': "\t", 'b': "\b", 'f': "\f", 'e': "\e", 'a': "\001", 'v': "\013", '"': '"', '\': '\', "'": "'"} let str = a:str if str =~ '^\s*".\{-\}\\\@','\>','g') let str = substitute(str,'"','\"','g') return str endfunction function! s:XmlEntityDecode(str) let str = substitute(a:str,'\c&#\%(0*38\|x0*26\);','&','g') let str = substitute(str,'\c&#\(\d\+\);','\=nr2char(submatch(1))','g') let str = substitute(str,'\c&#\(x\x\+\);','\=nr2char("0".submatch(1))','g') let str = substitute(str,'\c'',"'",'g') let str = substitute(str,'\c"','"','g') let str = substitute(str,'\c>','>','g') let str = substitute(str,'\c<','<','g') let str = substitute(str,'\C&\(\%(amp;\)\@!\w*\);','\=nr2char(get(g:unimpaired_html_entities,submatch(1),63))','g') return substitute(str,'\c&','\&','g') endfunction function! s:XmlDecode(str) let str = substitute(a:str,'<\%([[:alnum:]-]\+=\%("[^"]*"\|''[^'']*''\)\|.\)\{-\}>','','g') return s:XmlEntityDecode(str) endfunction function! s:Transform(algorithm,type) let sel_save = &selection let cb_save = &clipboard set selection=inclusive clipboard-=unnamed clipboard-=unnamedplus let reg_save = @@ if a:type =~ '^\d\+$' silent exe 'norm! ^v'.a:type.'$hy' elseif a:type =~ '^.$' silent exe "normal! `<" . a:type . "`>y" elseif a:type == 'line' silent exe "normal! '[V']y" elseif a:type == 'block' silent exe "normal! `[\`]y" else silent exe "normal! `[v`]y" endif let @@ = s:{a:algorithm}(@@) norm! gvp let @@ = reg_save let &selection = sel_save let &clipboard = cb_save if a:type =~ '^\d\+$' silent! call repeat#set("\unimpairedLine".a:algorithm,a:type) endif endfunction function! s:TransformOpfunc(type) return s:Transform(s:encode_algorithm, a:type) endfunction function! s:TransformSetup(algorithm) let s:encode_algorithm = a:algorithm let &opfunc = matchstr(expand(''), '\d\+_').'TransformOpfunc' endfunction function! s:MapTransform(algorithm, key) exe 'nnoremap unimpaired' .a:algorithm.' :call TransformSetup("'.a:algorithm.'")g@' exe 'xnoremap unimpaired' .a:algorithm.' :call Transform("'.a:algorithm.'",visualmode())' exe 'nnoremap unimpairedLine'.a:algorithm.' :call Transform("'.a:algorithm.'",v:count1)' exe 'nmap '.a:key.' unimpaired'.a:algorithm exe 'xmap '.a:key.' unimpaired'.a:algorithm exe 'nmap '.a:key.a:key[strlen(a:key)-1].' unimpairedLine'.a:algorithm endfunction call s:MapTransform('StringEncode','[y') call s:MapTransform('StringDecode',']y') call s:MapTransform('UrlEncode','[u') call s:MapTransform('UrlDecode',']u') call s:MapTransform('XmlEncode','[x') call s:MapTransform('XmlDecode',']x') " }}}1 let &cpo = s:cpo_save " vim:set ft=vim ts=8 sw=2 sts=2: