]>
Commit | Line | Data |
---|---|---|
0d23b6e5 BB |
1 | " unimpaired.vim - Pairs of handy bracket mappings |
2 | " Maintainer: Tim Pope <http://tpo.pe/> | |
3 | " Version: 1.1 | |
4 | " GetLatestVimScripts: 1590 1 :AutoInstall: unimpaired.vim | |
5 | ||
6 | if exists("g:loaded_unimpaired") || &cp || v:version < 700 | |
7 | finish | |
8 | endif | |
9 | let g:loaded_unimpaired = 1 | |
10 | ||
11 | " Next and previous {{{1 | |
12 | ||
13 | function! s:MapNextFamily(map,cmd) | |
14 | let map = '<Plug>unimpaired'.toupper(a:map) | |
15 | let end = ' ".(v:count ? v:count : "")<CR>' | |
16 | execute 'nmap <silent> '.map.'Previous :<C-U>exe "'.a:cmd.'previous'.end | |
17 | execute 'nmap <silent> '.map.'Next :<C-U>exe "'.a:cmd.'next'.end | |
18 | execute 'nmap <silent> '.map.'First :<C-U>exe "'.a:cmd.'first'.end | |
19 | execute 'nmap <silent> '.map.'Last :<C-U>exe "'.a:cmd.'last'.end | |
20 | execute 'nmap <silent> ['. a:map .' '.map.'Previous' | |
21 | execute 'nmap <silent> ]'. a:map .' '.map.'Next' | |
22 | execute 'nmap <silent> ['.toupper(a:map).' '.map.'First' | |
23 | execute 'nmap <silent> ]'.toupper(a:map).' '.map.'Last' | |
24 | endfunction | |
25 | ||
26 | call s:MapNextFamily('a','') | |
27 | call s:MapNextFamily('b','b') | |
28 | call s:MapNextFamily('l','l') | |
29 | call s:MapNextFamily('q','c') | |
30 | call s:MapNextFamily('t','t') | |
31 | ||
32 | function! s:entries(path) | |
33 | let path = substitute(a:path,'[\\/]$','','') | |
34 | let files = split(glob(path."/.*"),"\n") | |
35 | let files += split(glob(path."/*"),"\n") | |
36 | call map(files,'substitute(v:val,"[\\/]$","","")') | |
37 | call filter(files,'v:val !~# "[\\\\/]\\.\\.\\=$"') | |
38 | call filter(files,'v:val[-4:-1] !=# ".swp" && v:val[-1:-1] !=# "~"') | |
39 | return files | |
40 | endfunction | |
41 | ||
42 | function! s:FileByOffset(num) | |
43 | let file = expand('%:p') | |
44 | let num = a:num | |
45 | while num | |
46 | let files = s:entries(fnamemodify(file,':h')) | |
47 | if a:num < 0 | |
48 | call reverse(sort(filter(files,'v:val < file'))) | |
49 | else | |
50 | call sort(filter(files,'v:val > file')) | |
51 | endif | |
52 | let temp = get(files,0,'') | |
53 | if temp == '' | |
54 | let file = fnamemodify(file,':h') | |
55 | else | |
56 | let file = temp | |
57 | while isdirectory(file) | |
58 | let files = s:entries(file) | |
59 | if files == [] | |
60 | " TODO: walk back up the tree and continue | |
61 | break | |
62 | endif | |
63 | let file = files[num > 0 ? 0 : -1] | |
64 | endwhile | |
65 | let num += num > 0 ? -1 : 1 | |
66 | endif | |
67 | endwhile | |
68 | return file | |
69 | endfunction | |
70 | ||
71 | nnoremap <silent> <Plug>unimpairedONext :<C-U>edit `=<SID>FileByOffset(v:count1)`<CR> | |
72 | nnoremap <silent> <Plug>unimpairedOPrevious :<C-U>edit `=<SID>FileByOffset(-v:count1)`<CR> | |
73 | ||
74 | nmap ]o <Plug>unimpairedONext | |
75 | nmap [o <Plug>unimpairedOPrevious | |
76 | ||
77 | nmap [, :call search('^[<=>]\{7\}','bW')<CR> | |
78 | nmap ], :call search('^[<=>]\{7\}','W')<CR> | |
79 | omap [, V:call search('^[<=>]\{7\}','bW')<CR> | |
80 | omap ], V:call search('^[<=>]\{7\}','W')<CR> | |
81 | xmap [, :<C-U>exe 'norm! gv'<Bar>call search('^[<=>]\{7\}','bW')<CR> | |
82 | xmap ], :<C-U>exe 'norm! gv'<Bar>call search('^[<=>]\{7\}','W')<CR> | |
83 | nmap [< :call search('^<<<<<<<','bW')<CR> | |
84 | nmap [= :call search('^=======','bW')<CR> | |
85 | nmap [> :call search('^>>>>>>>','bW')<CR> | |
86 | nmap ]< :call search('^<<<<<<<','W')<CR> | |
87 | nmap ]= :call search('^=======','W')<CR> | |
88 | nmap ]> :call search('^>>>>>>>','W')<CR> | |
89 | xmap [< :<C-U>exe 'norm! gv'<Bar>call search('^<<<<<<<','bW')<CR> | |
90 | xmap [= :<C-U>exe 'norm! gv'<Bar>call search('^=======','bW')<CR> | |
91 | xmap [> :<C-U>exe 'norm! gv'<Bar>call search('^>>>>>>>','bW')<CR> | |
92 | xmap ]< :<C-U>exe 'norm! gv'<Bar>call search('^<<<<<<<','W')<CR> | |
93 | xmap ]= :<C-U>exe 'norm! gv'<Bar>call search('^=======','W')<CR> | |
94 | xmap ]> :<C-U>exe 'norm! gv'<Bar>call search('^>>>>>>>','W')<CR> | |
95 | omap [< V:call search('^<<<<<<<','bW')<CR> | |
96 | omap [= V:call search('^=======','bW')<CR> | |
97 | omap [> V:call search('^>>>>>>>','bW')<CR> | |
98 | omap ]< V:call search('^<<<<<<<','W')<CR> | |
99 | omap ]= V:call search('^=======','W')<CR> | |
100 | omap ]> V:call search('^>>>>>>>','W')<CR> | |
101 | ||
102 | " }}}1 | |
103 | " Line operations {{{1 | |
104 | ||
105 | function! s:BlankUp(count) abort | |
106 | put!=repeat(nr2char(10), a:count) | |
107 | ']+1 | |
108 | silent! call repeat#set("\<Plug>unimpairedBlankUp", a:count) | |
109 | endfunction | |
110 | ||
111 | function! s:BlankDown(count) abort | |
112 | put =repeat(nr2char(10), a:count) | |
113 | '[-1 | |
114 | silent! call repeat#set("\<Plug>unimpairedBlankDown", a:count) | |
115 | endfunction | |
116 | ||
117 | nnoremap <silent> <Plug>unimpairedBlankUp :<C-U>call <SID>BlankUp(v:count1)<CR> | |
118 | nnoremap <silent> <Plug>unimpairedBlankDown :<C-U>call <SID>BlankDown(v:count1)<CR> | |
119 | ||
120 | nmap [<Space> <Plug>unimpairedBlankUp | |
121 | nmap ]<Space> <Plug>unimpairedBlankDown | |
122 | ||
123 | function! s:Move(cmd, count, map) abort | |
124 | normal! m` | |
125 | exe 'move'.a:cmd.a:count | |
126 | norm! `` | |
127 | call repeat#set("\<Plug>unimpairedMove".a:map, a:count) | |
128 | endfunction | |
129 | ||
130 | nnoremap <silent> <Plug>unimpairedMoveUp :<C-U>call <SID>Move('--',v:count1,'Up')<CR> | |
131 | nnoremap <silent> <Plug>unimpairedMoveDown :<C-U>call <SID>Move('+',v:count1,'Down')<CR> | |
132 | xnoremap <silent> <Plug>unimpairedMoveUp :<C-U>exe 'normal! m`'<Bar>exe '''<,''>move--'.v:count1<CR>`` | |
133 | xnoremap <silent> <Plug>unimpairedMoveDown :<C-U>exe 'normal! m`'<Bar>exe '''<,''>move''>+'.v:count1<CR>`` | |
134 | ||
135 | nmap [e <Plug>unimpairedMoveUp | |
136 | nmap ]e <Plug>unimpairedMoveDown | |
137 | xmap [e <Plug>unimpairedMoveUp | |
138 | xmap ]e <Plug>unimpairedMoveDown | |
139 | ||
140 | " }}}1 | |
141 | " Encoding and decoding {{{1 | |
142 | ||
143 | function! s:StringEncode(str) | |
144 | let map = {"\n": 'n', "\r": 'r', "\t": 't', "\b": 'b', "\f": '\f', '"': '"', '\': '\'} | |
145 | return substitute(a:str,"[\001-\033\\\\\"]",'\="\\".get(map,submatch(0),printf("%03o",char2nr(submatch(0))))','g') | |
146 | endfunction | |
147 | ||
148 | function! s:StringDecode(str) | |
149 | let map = {'n': "\n", 'r': "\r", 't': "\t", 'b': "\b", 'f': "\f", 'e': "\e", 'a': "\001", 'v': "\013"} | |
150 | let str = a:str | |
151 | if str =~ '^\s*".\{-\}\\\@<!\%(\\\\\)*"\s*\n\=$' | |
152 | let str = substitute(substitute(str,'^\s*\zs"','',''),'"\ze\s*\n\=$','','') | |
153 | endif | |
154 | let str = substitute(str,'\\n\%(\n$\)\=','\n','g') | |
155 | 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') | |
156 | endfunction | |
157 | ||
158 | function! s:UrlEncode(str) | |
159 | return substitute(a:str,'[^A-Za-z0-9_.~-]','\="%".printf("%02X",char2nr(submatch(0)))','g') | |
160 | endfunction | |
161 | ||
162 | function! s:UrlDecode(str) | |
163 | let str = substitute(substitute(substitute(a:str,'%0[Aa]\n$','%0A',''),'%0[Aa]','\n','g'),'+',' ','g') | |
164 | return substitute(str,'%\(\x\x\)','\=nr2char("0x".submatch(1))','g') | |
165 | endfunction | |
166 | ||
167 | " HTML entities {{{2 | |
168 | ||
169 | let g:unimpaired_html_entities = { | |
170 | \ 'nbsp': 160, 'iexcl': 161, 'cent': 162, 'pound': 163, | |
171 | \ 'curren': 164, 'yen': 165, 'brvbar': 166, 'sect': 167, | |
172 | \ 'uml': 168, 'copy': 169, 'ordf': 170, 'laquo': 171, | |
173 | \ 'not': 172, 'shy': 173, 'reg': 174, 'macr': 175, | |
174 | \ 'deg': 176, 'plusmn': 177, 'sup2': 178, 'sup3': 179, | |
175 | \ 'acute': 180, 'micro': 181, 'para': 182, 'middot': 183, | |
176 | \ 'cedil': 184, 'sup1': 185, 'ordm': 186, 'raquo': 187, | |
177 | \ 'frac14': 188, 'frac12': 189, 'frac34': 190, 'iquest': 191, | |
178 | \ 'Agrave': 192, 'Aacute': 193, 'Acirc': 194, 'Atilde': 195, | |
179 | \ 'Auml': 196, 'Aring': 197, 'AElig': 198, 'Ccedil': 199, | |
180 | \ 'Egrave': 200, 'Eacute': 201, 'Ecirc': 202, 'Euml': 203, | |
181 | \ 'Igrave': 204, 'Iacute': 205, 'Icirc': 206, 'Iuml': 207, | |
182 | \ 'ETH': 208, 'Ntilde': 209, 'Ograve': 210, 'Oacute': 211, | |
183 | \ 'Ocirc': 212, 'Otilde': 213, 'Ouml': 214, 'times': 215, | |
184 | \ 'Oslash': 216, 'Ugrave': 217, 'Uacute': 218, 'Ucirc': 219, | |
185 | \ 'Uuml': 220, 'Yacute': 221, 'THORN': 222, 'szlig': 223, | |
186 | \ 'agrave': 224, 'aacute': 225, 'acirc': 226, 'atilde': 227, | |
187 | \ 'auml': 228, 'aring': 229, 'aelig': 230, 'ccedil': 231, | |
188 | \ 'egrave': 232, 'eacute': 233, 'ecirc': 234, 'euml': 235, | |
189 | \ 'igrave': 236, 'iacute': 237, 'icirc': 238, 'iuml': 239, | |
190 | \ 'eth': 240, 'ntilde': 241, 'ograve': 242, 'oacute': 243, | |
191 | \ 'ocirc': 244, 'otilde': 245, 'ouml': 246, 'divide': 247, | |
192 | \ 'oslash': 248, 'ugrave': 249, 'uacute': 250, 'ucirc': 251, | |
193 | \ 'uuml': 252, 'yacute': 253, 'thorn': 254, 'yuml': 255, | |
194 | \ 'OElig': 338, 'oelig': 339, 'Scaron': 352, 'scaron': 353, | |
195 | \ 'Yuml': 376, 'circ': 710, 'tilde': 732, 'ensp': 8194, | |
196 | \ 'emsp': 8195, 'thinsp': 8201, 'zwnj': 8204, 'zwj': 8205, | |
197 | \ 'lrm': 8206, 'rlm': 8207, 'ndash': 8211, 'mdash': 8212, | |
198 | \ 'lsquo': 8216, 'rsquo': 8217, 'sbquo': 8218, 'ldquo': 8220, | |
199 | \ 'rdquo': 8221, 'bdquo': 8222, 'dagger': 8224, 'Dagger': 8225, | |
200 | \ 'permil': 8240, 'lsaquo': 8249, 'rsaquo': 8250, 'euro': 8364, | |
201 | \ 'fnof': 402, 'Alpha': 913, 'Beta': 914, 'Gamma': 915, | |
202 | \ 'Delta': 916, 'Epsilon': 917, 'Zeta': 918, 'Eta': 919, | |
203 | \ 'Theta': 920, 'Iota': 921, 'Kappa': 922, 'Lambda': 923, | |
204 | \ 'Mu': 924, 'Nu': 925, 'Xi': 926, 'Omicron': 927, | |
205 | \ 'Pi': 928, 'Rho': 929, 'Sigma': 931, 'Tau': 932, | |
206 | \ 'Upsilon': 933, 'Phi': 934, 'Chi': 935, 'Psi': 936, | |
207 | \ 'Omega': 937, 'alpha': 945, 'beta': 946, 'gamma': 947, | |
208 | \ 'delta': 948, 'epsilon': 949, 'zeta': 950, 'eta': 951, | |
209 | \ 'theta': 952, 'iota': 953, 'kappa': 954, 'lambda': 955, | |
210 | \ 'mu': 956, 'nu': 957, 'xi': 958, 'omicron': 959, | |
211 | \ 'pi': 960, 'rho': 961, 'sigmaf': 962, 'sigma': 963, | |
212 | \ 'tau': 964, 'upsilon': 965, 'phi': 966, 'chi': 967, | |
213 | \ 'psi': 968, 'omega': 969, 'thetasym': 977, 'upsih': 978, | |
214 | \ 'piv': 982, 'bull': 8226, 'hellip': 8230, 'prime': 8242, | |
215 | \ 'Prime': 8243, 'oline': 8254, 'frasl': 8260, 'weierp': 8472, | |
216 | \ 'image': 8465, 'real': 8476, 'trade': 8482, 'alefsym': 8501, | |
217 | \ 'larr': 8592, 'uarr': 8593, 'rarr': 8594, 'darr': 8595, | |
218 | \ 'harr': 8596, 'crarr': 8629, 'lArr': 8656, 'uArr': 8657, | |
219 | \ 'rArr': 8658, 'dArr': 8659, 'hArr': 8660, 'forall': 8704, | |
220 | \ 'part': 8706, 'exist': 8707, 'empty': 8709, 'nabla': 8711, | |
221 | \ 'isin': 8712, 'notin': 8713, 'ni': 8715, 'prod': 8719, | |
222 | \ 'sum': 8721, 'minus': 8722, 'lowast': 8727, 'radic': 8730, | |
223 | \ 'prop': 8733, 'infin': 8734, 'ang': 8736, 'and': 8743, | |
224 | \ 'or': 8744, 'cap': 8745, 'cup': 8746, 'int': 8747, | |
225 | \ 'there4': 8756, 'sim': 8764, 'cong': 8773, 'asymp': 8776, | |
226 | \ 'ne': 8800, 'equiv': 8801, 'le': 8804, 'ge': 8805, | |
227 | \ 'sub': 8834, 'sup': 8835, 'nsub': 8836, 'sube': 8838, | |
228 | \ 'supe': 8839, 'oplus': 8853, 'otimes': 8855, 'perp': 8869, | |
229 | \ 'sdot': 8901, 'lceil': 8968, 'rceil': 8969, 'lfloor': 8970, | |
230 | \ 'rfloor': 8971, 'lang': 9001, 'rang': 9002, 'loz': 9674, | |
231 | \ 'spades': 9824, 'clubs': 9827, 'hearts': 9829, 'diams': 9830, | |
232 | \ 'apos': 39} | |
233 | ||
234 | " }}}2 | |
235 | ||
236 | function! s:XmlEncode(str) | |
237 | let str = a:str | |
238 | let str = substitute(str,'&','\&','g') | |
239 | let str = substitute(str,'<','\<','g') | |
240 | let str = substitute(str,'>','\>','g') | |
241 | let str = substitute(str,'"','\"','g') | |
242 | return str | |
243 | endfunction | |
244 | ||
245 | function! s:XmlEntityDecode(str) | |
246 | let str = substitute(a:str,'\c&#\%(0*38\|x0*26\);','&','g') | |
247 | let str = substitute(str,'\c&#\(\d\+\);','\=nr2char(submatch(1))','g') | |
248 | let str = substitute(str,'\c&#\(x\x\+\);','\=nr2char("0".submatch(1))','g') | |
249 | let str = substitute(str,'\c'',"'",'g') | |
250 | let str = substitute(str,'\c"','"','g') | |
251 | let str = substitute(str,'\c>','>','g') | |
252 | let str = substitute(str,'\c<','<','g') | |
253 | let str = substitute(str,'\C&\(\%(amp;\)\@!\w*\);','\=nr2char(get(g:unimpaired_html_entities,submatch(1),63))','g') | |
254 | return substitute(str,'\c&','\&','g') | |
255 | endfunction | |
256 | ||
257 | function! s:XmlDecode(str) | |
258 | let str = substitute(a:str,'<\%([[:alnum:]-]\+=\%("[^"]*"\|''[^'']*''\)\|.\)\{-\}>','','g') | |
259 | return s:XmlEntityDecode(str) | |
260 | endfunction | |
261 | ||
262 | function! s:Transform(algorithm,type) | |
263 | let sel_save = &selection | |
264 | let cb_save = &clipboard | |
265 | set selection=inclusive clipboard-=unnamed clipboard-=unnamedplus | |
266 | let reg_save = @@ | |
267 | if a:type =~ '^\d\+$' | |
268 | silent exe 'norm! ^v'.a:type.'$hy' | |
269 | elseif a:type =~ '^.$' | |
270 | silent exe "normal! `<" . a:type . "`>y" | |
271 | elseif a:type == 'line' | |
272 | silent exe "normal! '[V']y" | |
273 | elseif a:type == 'block' | |
274 | silent exe "normal! `[\<C-V>`]y" | |
275 | else | |
276 | silent exe "normal! `[v`]y" | |
277 | endif | |
278 | let @@ = s:{a:algorithm}(@@) | |
279 | norm! gvp | |
280 | let @@ = reg_save | |
281 | let &selection = sel_save | |
282 | let &clipboard = cb_save | |
283 | if a:type =~ '^\d\+$' | |
284 | silent! call repeat#set("\<Plug>unimpairedLine".a:algorithm,a:type) | |
285 | endif | |
286 | endfunction | |
287 | ||
288 | function! s:TransformOpfunc(type) | |
289 | return s:Transform(s:encode_algorithm, a:type) | |
290 | endfunction | |
291 | ||
292 | function! s:TransformSetup(algorithm) | |
293 | let s:encode_algorithm = a:algorithm | |
294 | let &opfunc = matchstr(expand('<sfile>'), '<SNR>\d\+_').'TransformOpfunc' | |
295 | endfunction | |
296 | ||
297 | function! s:MapTransform(algorithm, key) | |
298 | exe 'nnoremap <silent> <Plug>unimpaired' .a:algorithm.' :<C-U>call <SID>TransformSetup("'.a:algorithm.'")<CR>g@' | |
299 | exe 'xnoremap <silent> <Plug>unimpaired' .a:algorithm.' :<C-U>call <SID>Transform("'.a:algorithm.'",visualmode())<CR>' | |
300 | exe 'nnoremap <silent> <Plug>unimpairedLine'.a:algorithm.' :<C-U>call <SID>Transform("'.a:algorithm.'",v:count1)<CR>' | |
301 | exe 'nmap '.a:key.' <Plug>unimpaired'.a:algorithm | |
302 | exe 'xmap '.a:key.' <Plug>unimpaired'.a:algorithm | |
303 | exe 'nmap '.a:key.a:key[strlen(a:key)-1].' <Plug>unimpairedLine'.a:algorithm | |
304 | endfunction | |
305 | ||
306 | call s:MapTransform('StringEncode','[y') | |
307 | call s:MapTransform('StringDecode',']y') | |
308 | call s:MapTransform('UrlEncode','[u') | |
309 | call s:MapTransform('UrlDecode',']u') | |
310 | call s:MapTransform('XmlEncode','[x') | |
311 | call s:MapTransform('XmlDecode',']x') | |
312 | ||
313 | " }}}1 | |
314 | ||
315 | " vim:set sw=2 sts=2: |