]>
Commit | Line | Data |
---|---|---|
1 | " Author: | |
2 | " Original: Gergely Kontra <kgergely@mcl.hu> | |
3 | " Current: Eric Van Dewoestine <ervandew@gmail.com> (as of version 0.4) | |
4 | " Please direct all correspondence to Eric. | |
5 | " Version: 1.6 | |
6 | " GetLatestVimScripts: 1643 1 :AutoInstall: supertab.vim | |
7 | " | |
8 | " Description: {{{ | |
9 | " Use your tab key to do all your completion in insert mode! | |
10 | " You can cycle forward and backward with the <Tab> and <S-Tab> keys | |
11 | " Note: you must press <Tab> once to be able to cycle back | |
12 | " | |
13 | " http://www.vim.org/scripts/script.php?script_id=1643 | |
14 | " }}} | |
15 | " | |
16 | " License: {{{ | |
17 | " Copyright (c) 2002 - 2011 | |
18 | " All rights reserved. | |
19 | " | |
20 | " Redistribution and use of this software in source and binary forms, with | |
21 | " or without modification, are permitted provided that the following | |
22 | " conditions are met: | |
23 | " | |
24 | " * Redistributions of source code must retain the above | |
25 | " copyright notice, this list of conditions and the | |
26 | " following disclaimer. | |
27 | " | |
28 | " * Redistributions in binary form must reproduce the above | |
29 | " copyright notice, this list of conditions and the | |
30 | " following disclaimer in the documentation and/or other | |
31 | " materials provided with the distribution. | |
32 | " | |
33 | " * Neither the name of Gergely Kontra or Eric Van Dewoestine nor the names | |
34 | " of its contributors may be used to endorse or promote products derived | |
35 | " from this software without specific prior written permission of Gergely | |
36 | " Kontra or Eric Van Dewoestine. | |
37 | " | |
38 | " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
39 | " IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
40 | " THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
41 | " PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
42 | " CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
43 | " EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
44 | " PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
45 | " PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
46 | " LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
47 | " NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
48 | " SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
49 | " }}} | |
50 | " | |
51 | " Testing Info: {{{ | |
52 | " Running vim + supertab with the absolute bar minimum settings: | |
53 | " $ vim -u NONE -U NONE -c "set nocp | runtime plugin/supertab.vim" | |
54 | " }}} | |
55 | ||
56 | if v:version < 700 | |
57 | finish | |
58 | endif | |
59 | ||
60 | if exists('complType') " Integration with other completion functions. | |
61 | finish | |
62 | endif | |
63 | ||
64 | let s:save_cpo=&cpo | |
65 | set cpo&vim | |
66 | ||
67 | " Global Variables {{{ | |
68 | ||
69 | if !exists("g:SuperTabDefaultCompletionType") | |
70 | let g:SuperTabDefaultCompletionType = "<c-p>" | |
71 | endif | |
72 | ||
73 | if !exists("g:SuperTabContextDefaultCompletionType") | |
74 | let g:SuperTabContextDefaultCompletionType = "<c-p>" | |
75 | endif | |
76 | ||
77 | if !exists("g:SuperTabCompletionContexts") | |
78 | let g:SuperTabCompletionContexts = ['s:ContextText'] | |
79 | endif | |
80 | ||
81 | if !exists("g:SuperTabRetainCompletionDuration") | |
82 | let g:SuperTabRetainCompletionDuration = 'insert' | |
83 | endif | |
84 | ||
85 | if !exists("g:SuperTabNoCompleteBefore") | |
86 | " retain backwards compatability | |
87 | if exists("g:SuperTabMidWordCompletion") && !g:SuperTabMidWordCompletion | |
88 | let g:SuperTabNoCompleteBefore = ['\k'] | |
89 | else | |
90 | let g:SuperTabNoCompleteBefore = [] | |
91 | endif | |
92 | endif | |
93 | ||
94 | if !exists("g:SuperTabNoCompleteAfter") | |
95 | " retain backwards compatability | |
96 | if exists("g:SuperTabLeadingSpaceCompletion") && g:SuperTabLeadingSpaceCompletion | |
97 | let g:SuperTabNoCompleteAfter = [] | |
98 | else | |
99 | let g:SuperTabNoCompleteAfter = ['\s'] | |
100 | endif | |
101 | endif | |
102 | ||
103 | if !exists("g:SuperTabMappingForward") | |
104 | let g:SuperTabMappingForward = '<tab>' | |
105 | endif | |
106 | if !exists("g:SuperTabMappingBackward") | |
107 | let g:SuperTabMappingBackward = '<s-tab>' | |
108 | endif | |
109 | ||
110 | if !exists("g:SuperTabMappingTabLiteral") | |
111 | let g:SuperTabMappingTabLiteral = '<c-tab>' | |
112 | endif | |
113 | ||
114 | if !exists("g:SuperTabLongestEnhanced") | |
115 | let g:SuperTabLongestEnhanced = 0 | |
116 | endif | |
117 | ||
118 | if !exists("g:SuperTabLongestHighlight") | |
119 | let g:SuperTabLongestHighlight = 0 | |
120 | endif | |
121 | ||
122 | if !exists("g:SuperTabCrMapping") | |
123 | let g:SuperTabCrMapping = 1 | |
124 | endif | |
125 | ||
126 | " }}} | |
127 | ||
128 | " Script Variables {{{ | |
129 | ||
130 | " construct the help text. | |
131 | let s:tabHelp = | |
132 | \ "Hit <CR> or CTRL-] on the completion type you wish to switch to.\n" . | |
133 | \ "Use :help ins-completion for more information.\n" . | |
134 | \ "\n" . | |
135 | \ "|<c-n>| - Keywords in 'complete' searching down.\n" . | |
136 | \ "|<c-p>| - Keywords in 'complete' searching up (SuperTab default).\n" . | |
137 | \ "|<c-x><c-l>| - Whole lines.\n" . | |
138 | \ "|<c-x><c-n>| - Keywords in current file.\n" . | |
139 | \ "|<c-x><c-k>| - Keywords in 'dictionary'.\n" . | |
140 | \ "|<c-x><c-t>| - Keywords in 'thesaurus', thesaurus-style.\n" . | |
141 | \ "|<c-x><c-i>| - Keywords in the current and included files.\n" . | |
142 | \ "|<c-x><c-]>| - Tags.\n" . | |
143 | \ "|<c-x><c-f>| - File names.\n" . | |
144 | \ "|<c-x><c-d>| - Definitions or macros.\n" . | |
145 | \ "|<c-x><c-v>| - Vim command-line.\n" . | |
146 | \ "|<c-x><c-u>| - User defined completion.\n" . | |
147 | \ "|<c-x><c-o>| - Omni completion.\n" . | |
148 | \ "|<c-x>s| - Spelling suggestions." | |
149 | ||
150 | " set the available completion types and modes. | |
151 | let s:types = | |
152 | \ "\<c-e>\<c-y>\<c-l>\<c-n>\<c-k>\<c-t>\<c-i>\<c-]>" . | |
153 | \ "\<c-f>\<c-d>\<c-v>\<c-n>\<c-p>\<c-u>\<c-o>\<c-n>\<c-p>s" | |
154 | let s:modes = '/^E/^Y/^L/^N/^K/^T/^I/^]/^F/^D/^V/^P/^U/^O/s' | |
155 | let s:types = s:types . "np" | |
156 | let s:modes = s:modes . '/n/p' | |
157 | ||
158 | " }}} | |
159 | ||
160 | " SuperTabSetDefaultCompletionType(type) {{{ | |
161 | " Globally available function that users can use to set the default | |
162 | " completion type for the current buffer, like in an ftplugin. | |
163 | function! SuperTabSetDefaultCompletionType(type) | |
164 | " init hack for <c-x><c-v> workaround. | |
165 | let b:complCommandLine = 0 | |
166 | ||
167 | let b:SuperTabDefaultCompletionType = a:type | |
168 | ||
169 | " set the current completion type to the default | |
170 | call SuperTabSetCompletionType(b:SuperTabDefaultCompletionType) | |
171 | endfunction " }}} | |
172 | ||
173 | " SuperTabSetCompletionType(type) {{{ | |
174 | " Globally available function that users can use to create mappings to quickly | |
175 | " switch completion modes. Useful when a user wants to restore the default or | |
176 | " switch to another mode without having to kick off a completion of that type | |
177 | " or use SuperTabHelp. Note, this function only changes the current | |
178 | " completion type, not the default, meaning that the default will still be | |
179 | " restored once the configured retension duration has been met (see | |
180 | " g:SuperTabRetainCompletionDuration). To change the default for the current | |
181 | " buffer, use SuperTabDefaultCompletionType(type) instead. Example mapping to | |
182 | " restore SuperTab default: | |
183 | " nmap <F6> :call SetSuperTabCompletionType("<c-p>")<cr> | |
184 | function! SuperTabSetCompletionType(type) | |
185 | call s:InitBuffer() | |
186 | exec "let b:complType = \"" . escape(a:type, '<') . "\"" | |
187 | endfunction " }}} | |
188 | ||
189 | " SuperTabAlternateCompletion(type) {{{ | |
190 | " Function which can be mapped to a key to kick off an alternate completion | |
191 | " other than the default. For instance, if you have 'context' as the default | |
192 | " and want to map ctrl+space to issue keyword completion. | |
193 | " Note: due to the way vim expands ctrl characters in mappings, you cannot | |
194 | " create the alternate mapping like so: | |
195 | " imap <c-space> <c-r>=SuperTabAlternateCompletion("<c-p>")<cr> | |
196 | " instead, you have to use \<lt> to prevent vim from expanding the key | |
197 | " when creating the mapping. | |
198 | " gvim: | |
199 | " imap <c-space> <c-r>=SuperTabAlternateCompletion("\<lt>c-p>")<cr> | |
200 | " console: | |
201 | " imap <nul> <c-r>=SuperTabAlternateCompletion("\<lt>c-p>")<cr> | |
202 | function! SuperTabAlternateCompletion(type) | |
203 | call SuperTabSetCompletionType(a:type) | |
204 | " end any current completion before attempting to start the new one. | |
205 | " use feedkeys to prevent possible remapping of <c-e> from causing issues. | |
206 | "call feedkeys("\<c-e>", 'n') | |
207 | " ^ since we can't detect completion mode vs regular insert mode, we force | |
208 | " vim into keyword completion mode and end that mode to prevent the regular | |
209 | " insert behavior of <c-e> from occurring. | |
210 | call feedkeys("\<c-x>\<c-p>\<c-e>", 'n') | |
211 | call feedkeys(b:complType, 'n') | |
212 | return '' | |
213 | endfunction " }}} | |
214 | ||
215 | " SuperTabLongestHighlight(dir) {{{ | |
216 | " When longest highlight is enabled, this function is used to do the actual | |
217 | " selection of the completion popup entry. | |
218 | function! SuperTabLongestHighlight(dir) | |
219 | if !pumvisible() | |
220 | return '' | |
221 | endif | |
222 | return a:dir == -1 ? "\<up>" : "\<down>" | |
223 | endfunction " }}} | |
224 | ||
225 | " s:Init {{{ | |
226 | " Global initilization when supertab is loaded. | |
227 | function! s:Init() | |
228 | " Setup mechanism to restore original completion type upon leaving insert | |
229 | " mode if configured to do so | |
230 | if g:SuperTabRetainCompletionDuration == 'insert' | |
231 | augroup supertab_retain | |
232 | autocmd! | |
233 | autocmd InsertLeave * call s:SetDefaultCompletionType() | |
234 | augroup END | |
235 | endif | |
236 | endfunction " }}} | |
237 | ||
238 | " s:InitBuffer {{{ | |
239 | " Per buffer initilization. | |
240 | function! s:InitBuffer() | |
241 | if exists('b:SuperTabNoCompleteBefore') | |
242 | return | |
243 | endif | |
244 | ||
245 | let b:complReset = 0 | |
246 | let b:complTypeManual = !exists('b:complTypeManual') ? '' : b:complTypeManual | |
247 | let b:complTypeContext = '' | |
248 | ||
249 | " init hack for <c-x><c-v> workaround. | |
250 | let b:complCommandLine = 0 | |
251 | ||
252 | if !exists('b:SuperTabNoCompleteBefore') | |
253 | let b:SuperTabNoCompleteBefore = g:SuperTabNoCompleteBefore | |
254 | endif | |
255 | if !exists('b:SuperTabNoCompleteAfter') | |
256 | let b:SuperTabNoCompleteAfter = g:SuperTabNoCompleteAfter | |
257 | endif | |
258 | ||
259 | let b:SuperTabDefaultCompletionType = g:SuperTabDefaultCompletionType | |
260 | ||
261 | " set the current completion type to the default | |
262 | call SuperTabSetCompletionType(b:SuperTabDefaultCompletionType) | |
263 | endfunction " }}} | |
264 | ||
265 | " s:ManualCompletionEnter() {{{ | |
266 | " Handles manual entrance into completion mode. | |
267 | function! s:ManualCompletionEnter() | |
268 | if &smd | |
269 | echo '' | echohl ModeMsg | echo '-- ^X++ mode (' . s:modes . ')' | echohl None | |
270 | endif | |
271 | let complType = nr2char(getchar()) | |
272 | if stridx(s:types, complType) != -1 | |
273 | if stridx("\<c-e>\<c-y>", complType) != -1 " no memory, just scroll... | |
274 | return "\<c-x>" . complType | |
275 | elseif stridx('np', complType) != -1 | |
276 | let complType = nr2char(char2nr(complType) - 96) | |
277 | else | |
278 | let complType = "\<c-x>" . complType | |
279 | endif | |
280 | ||
281 | let b:complTypeManual = complType | |
282 | ||
283 | if index(['insert', 'session'], g:SuperTabRetainCompletionDuration) != -1 | |
284 | let b:complType = complType | |
285 | endif | |
286 | ||
287 | " Hack to workaround bug when invoking command line completion via <c-r>= | |
288 | if complType == "\<c-x>\<c-v>" | |
289 | return s:CommandLineCompletion() | |
290 | endif | |
291 | ||
292 | " optionally enable enhanced longest completion | |
293 | if g:SuperTabLongestEnhanced && &completeopt =~ 'longest' | |
294 | call s:EnableLongestEnhancement() | |
295 | endif | |
296 | ||
297 | if g:SuperTabLongestHighlight && | |
298 | \ &completeopt =~ 'longest' && | |
299 | \ &completeopt =~ 'menu' && | |
300 | \ !pumvisible() | |
301 | let dir = (complType == "\<c-x>\<c-p>") ? -1 : 1 | |
302 | call feedkeys("\<c-r>=SuperTabLongestHighlight(" . dir . ")\<cr>", 'n') | |
303 | endif | |
304 | ||
305 | return complType | |
306 | endif | |
307 | ||
308 | echohl "Unknown mode" | |
309 | return complType | |
310 | endfunction " }}} | |
311 | ||
312 | " s:SetCompletionType() {{{ | |
313 | " Sets the completion type based on what the user has chosen from the help | |
314 | " buffer. | |
315 | function! s:SetCompletionType() | |
316 | let chosen = substitute(getline('.'), '.*|\(.*\)|.*', '\1', '') | |
317 | if chosen != getline('.') | |
318 | let winnr = b:winnr | |
319 | close | |
320 | exec winnr . 'winc w' | |
321 | call SuperTabSetCompletionType(chosen) | |
322 | endif | |
323 | endfunction " }}} | |
324 | ||
325 | " s:SetDefaultCompletionType() {{{ | |
326 | function! s:SetDefaultCompletionType() | |
327 | if exists('b:SuperTabDefaultCompletionType') && | |
328 | \ (!exists('b:complCommandLine') || !b:complCommandLine) | |
329 | call SuperTabSetCompletionType(b:SuperTabDefaultCompletionType) | |
330 | endif | |
331 | endfunction " }}} | |
332 | ||
333 | " s:SuperTab(command) {{{ | |
334 | " Used to perform proper cycle navigation as the user requests the next or | |
335 | " previous entry in a completion list, and determines whether or not to simply | |
336 | " retain the normal usage of <tab> based on the cursor position. | |
337 | function! s:SuperTab(command) | |
338 | if exists('b:SuperTabDisabled') && b:SuperTabDisabled | |
339 | return "\<tab>" | |
340 | endif | |
341 | ||
342 | call s:InitBuffer() | |
343 | ||
344 | if s:WillComplete() | |
345 | " optionally enable enhanced longest completion | |
346 | if g:SuperTabLongestEnhanced && &completeopt =~ 'longest' | |
347 | call s:EnableLongestEnhancement() | |
348 | endif | |
349 | ||
350 | if !pumvisible() | |
351 | let b:complTypeManual = '' | |
352 | endif | |
353 | ||
354 | " exception: if in <c-p> mode, then <c-n> should move up the list, and | |
355 | " <c-p> down the list. | |
356 | if a:command == 'p' && !b:complReset && | |
357 | \ (b:complType == "\<c-p>" || | |
358 | \ (b:complType == 'context' && | |
359 | \ b:complTypeManual == '' && | |
360 | \ b:complTypeContext == "\<c-p>")) | |
361 | return "\<c-n>" | |
362 | ||
363 | elseif a:command == 'p' && !b:complReset && | |
364 | \ (b:complType == "\<c-n>" || | |
365 | \ (b:complType == 'context' && | |
366 | \ b:complTypeManual == '' && | |
367 | \ b:complTypeContext == "\<c-n>")) | |
368 | return "\<c-p>" | |
369 | ||
370 | " already in completion mode and not resetting for longest enhancement, so | |
371 | " just scroll to next/previous | |
372 | elseif pumvisible() && !b:complReset | |
373 | let type = b:complType == 'context' ? b:complTypeContext : b:complType | |
374 | if a:command == 'n' | |
375 | return type == "\<c-p>" ? "\<c-p>" : "\<c-n>" | |
376 | endif | |
377 | return type == "\<c-p>" ? "\<c-n>" : "\<c-p>" | |
378 | endif | |
379 | ||
380 | " handle 'context' completion. | |
381 | if b:complType == 'context' | |
382 | let complType = s:ContextCompletion() | |
383 | if complType == '' | |
384 | exec "let complType = \"" . | |
385 | \ escape(g:SuperTabContextDefaultCompletionType, '<') . "\"" | |
386 | endif | |
387 | let b:complTypeContext = complType | |
388 | ||
389 | " Hack to workaround bug when invoking command line completion via <c-r>= | |
390 | elseif b:complType == "\<c-x>\<c-v>" | |
391 | let complType = s:CommandLineCompletion() | |
392 | else | |
393 | let complType = b:complType | |
394 | endif | |
395 | ||
396 | " highlight first result if longest enabled | |
397 | if g:SuperTabLongestHighlight && | |
398 | \ &completeopt =~ 'longest' && | |
399 | \ &completeopt =~ 'menu' && | |
400 | \ (!pumvisible() || b:complReset) | |
401 | let dir = (complType == "\<c-p>") ? -1 : 1 | |
402 | call feedkeys("\<c-r>=SuperTabLongestHighlight(" . dir . ")\<cr>", 'n') | |
403 | endif | |
404 | ||
405 | if b:complReset | |
406 | let b:complReset = 0 | |
407 | " not an accurate condition for everyone, but better than sending <c-e> | |
408 | " at the wrong time. | |
409 | if pumvisible() | |
410 | return "\<c-e>" . complType | |
411 | endif | |
412 | endif | |
413 | ||
414 | return complType | |
415 | endif | |
416 | ||
417 | return "\<tab>" | |
418 | endfunction " }}} | |
419 | ||
420 | " s:SuperTabHelp() {{{ | |
421 | " Opens a help window where the user can choose a completion type to enter. | |
422 | function! s:SuperTabHelp() | |
423 | let winnr = winnr() | |
424 | if bufwinnr("SuperTabHelp") == -1 | |
425 | botright split SuperTabHelp | |
426 | ||
427 | setlocal noswapfile | |
428 | setlocal buftype=nowrite | |
429 | setlocal bufhidden=delete | |
430 | ||
431 | let saved = @" | |
432 | let @" = s:tabHelp | |
433 | silent put | |
434 | call cursor(1, 1) | |
435 | silent 1,delete | |
436 | call cursor(4, 1) | |
437 | let @" = saved | |
438 | exec "resize " . line('$') | |
439 | ||
440 | syntax match Special "|.\{-}|" | |
441 | ||
442 | setlocal readonly | |
443 | setlocal nomodifiable | |
444 | ||
445 | nmap <silent> <buffer> <cr> :call <SID>SetCompletionType()<cr> | |
446 | nmap <silent> <buffer> <c-]> :call <SID>SetCompletionType()<cr> | |
447 | else | |
448 | exec bufwinnr("SuperTabHelp") . "winc w" | |
449 | endif | |
450 | let b:winnr = winnr | |
451 | endfunction " }}} | |
452 | ||
453 | " s:WillComplete() {{{ | |
454 | " Determines if completion should be kicked off at the current location. | |
455 | function! s:WillComplete() | |
456 | if pumvisible() | |
457 | return 1 | |
458 | endif | |
459 | ||
460 | let line = getline('.') | |
461 | let cnum = col('.') | |
462 | ||
463 | " Start of line. | |
464 | if line =~ '^\s*\%' . cnum . 'c' | |
465 | return 0 | |
466 | endif | |
467 | ||
468 | " honor SuperTabNoCompleteAfter | |
469 | let pre = line[:cnum - 2] | |
470 | for pattern in b:SuperTabNoCompleteAfter | |
471 | if pre =~ pattern . '$' | |
472 | return 0 | |
473 | endif | |
474 | endfor | |
475 | ||
476 | " honor SuperTabNoCompleteBefore | |
477 | " Within a word, but user does not have mid word completion enabled. | |
478 | let post = line[cnum - 1:] | |
479 | for pattern in b:SuperTabNoCompleteBefore | |
480 | if post =~ '^' . pattern | |
481 | return 0 | |
482 | endif | |
483 | endfor | |
484 | ||
485 | return 1 | |
486 | endfunction " }}} | |
487 | ||
488 | " s:EnableLongestEnhancement() {{{ | |
489 | function! s:EnableLongestEnhancement() | |
490 | augroup supertab_reset | |
491 | autocmd! | |
492 | autocmd InsertLeave,CursorMovedI <buffer> | |
493 | \ call s:ReleaseKeyPresses() | autocmd! supertab_reset | |
494 | augroup END | |
495 | call s:CaptureKeyPresses() | |
496 | endfunction " }}} | |
497 | ||
498 | " s:CompletionReset(char) {{{ | |
499 | function! s:CompletionReset(char) | |
500 | let b:complReset = 1 | |
501 | return a:char | |
502 | endfunction " }}} | |
503 | ||
504 | " s:CaptureKeyPresses() {{{ | |
505 | function! s:CaptureKeyPresses() | |
506 | if !exists('b:capturing') || !b:capturing | |
507 | let b:capturing = 1 | |
508 | " save any previous mappings | |
509 | " TODO: capture additional info provided by vim 7.3.032 and up. | |
510 | let b:captured = { | |
511 | \ '<bs>': maparg('<bs>', 'i'), | |
512 | \ '<c-h>': maparg('<c-h>', 'i'), | |
513 | \ } | |
514 | " TODO: use &keyword to get an accurate list of chars to map | |
515 | for c in split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_', '.\zs') | |
516 | exec 'imap <buffer> ' . c . ' <c-r>=<SID>CompletionReset("' . c . '")<cr>' | |
517 | endfor | |
518 | imap <buffer> <bs> <c-r>=<SID>CompletionReset("\<lt>bs>")<cr> | |
519 | imap <buffer> <c-h> <c-r>=<SID>CompletionReset("\<lt>c-h>")<cr> | |
520 | endif | |
521 | endfunction " }}} | |
522 | ||
523 | " s:ReleaseKeyPresses() {{{ | |
524 | function! s:ReleaseKeyPresses() | |
525 | if exists('b:capturing') && b:capturing | |
526 | let b:capturing = 0 | |
527 | for c in split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_', '.\zs') | |
528 | exec 'iunmap <buffer> ' . c | |
529 | endfor | |
530 | ||
531 | iunmap <buffer> <bs> | |
532 | iunmap <buffer> <c-h> | |
533 | ||
534 | " restore any previous mappings | |
535 | for [key, rhs] in items(b:captured) | |
536 | if rhs != '' | |
537 | let args = substitute(rhs, '.*\(".\{-}"\).*', '\1', '') | |
538 | if args != rhs | |
539 | let args = substitute(args, '<', '<lt>', 'g') | |
540 | let expr = substitute(rhs, '\(.*\)".\{-}"\(.*\)', '\1%s\2', '') | |
541 | let rhs = printf(expr, args) | |
542 | endif | |
543 | exec printf("imap <silent> %s %s", key, rhs) | |
544 | endif | |
545 | endfor | |
546 | unlet b:captured | |
547 | ||
548 | if mode() == 'i' && &completeopt =~ 'menu' | |
549 | " force full exit from completion mode (don't exit insert mode since | |
550 | " that will break repeating with '.') | |
551 | call feedkeys("\<space>\<bs>", 'n') | |
552 | endif | |
553 | endif | |
554 | endfunction " }}} | |
555 | ||
556 | " s:CommandLineCompletion() {{{ | |
557 | " Hack needed to account for apparent bug in vim command line mode completion | |
558 | " when invoked via <c-r>= | |
559 | function! s:CommandLineCompletion() | |
560 | " This hack will trigger InsertLeave which will then invoke | |
561 | " s:SetDefaultCompletionType. To prevent default completion from being | |
562 | " restored prematurely, set an internal flag for s:SetDefaultCompletionType | |
563 | " to check for. | |
564 | let b:complCommandLine = 1 | |
565 | return "\<c-\>\<c-o>:call feedkeys('\<c-x>\<c-v>\<c-v>', 'n') | " . | |
566 | \ "let b:complCommandLine = 0\<cr>" | |
567 | endfunction " }}} | |
568 | ||
569 | " s:ContextCompletion() {{{ | |
570 | function! s:ContextCompletion() | |
571 | let contexts = exists('b:SuperTabCompletionContexts') ? | |
572 | \ b:SuperTabCompletionContexts : g:SuperTabCompletionContexts | |
573 | ||
574 | for context in contexts | |
575 | try | |
576 | let Context = function(context) | |
577 | let complType = Context() | |
578 | unlet Context | |
579 | if type(complType) == 1 && complType != '' | |
580 | return complType | |
581 | endif | |
582 | catch /E700/ | |
583 | echohl Error | |
584 | echom 'supertab: no context function "' . context . '" found.' | |
585 | echohl None | |
586 | endtry | |
587 | endfor | |
588 | return '' | |
589 | endfunction " }}} | |
590 | ||
591 | " s:ContextDiscover() {{{ | |
592 | function! s:ContextDiscover() | |
593 | let discovery = exists('g:SuperTabContextDiscoverDiscovery') ? | |
594 | \ g:SuperTabContextDiscoverDiscovery : [] | |
595 | ||
596 | " loop through discovery list to find the default | |
597 | if !empty(discovery) | |
598 | for pair in discovery | |
599 | let var = substitute(pair, '\(.*\):.*', '\1', '') | |
600 | let type = substitute(pair, '.*:\(.*\)', '\1', '') | |
601 | exec 'let value = ' . var | |
602 | if value !~ '^\s*$' && value != '0' | |
603 | exec "let complType = \"" . escape(type, '<') . "\"" | |
604 | return complType | |
605 | endif | |
606 | endfor | |
607 | endif | |
608 | endfunction " }}} | |
609 | ||
610 | " s:ContextText() {{{ | |
611 | function! s:ContextText() | |
612 | let exclusions = exists('g:SuperTabContextTextFileTypeExclusions') ? | |
613 | \ g:SuperTabContextTextFileTypeExclusions : [] | |
614 | ||
615 | if index(exclusions, &ft) == -1 | |
616 | let curline = getline('.') | |
617 | let cnum = col('.') | |
618 | let synname = synIDattr(synID(line('.'), cnum - 1, 1), 'name') | |
619 | if curline =~ '.*/\w*\%' . cnum . 'c' || | |
620 | \ ((has('win32') || has('win64')) && curline =~ '.*\\\w*\%' . cnum . 'c') | |
621 | return "\<c-x>\<c-f>" | |
622 | ||
623 | elseif curline =~ '.*\(\w\|[\])]\)\(\.\|::\|->\)\w*\%' . cnum . 'c' && | |
624 | \ synname !~ '\(String\|Comment\)' | |
625 | let omniPrecedence = exists('g:SuperTabContextTextOmniPrecedence') ? | |
626 | \ g:SuperTabContextTextOmniPrecedence : ['&completefunc', '&omnifunc'] | |
627 | ||
628 | for omniFunc in omniPrecedence | |
629 | if omniFunc !~ '^&' | |
630 | let omniFunc = '&' . omniFunc | |
631 | endif | |
632 | if getbufvar(bufnr('%'), omniFunc) != '' | |
633 | return omniFunc == '&omnifunc' ? "\<c-x>\<c-o>" : "\<c-x>\<c-u>" | |
634 | endif | |
635 | endfor | |
636 | endif | |
637 | endif | |
638 | endfunction " }}} | |
639 | ||
640 | " s:ExpandMap(map) {{{ | |
641 | function! s:ExpandMap(map) | |
642 | let map = a:map | |
643 | if map =~ '<Plug>' | |
644 | let plug = substitute(map, '.\{-}\(<Plug>\w\+\).*', '\1', '') | |
645 | let plug_map = maparg(plug, 'i') | |
646 | let map = substitute(map, '.\{-}\(<Plug>\w\+\).*', plug_map, '') | |
647 | endif | |
648 | return map | |
649 | endfunction " }}} | |
650 | ||
651 | " Key Mappings {{{ | |
652 | " map a regular tab to ctrl-tab (note: doesn't work in console vim) | |
653 | exec 'inoremap ' . g:SuperTabMappingTabLiteral . ' <tab>' | |
654 | ||
655 | imap <c-x> <c-r>=<SID>ManualCompletionEnter()<cr> | |
656 | ||
657 | imap <script> <Plug>SuperTabForward <c-r>=<SID>SuperTab('n')<cr> | |
658 | imap <script> <Plug>SuperTabBackward <c-r>=<SID>SuperTab('p')<cr> | |
659 | ||
660 | exec 'imap ' . g:SuperTabMappingForward . ' <Plug>SuperTabForward' | |
661 | exec 'imap ' . g:SuperTabMappingBackward . ' <Plug>SuperTabBackward' | |
662 | ||
663 | " After hitting <Tab>, hitting it once more will go to next match | |
664 | " (because in XIM mode <c-n> and <c-p> mappings are ignored) | |
665 | " and wont start a brand new completion | |
666 | " The side effect, that in the beginning of line <c-n> and <c-p> inserts a | |
667 | " <Tab>, but I hope it may not be a problem... | |
668 | let ctrl_n = maparg('<c-n>', 'i') | |
669 | if ctrl_n != '' | |
670 | let ctrl_n = substitute(ctrl_n, '<', '<lt>', 'g') | |
671 | exec 'imap <c-n> <c-r>=<SID>ForwardBack("n", "' . ctrl_n . '")<cr>' | |
672 | else | |
673 | imap <c-n> <Plug>SuperTabForward | |
674 | endif | |
675 | let ctrl_p = maparg('<c-p>', 'i') | |
676 | if ctrl_p != '' | |
677 | let ctrl_p = substitute(ctrl_p, '<', '<lt>', 'g') | |
678 | exec 'imap <c-p> <c-r>=<SID>ForwardBack("p", "' . ctrl_p . '")<cr>' | |
679 | else | |
680 | imap <c-p> <Plug>SuperTabBackward | |
681 | endif | |
682 | function! s:ForwardBack(command, map) | |
683 | exec "let map = \"" . escape(a:map, '<') . "\"" | |
684 | return pumvisible() ? s:SuperTab(a:command) : map | |
685 | endfunction | |
686 | ||
687 | if g:SuperTabCrMapping | |
688 | if maparg('<CR>','i') =~ '<CR>' | |
689 | let map = maparg('<cr>', 'i') | |
690 | let cr = (map =~? '\(^\|[^)]\)<cr>') | |
691 | let map = s:ExpandMap(map) | |
692 | exec "inoremap <script> <cr> <c-r>=<SID>SelectCompletion(" . cr . ")<cr>" . map | |
693 | else | |
694 | inoremap <cr> <c-r>=<SID>SelectCompletion(1)<cr> | |
695 | endif | |
696 | function! s:SelectCompletion(cr) | |
697 | " selecting a completion | |
698 | if pumvisible() | |
699 | " ugly hack to let other <cr> mappings for other plugins cooperate | |
700 | " with supertab | |
701 | let b:supertab_pumwasvisible = 1 | |
702 | return "\<c-y>" | |
703 | endif | |
704 | ||
705 | " only needed when chained with other mappings and one of them will | |
706 | " issue a <cr>. | |
707 | if exists('b:supertab_pumwasvisible') && !a:cr | |
708 | unlet b:supertab_pumwasvisible | |
709 | return '' | |
710 | endif | |
711 | ||
712 | " not so pleasant hack to keep <cr> working for abbreviations | |
713 | let word = substitute(getline('.'), '^.*\s\+\(.*\%' . col('.') . 'c\).*', '\1', '') | |
714 | if maparg(word, 'i', 1) != '' | |
715 | call feedkeys("\<c-]>", 't') | |
716 | call feedkeys("\<cr>", 'n') | |
717 | return '' | |
718 | endif | |
719 | ||
720 | " only return a cr if nothing else is mapped to it since we don't want | |
721 | " to duplicate a cr returned by another mapping. | |
722 | return a:cr ? "\<cr>" : "" | |
723 | endfunction | |
724 | endif | |
725 | " }}} | |
726 | ||
727 | " Command Mappings {{{ | |
728 | if !exists(":SuperTabHelp") | |
729 | command SuperTabHelp :call <SID>SuperTabHelp() | |
730 | endif | |
731 | " }}} | |
732 | ||
733 | call s:Init() | |
734 | ||
735 | let &cpo = s:save_cpo | |
736 | ||
737 | " vim:ft=vim:fdm=marker |