Permalink
Find file
466 lines (409 sloc) 18.2 KB
" unimpaired.vim - Pairs of handy bracket mappings
" Maintainer: Tim Pope <http://tpo.pe/>
" Version: 1.2
" GetLatestVimScripts: 1590 1 :AutoInstall: unimpaired.vim
if exists("g:loaded_unimpaired") || &cp || v:version < 700
finish
endif
let g:loaded_unimpaired = 1
" Next and previous {{{1
function! s:MapNextFamily(map,cmd)
let map = '<Plug>unimpaired'.toupper(a:map)
let cmd = '".(v:count ? v:count : "")."'.a:cmd
let end = '"<CR>'.(a:cmd == 'l' || a:cmd == 'c' ? 'zv' : '')
execute 'nnoremap <silent> '.map.'Previous :<C-U>exe "'.cmd.'previous'.end
execute 'nnoremap <silent> '.map.'Next :<C-U>exe "'.cmd.'next'.end
execute 'nnoremap <silent> '.map.'First :<C-U>exe "'.cmd.'first'.end
execute 'nnoremap <silent> '.map.'Last :<C-U>exe "'.cmd.'last'.end
execute 'nmap <silent> ['. a:map .' '.map.'Previous'
execute 'nmap <silent> ]'. a:map .' '.map.'Next'
execute 'nmap <silent> ['.toupper(a:map).' '.map.'First'
execute 'nmap <silent> ]'.toupper(a:map).' '.map.'Last'
if exists(':'.a:cmd.'nfile')
execute 'nnoremap <silent> '.map.'PFile :<C-U>exe "'.cmd.'pfile'.end
execute 'nnoremap <silent> '.map.'NFile :<C-U>exe "'.cmd.'nfile'.end
execute 'nmap <silent> [<C-'.a:map.'> '.map.'PFile'
execute 'nmap <silent> ]<C-'.a:map.'> '.map.'NFile'
endif
endfunction
call s:MapNextFamily('a','')
call s:MapNextFamily('b','b')
call s:MapNextFamily('l','l')
call s:MapNextFamily('q','c')
call s:MapNextFamily('t','t')
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 !~# "[\\\\/]\\.\\.\\=$"')
let filter_suffixes = substitute(escape(&suffixes, '~.*$^'), ',', '$\\|', 'g') .'$'
call filter(files, 'v:val !~# filter_suffixes')
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
function! s:fnameescape(file) abort
if exists('*fnameescape')
return fnameescape(a:file)
else
return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
endif
endfunction
nnoremap <silent> <Plug>unimpairedDirectoryNext :<C-U>edit <C-R>=fnamemodify(<SID>fnameescape(<SID>FileByOffset(v:count1)), ':.')<CR><CR>
nnoremap <silent> <Plug>unimpairedDirectoryPrevious :<C-U>edit <C-R>=fnamemodify(<SID>fnameescape(<SID>FileByOffset(-v:count1)), ':.')<CR><CR>
nmap ]f <Plug>unimpairedDirectoryNext
nmap [f <Plug>unimpairedDirectoryPrevious
nmap <silent> <Plug>unimpairedONext <Plug>unimpairedDirectoryNext:echohl WarningMSG<Bar>echo "]o is deprecated. Use ]f"<Bar>echohl NONE<CR>
nmap <silent> <Plug>unimpairedOPrevious <Plug>unimpairedDirectoryPrevious:echohl WarningMSG<Bar>echo "[o is deprecated. Use [f"<Bar>echohl NONE<CR>
nmap ]o <Plug>unimpairedONext
nmap [o <Plug>unimpairedOPrevious
" }}}1
" Diff {{{1
nmap [n <Plug>unimpairedContextPrevious
nmap ]n <Plug>unimpairedContextNext
omap [n <Plug>unimpairedContextPrevious
omap ]n <Plug>unimpairedContextNext
nnoremap <silent> <Plug>unimpairedContextPrevious :call <SID>Context(1)<CR>
nnoremap <silent> <Plug>unimpairedContextNext :call <SID>Context(0)<CR>
onoremap <silent> <Plug>unimpairedContextPrevious :call <SID>ContextMotion(1)<CR>
onoremap <silent> <Plug>unimpairedContextNext :call <SID>ContextMotion(0)<CR>
function! s:Context(reverse)
call search('^\(@@ .* @@\|[<=>|]\{7}[<=>|]\@!\)', a:reverse ? 'bW' : 'W')
endfunction
function! s:ContextMotion(reverse)
if a:reverse
-
endif
call search('^@@ .* @@\|^diff \|^[<=>|]\{7}[<=>|]\@!', 'bWc')
if getline('.') =~# '^diff '
let end = search('^diff ', 'Wn') - 1
if end < 0
let end = line('$')
endif
elseif getline('.') =~# '^@@ '
let end = search('^@@ .* @@\|^diff ', 'Wn') - 1
if end < 0
let end = line('$')
endif
elseif getline('.') =~# '^=\{7\}'
+
let end = search('^>\{7}>\@!', 'Wnc')
elseif getline('.') =~# '^[<=>|]\{7\}'
let end = search('^[<=>|]\{7}[<=>|]\@!', 'Wn') - 1
else
return
endif
if end > line('.')
execute 'normal! V'.(end - line('.')).'j'
elseif end == line('.')
normal! V
endif
endfunction
" }}}1
" Line operations {{{1
function! s:BlankUp(count) abort
put!=repeat(nr2char(10), a:count)
']+1
silent! call repeat#set("\<Plug>unimpairedBlankUp", a:count)
endfunction
function! s:BlankDown(count) abort
put =repeat(nr2char(10), a:count)
'[-1
silent! call repeat#set("\<Plug>unimpairedBlankDown", a:count)
endfunction
nnoremap <silent> <Plug>unimpairedBlankUp :<C-U>call <SID>BlankUp(v:count1)<CR>
nnoremap <silent> <Plug>unimpairedBlankDown :<C-U>call <SID>BlankDown(v:count1)<CR>
nmap [<Space> <Plug>unimpairedBlankUp
nmap ]<Space> <Plug>unimpairedBlankDown
function! s:Move(cmd, count, map) abort
normal! m`
silent! exe 'move'.a:cmd.a:count
norm! ``
silent! call repeat#set("\<Plug>unimpairedMove".a:map, a:count)
endfunction
function! s:MoveSelectionUp(count) abort
normal! m`
silent! exe "'<,'>move'<--".a:count
norm! ``
silent! call repeat#set("\<Plug>unimpairedMoveSelectionUp", a:count)
endfunction
function! s:MoveSelectionDown(count) abort
normal! m`
exe "'<,'>move'>+".a:count
norm! ``
silent! call repeat#set("\<Plug>unimpairedMoveSelectionDown", a:count)
endfunction
nnoremap <silent> <Plug>unimpairedMoveUp :<C-U>call <SID>Move('--',v:count1,'Up')<CR>
nnoremap <silent> <Plug>unimpairedMoveDown :<C-U>call <SID>Move('+',v:count1,'Down')<CR>
noremap <silent> <Plug>unimpairedMoveSelectionUp :<C-U>call <SID>MoveSelectionUp(v:count1)<CR>
noremap <silent> <Plug>unimpairedMoveSelectionDown :<C-U>call <SID>MoveSelectionDown(v:count1)<CR>
nmap [e <Plug>unimpairedMoveUp
nmap ]e <Plug>unimpairedMoveDown
xmap [e <Plug>unimpairedMoveSelectionUp
xmap ]e <Plug>unimpairedMoveSelectionDown
" }}}1
" Option toggling {{{1
function! s:statusbump() abort
let &l:readonly = &l:readonly
return ''
endfunction
function! s:toggle(op) abort
call s:statusbump()
return eval('&'.a:op) ? 'no'.a:op : a:op
endfunction
function! s:option_map(letter, option, mode) abort
exe 'nnoremap [o'.a:letter ':'.a:mode.' '.a:option.'<C-R>=<SID>statusbump()<CR><CR>'
exe 'nnoremap ]o'.a:letter ':'.a:mode.' no'.a:option.'<C-R>=<SID>statusbump()<CR><CR>'
exe 'nnoremap co'.a:letter ':'.a:mode.' <C-R>=<SID>toggle("'.a:option.'")<CR><CR>'
endfunction
nnoremap [ob :set background=light<CR>
nnoremap ]ob :set background=dark<CR>
nnoremap cob :set background=<C-R>=&background == 'dark' ? 'light' : 'dark'<CR><CR>
call s:option_map('c', 'cursorline', 'setlocal')
call s:option_map('u', 'cursorcolumn', 'setlocal')
nnoremap [od :diffthis<CR>
nnoremap ]od :diffoff<CR>
nnoremap cod :<C-R>=&diff ? 'diffoff' : 'diffthis'<CR><CR>
call s:option_map('h', 'hlsearch', 'set')
call s:option_map('i', 'ignorecase', 'set')
call s:option_map('l', 'list', 'setlocal')
call s:option_map('n', 'number', 'setlocal')
call s:option_map('r', 'relativenumber', 'setlocal')
call s:option_map('s', 'spell', 'setlocal')
call s:option_map('w', 'wrap', 'setlocal')
nnoremap [ox :set cursorline cursorcolumn<CR>
nnoremap ]ox :set nocursorline nocursorcolumn<CR>
nnoremap cox :set <C-R>=&cursorline && &cursorcolumn ? 'nocursorline nocursorcolumn' : 'cursorline cursorcolumn'<CR><CR>
nnoremap [ov :set virtualedit+=all<CR>
nnoremap ]ov :set virtualedit-=all<CR>
nnoremap cov :set <C-R>=(&virtualedit =~# "all") ? 'virtualedit-=all' : 'virtualedit+=all'<CR><CR>
function! s:setup_paste() abort
let s:paste = &paste
let s:mouse = &mouse
set paste
set mouse=
augroup unimpaired_paste
autocmd!
autocmd InsertLeave *
\ if exists('s:paste') |
\ let &paste = s:paste |
\ let &mouse = s:mouse |
\ unlet s:paste |
\ unlet s:mouse |
\ endif |
\ autocmd! unimpaired_paste
augroup END
endfunction
nnoremap <silent> <Plug>unimpairedPaste :call <SID>setup_paste()<CR>
nnoremap <silent> yo :call <SID>setup_paste()<CR>o
nnoremap <silent> yO :call <SID>setup_paste()<CR>O
" }}}1
" Put {{{1
function! s:putline(how, map) abort
let [body, type] = [getreg(v:register), getregtype(v:register)]
call setreg(v:register, body, 'l')
exe 'normal! "'.v:register.a:how
call setreg(v:register, body, type)
if type !=# 'V'
silent! call repeat#set("\<Plug>unimpairedPut".a:map)
endif
endfunction
nnoremap <silent> <Plug>unimpairedPutAbove :call <SID>putline('[p', 'Above')<CR>
nnoremap <silent> <Plug>unimpairedPutBelow :call <SID>putline(']p', 'Below')<CR>
nmap [p <Plug>unimpairedPutAbove
nmap ]p <Plug>unimpairedPutBelow
nnoremap <silent> >P :call <SID>putline('[p', 'Above')<CR>>']
nnoremap <silent> >p :call <SID>putline(']p', 'Below')<CR>>']
nnoremap <silent> <P :call <SID>putline('[p', 'Above')<CR><']
nnoremap <silent> <p :call <SID>putline(']p', 'Below')<CR><']
nnoremap <silent> =P :call <SID>putline('[p', 'Above')<CR>=']
nnoremap <silent> =p :call <SID>putline(']p', 'Below')<CR>=']
" }}}1
" Encoding and decoding {{{1
function! s:string_encode(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:string_decode(str)
let map = {'n': "\n", 'r': "\r", 't': "\t", 'b': "\b", 'f': "\f", 'e': "\e", 'a': "\001", 'v': "\013", "\n": ''}
let str = a:str
if str =~ '^\s*".\{-\}\\\@<!\%(\\\\\)*"\s*\n\=$'
let str = substitute(substitute(str,'^\s*\zs"','',''),'"\ze\s*\n\=$','','')
endif
return substitute(str,'\\\(\o\{1,3\}\|x\x\{1,2\}\|u\x\{1,4\}\|.\)','\=get(map,submatch(1),submatch(1) =~? "^[0-9xu]" ? nr2char("0".substitute(submatch(1),"^[Uu]","x","")) : submatch(1))','g')
endfunction
function! s:url_encode(str)
return substitute(a:str,'[^A-Za-z0-9_.~-]','\="%".printf("%02X",char2nr(submatch(0)))','g')
endfunction
function! s:url_decode(str)
let str = substitute(substitute(substitute(a:str,'%0[Aa]\n$','%0A',''),'%0[Aa]','\n','g'),'+',' ','g')
return substitute(str,'%\(\x\x\)','\=nr2char("0x".submatch(1))','g')
endfunction
" HTML entities {{{2
let g:unimpaired_html_entities = {
\ 'nbsp': 160, 'iexcl': 161, 'cent': 162, 'pound': 163,
\ 'curren': 164, 'yen': 165, 'brvbar': 166, 'sect': 167,
\ 'uml': 168, 'copy': 169, 'ordf': 170, 'laquo': 171,
\ 'not': 172, 'shy': 173, 'reg': 174, 'macr': 175,
\ 'deg': 176, 'plusmn': 177, 'sup2': 178, 'sup3': 179,
\ 'acute': 180, 'micro': 181, 'para': 182, 'middot': 183,
\ 'cedil': 184, 'sup1': 185, 'ordm': 186, 'raquo': 187,
\ 'frac14': 188, 'frac12': 189, 'frac34': 190, 'iquest': 191,
\ 'Agrave': 192, 'Aacute': 193, 'Acirc': 194, 'Atilde': 195,
\ 'Auml': 196, 'Aring': 197, 'AElig': 198, 'Ccedil': 199,
\ 'Egrave': 200, 'Eacute': 201, 'Ecirc': 202, 'Euml': 203,
\ 'Igrave': 204, 'Iacute': 205, 'Icirc': 206, 'Iuml': 207,
\ 'ETH': 208, 'Ntilde': 209, 'Ograve': 210, 'Oacute': 211,
\ 'Ocirc': 212, 'Otilde': 213, 'Ouml': 214, 'times': 215,
\ 'Oslash': 216, 'Ugrave': 217, 'Uacute': 218, 'Ucirc': 219,
\ 'Uuml': 220, 'Yacute': 221, 'THORN': 222, 'szlig': 223,
\ 'agrave': 224, 'aacute': 225, 'acirc': 226, 'atilde': 227,
\ 'auml': 228, 'aring': 229, 'aelig': 230, 'ccedil': 231,
\ 'egrave': 232, 'eacute': 233, 'ecirc': 234, 'euml': 235,
\ 'igrave': 236, 'iacute': 237, 'icirc': 238, 'iuml': 239,
\ 'eth': 240, 'ntilde': 241, 'ograve': 242, 'oacute': 243,
\ 'ocirc': 244, 'otilde': 245, 'ouml': 246, 'divide': 247,
\ 'oslash': 248, 'ugrave': 249, 'uacute': 250, 'ucirc': 251,
\ 'uuml': 252, 'yacute': 253, 'thorn': 254, 'yuml': 255,
\ 'OElig': 338, 'oelig': 339, 'Scaron': 352, 'scaron': 353,
\ 'Yuml': 376, 'circ': 710, 'tilde': 732, 'ensp': 8194,
\ 'emsp': 8195, 'thinsp': 8201, 'zwnj': 8204, 'zwj': 8205,
\ 'lrm': 8206, 'rlm': 8207, 'ndash': 8211, 'mdash': 8212,
\ 'lsquo': 8216, 'rsquo': 8217, 'sbquo': 8218, 'ldquo': 8220,
\ 'rdquo': 8221, 'bdquo': 8222, 'dagger': 8224, 'Dagger': 8225,
\ 'permil': 8240, 'lsaquo': 8249, 'rsaquo': 8250, 'euro': 8364,
\ 'fnof': 402, 'Alpha': 913, 'Beta': 914, 'Gamma': 915,
\ 'Delta': 916, 'Epsilon': 917, 'Zeta': 918, 'Eta': 919,
\ 'Theta': 920, 'Iota': 921, 'Kappa': 922, 'Lambda': 923,
\ 'Mu': 924, 'Nu': 925, 'Xi': 926, 'Omicron': 927,
\ 'Pi': 928, 'Rho': 929, 'Sigma': 931, 'Tau': 932,
\ 'Upsilon': 933, 'Phi': 934, 'Chi': 935, 'Psi': 936,
\ 'Omega': 937, 'alpha': 945, 'beta': 946, 'gamma': 947,
\ 'delta': 948, 'epsilon': 949, 'zeta': 950, 'eta': 951,
\ 'theta': 952, 'iota': 953, 'kappa': 954, 'lambda': 955,
\ 'mu': 956, 'nu': 957, 'xi': 958, 'omicron': 959,
\ 'pi': 960, 'rho': 961, 'sigmaf': 962, 'sigma': 963,
\ 'tau': 964, 'upsilon': 965, 'phi': 966, 'chi': 967,
\ 'psi': 968, 'omega': 969, 'thetasym': 977, 'upsih': 978,
\ 'piv': 982, 'bull': 8226, 'hellip': 8230, 'prime': 8242,
\ 'Prime': 8243, 'oline': 8254, 'frasl': 8260, 'weierp': 8472,
\ 'image': 8465, 'real': 8476, 'trade': 8482, 'alefsym': 8501,
\ 'larr': 8592, 'uarr': 8593, 'rarr': 8594, 'darr': 8595,
\ 'harr': 8596, 'crarr': 8629, 'lArr': 8656, 'uArr': 8657,
\ 'rArr': 8658, 'dArr': 8659, 'hArr': 8660, 'forall': 8704,
\ 'part': 8706, 'exist': 8707, 'empty': 8709, 'nabla': 8711,
\ 'isin': 8712, 'notin': 8713, 'ni': 8715, 'prod': 8719,
\ 'sum': 8721, 'minus': 8722, 'lowast': 8727, 'radic': 8730,
\ 'prop': 8733, 'infin': 8734, 'ang': 8736, 'and': 8743,
\ 'or': 8744, 'cap': 8745, 'cup': 8746, 'int': 8747,
\ 'there4': 8756, 'sim': 8764, 'cong': 8773, 'asymp': 8776,
\ 'ne': 8800, 'equiv': 8801, 'le': 8804, 'ge': 8805,
\ 'sub': 8834, 'sup': 8835, 'nsub': 8836, 'sube': 8838,
\ 'supe': 8839, 'oplus': 8853, 'otimes': 8855, 'perp': 8869,
\ 'sdot': 8901, 'lceil': 8968, 'rceil': 8969, 'lfloor': 8970,
\ 'rfloor': 8971, 'lang': 9001, 'rang': 9002, 'loz': 9674,
\ 'spades': 9824, 'clubs': 9827, 'hearts': 9829, 'diams': 9830,
\ 'apos': 39}
" }}}2
function! s:xml_encode(str)
let str = a:str
let str = substitute(str,'&','\&amp;','g')
let str = substitute(str,'<','\&lt;','g')
let str = substitute(str,'>','\&gt;','g')
let str = substitute(str,'"','\&quot;','g')
return str
endfunction
function! s:xml_entity_decode(str)
let str = substitute(a:str,'\c&#\%(0*38\|x0*26\);','&amp;','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&apos;',"'",'g')
let str = substitute(str,'\c&quot;','"','g')
let str = substitute(str,'\c&gt;','>','g')
let str = substitute(str,'\c&lt;','<','g')
let str = substitute(str,'\C&\(\%(amp;\)\@!\w*\);','\=nr2char(get(g:unimpaired_html_entities,submatch(1),63))','g')
return substitute(str,'\c&amp;','\&','g')
endfunction
function! s:xml_decode(str)
let str = substitute(a:str,'<\%([[:alnum:]-]\+=\%("[^"]*"\|''[^'']*''\)\|.\)\{-\}>','','g')
return s:xml_entity_decode(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! `[\<C-V>`]y"
else
silent exe "normal! `[v`]y"
endif
if a:algorithm =~# '^\u\|#'
let @@ = {a:algorithm}(@@)
else
let @@ = s:{a:algorithm}(@@)
endif
norm! gvp
let @@ = reg_save
let &selection = sel_save
let &clipboard = cb_save
if a:type =~ '^\d\+$'
silent! call repeat#set("\<Plug>unimpaired_line_".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('<sfile>'), '<SNR>\d\+_').'TransformOpfunc'
endfunction
function! UnimpairedMapTransform(algorithm, key)
exe 'nnoremap <silent> <Plug>unimpaired_' .a:algorithm.' :<C-U>call <SID>TransformSetup("'.a:algorithm.'")<CR>g@'
exe 'xnoremap <silent> <Plug>unimpaired_' .a:algorithm.' :<C-U>call <SID>Transform("'.a:algorithm.'",visualmode())<CR>'
exe 'nnoremap <silent> <Plug>unimpaired_line_'.a:algorithm.' :<C-U>call <SID>Transform("'.a:algorithm.'",v:count1)<CR>'
exe 'nmap '.a:key.' <Plug>unimpaired_'.a:algorithm
exe 'xmap '.a:key.' <Plug>unimpaired_'.a:algorithm
exe 'nmap '.a:key.a:key[strlen(a:key)-1].' <Plug>unimpaired_line_'.a:algorithm
endfunction
call UnimpairedMapTransform('string_encode','[y')
call UnimpairedMapTransform('string_decode',']y')
call UnimpairedMapTransform('url_encode','[u')
call UnimpairedMapTransform('url_decode',']u')
call UnimpairedMapTransform('xml_encode','[x')
call UnimpairedMapTransform('xml_decode',']x')
" }}}1
" vim:set sw=2 sts=2: