Created
December 18, 2008 06:05
-
-
Save Shougo/37405 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" FILE: altautocomplpop.vim | |
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com> | |
" Last Modified: 18 Dec 2008 | |
" Usage: Just source this file. | |
" LICENSE: No Warranties. Use at your own risk. Add stuff to taste. | |
" If you like this script type :help uganda<Enter> | |
" If you want to show appreciation to the author, please | |
" visit the UDAVUM KARANGAL website http://www.udavumkarangal.org/ | |
" NOTES: Written to work with vim-7.0 | |
if exists('g:loaded_altautocomplpop') | |
finish | |
endif | |
let g:loaded_altautocomplpop = 1 | |
" Global variable definition | |
if !exists("g:AltAutoComplPop_MaxList") | |
let g:AltAutoComplPop_MaxList = 150 | |
endif | |
if !exists("g:AltAutoComplPop_MaxKeywordWidth") | |
let g:AltAutoComplPop_MaxKeywordWidth = 50 | |
endif | |
if !exists("g:AltAutoComplPop_MaxFilenameWidth") | |
let g:AltAutoComplPop_MaxFilenameWidth = 20 | |
endif | |
if !exists("g:AltAutoComplPop_PartialMatch") | |
let g:AltAutoComplPop_PartialMatch = 1 | |
endif | |
if !exists("g:AltAutoComplPop_StartCharLength") | |
let g:AltAutoComplPop_StartCharLength = 2 | |
endif | |
if !exists("g:AltAutoComplPop_IgnoreCase") | |
let g:AltAutoComplPop_IgnoreCase = 1 | |
endif | |
let s:disable_altautocomplpop = 1 | |
command! -nargs=0 AltAutoComplPopEnable call s:AltAutoComplPop.Enable() | |
command! -nargs=0 AltAutoComplPopDisable call s:AltAutoComplPop.Disable() | |
command! -nargs=0 AltAutoComplPopToggle call s:AltAutoComplPop.Toggle() | |
let s:AltAutoComplPop = {} | |
function! s:AltAutoComplPop.Complete() | |
if pumvisible() || &paste | |
return | |
endif | |
" Prevent multiplex call | |
if s:complete_lock | |
return | |
endif | |
" Get cursor word | |
let l:cur = col('.') - 1 | |
let l:cur_text = strpart(getline('.'), 0, l:cur) | |
" Prevent infinity loop | |
if l:cur_text == s:old_text | |
return | |
endif | |
let s:old_text = l:cur_text | |
" Not complete multi byte character | |
if char2nr(l:cur_text[l:cur-1]) >= 0x80 | |
return | |
endif | |
let l:pattern = '\k\{'. g:AltAutoComplPop_StartCharLength .',}$' | |
let l:cur_keyword_pos = match(l:cur_text, l:pattern) | |
if l:cur_keyword_pos < 0 | |
return | |
endif | |
" Save options | |
let s:ignorecase_save = &l:ignorecase | |
" Extract complete words | |
let &l:ignorecase = g:AltAutoComplPop_IgnoreCase | |
let l:cur_keyword_str = matchstr(l:cur_text, l:pattern) | |
let s:complete_words = s:AltAutoComplPop.ExtractComplete(l:cur_keyword_str) | |
" Prevent filcker | |
if empty(s:complete_words) | |
return | |
endif | |
" Lock | |
let s:complete_lock = 1 | |
" Original complete | |
let &l:completefunc = "g:AltAutoComplPop_AutoCompleteFunc" | |
let s:cur_keyword_pos = l:cur_keyword_pos | |
call feedkeys("\<C-x>\<C-u>\<C-p>", "n") | |
endfunction | |
function! g:AltAutoComplPop_AutoCompleteFunc(findstart, base) | |
if a:findstart | |
return s:cur_keyword_pos | |
endif | |
" Prevent multiplex call | |
if !s:complete_lock | |
return [] | |
endif | |
" Restore options | |
let &l:completefunc = "g:AltAutoComplPop_ManualCompleteFunc" | |
let &l:ignorecase = s:ignorecase_save | |
" Unlock | |
let s:complete_lock = 0 | |
return s:complete_words | |
endfunction | |
function! g:AltAutoComplPop_ManualCompleteFunc(findstart, base) | |
if a:findstart | |
" Get cursor word | |
let l:cur = col('.') - 1 | |
let l:cur_text = strpart(getline('.'), 0, l:cur) | |
" Prevent infinity loop | |
if l:cur_text == s:old_text | |
return | |
endif | |
let s:old_text = l:cur_text | |
" Not complete multi byte character | |
if char2nr(l:cur_text[l:cur-1]) >= 0x80 | |
return -1 | |
endif | |
let l:cur_keyword_pos = match(l:cur_text, '\k\+$') | |
return l:cur_keyword_pos | |
endif | |
" Save options | |
let l:ignorecase_save = &l:ignorecase | |
let &l:ignorecase = g:AltAutoComplPop_IgnoreCase | |
let l:complete_words = s:AltAutoComplPop.ExtractComplete(a:base) | |
" Restore options | |
let &l:ignorecase = l:ignorecase_save | |
return l:complete_words | |
endfunction | |
function! s:CompareRank(i1, i2) | |
return a:i1.rank == a:i2.rank ? 0 : a:i1.rank < a:i2.rank ? 1 : -1 | |
endfunction | |
function! s:AltAutoComplPop.ExtractComplete(cur_keyword_str) | |
" Keyword filter | |
if g:AltAutoComplPop_PartialMatch | |
" Partial match | |
let l:pattern = 'v:val.word =~ "' . a:cur_keyword_str . '"' | |
else | |
" Normal match | |
let l:pattern = 'v:val.word =~ "^' . a:cur_keyword_str . '"' | |
endif | |
let l:cache_keyword_filtered = filter(values(s:cache_keyword), l:pattern) | |
let l:cache_keyword_buffer_filtered = filter(values(s:cache_keyword_buffer), l:pattern) | |
" Sort | |
let l:cache_keyword_sorted = sort(l:cache_keyword_filtered, "s:CompareRank") | |
let l:cache_keyword_buffer_sorted = sort(l:cache_keyword_buffer_filtered, "s:CompareRank") | |
let l:ret = extend(l:cache_keyword_sorted, l:cache_keyword_buffer_sorted) | |
" Trunk too many item | |
return l:ret[:g:AltAutoComplPop_MaxList] | |
endfunction | |
let s:cache_keyword = {} | |
function! s:AltAutoComplPop.Caching() | |
let s:cache_keyword = {} | |
let l:max_line = line("$") | |
let l:line_num = 1 | |
while l:line_num <= l:max_line | |
let l:line = getline(line_num) | |
let l:match_num = match(l:line, '\k\+') | |
let l:match_str = matchstr(l:line, '\k\+') | |
while l:match_num >= 0 | |
" Check dup | |
if has_key(s:cache_keyword, l:match_str) | |
let s:cache_keyword[l:match_str].rank += 1 | |
" For debbuging | |
let s:cache_keyword[l:match_str].menu = printf(" %d", s:cache_keyword[l:match_str].rank) | |
else | |
" For debbuging | |
let l:menu = printf(" %d", 1) | |
let l:abbr = printf("%." . g:AltAutoComplPop_MaxKeywordWidth . "s", l:match_str) | |
let l:dict = {'word' : l:match_str, 'abbr' : l:abbr, 'menu' : l:menu, 'rank' : 1, 'dup' : 0} | |
" Append list | |
let s:cache_keyword[l:match_str] = l:dict | |
endif | |
" Next match | |
let l:match_num += len(l:match_str) | |
let l:match_num = match(l:line, '\k\+', l:match_num) | |
let l:match_str = matchstr(l:line, '\k\+', l:match_num) | |
endwhile | |
let l:line_num += 1 | |
endwhile | |
endfunction | |
let s:cache_keyword_buffer = {} | |
function! s:AltAutoComplPop.CachingBuffer() | |
let s:cache_keyword_buffer = {} | |
let l:bufnumber = 1 | |
let l:max_buf = bufnr("$") | |
while l:bufnumber <= l:max_buf | |
if buflisted(l:bufnumber) && l:bufnumber != bufnr("%") | |
let l:buflines = getbufline(l:bufnumber, 1, "$") | |
let l:max_line = len(l:buflines) | |
let l:line_num = 0 | |
while l:line_num < l:max_line | |
let l:line = buflines[l:line_num] | |
let l:match_num = match(l:line, '\k\+') | |
let l:match_str = matchstr(l:line, '\k\+') | |
while l:match_num >= 0 | |
" Check dup | |
if has_key(s:cache_keyword_buffer, l:match_str) | |
let s:cache_keyword_buffer[l:match_str].rank += 1 | |
" For debbuging | |
let s:cache_keyword_buffer[l:match_str].menu = printf("%." . g:AltAutoComplPop_MaxFilenameWidth . "s %d", fnamemodify(bufname(l:bufnumber), ':t'), s:cache_keyword_buffer[l:match_str].rank) | |
else | |
" For debbuging | |
let l:menu = printf("%." . g:AltAutoComplPop_MaxFilenameWidth . "s %d", fnamemodify(bufname(l:bufnumber), ':t'), 1) | |
"let l:menu = printf("%." . g:AltAutoComplPop_MaxFilenameWidth . "s", fnamemodify(bufname(l:bufnumber), ':t')) | |
let l:abbr = printf("%." . g:AltAutoComplPop_MaxKeywordWidth . "s", l:match_str) | |
let l:dict = {'word' : l:match_str, 'abbr' : l:abbr, 'menu' : l:menu, 'rank' : 1, 'dup' : 0} | |
" Append list | |
"call add(s:cache_keyword_buffer, l:dict) | |
let s:cache_keyword_buffer[l:match_str] = l:dict | |
endif | |
" Next match | |
let l:match_num += len(l:match_str) | |
let l:match_num = match(l:line, '\k\+', l:match_num) | |
let l:match_str = matchstr(l:line, '\k\+', l:match_num) | |
endwhile | |
let l:line_num += 1 | |
endwhile | |
endif | |
let l:bufnumber += 1 | |
endwhile | |
endfunction | |
function! s:AltAutoComplPop.Enable() | |
augroup AltAutoComplPop | |
autocmd! | |
autocmd InsertEnter * call s:AltAutoComplPop.Caching() | |
autocmd BufWinEnter * call s:AltAutoComplPop.CachingBuffer() | |
autocmd CursorMovedI * call s:AltAutoComplPop.Complete() | |
augroup END | |
" Initialize | |
let s:complete_lock = 0 | |
let s:old_text = '' | |
" Save options | |
let s:completefunc_save = &l:completefunc | |
" Set completefunc | |
let &l:completefunc = "g:AltAutoComplPop_ManualCompleteFunc" | |
" Initialize cache | |
call s:AltAutoComplPop.CachingBuffer() | |
endfunction | |
function! s:AltAutoComplPop.Disable() | |
" Restore options | |
let &l:completefunc = s:completefunc_save | |
augroup AltAutoComplPop | |
autocmd! | |
augroup END | |
endfunction | |
function! s:AltAutoComplPop.Toggle() | |
if s:disable_altautocomplpop | |
let s:disable_altautocomplpop = 0 | |
call s:AltAutoComplPop.Enable() | |
else | |
let s:disable_altautocomplpop = 1 | |
call s:AltAutoComplPop.Disable() | |
endif | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment