Skip to content

Instantly share code, notes, and snippets.

@Shougo
Created December 18, 2008 06:05
Show Gist options
  • Save Shougo/37405 to your computer and use it in GitHub Desktop.
Save Shougo/37405 to your computer and use it in GitHub Desktop.
" 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