initial commit

* forked off from https://github.com/maralla/completor.vim
  d475b42c92a000ff9eeb6b4b311eb06f457e71a3
This commit is contained in:
Prabir Shrestha
2017-01-10 23:26:27 -08:00
commit be56e330d8
4 changed files with 188 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto

27
README.md Normal file
View File

@@ -0,0 +1,27 @@
asyncomplete.vim (exprimental)
==============================
Provide async autocompletion for vim8 with `lambda` and `timers`.
This should work in Neovim once [lambda support](https://github.com/neovim/neovim/pull/5771) is merged in master.
This repository is fork of [https://github.com/maralla/completor.vim](https://github.com/maralla/completor.vim) in pure vim script with python dependency removed.
**Do not depend on this repository. This is me trying out async completion in vim so I will be pushing random things that may break**
### Installing
```viml
Plug 'prabirshrestha/asyncomplete.vim'
```
### Example
```viml
function! s:js_completor(args)
call timer_start(2000, {t->a:args.done([{'word': 'class'}, {'word': 'function'}, {'word': 'value'}])})
endfunction
call asyncomplete#register('javascript', ['.', ' '], function('s:js_completor'))
```
### Credits
All the credit goes to [https://github.com/maralla/completor.vim](https://github.com/maralla/completor.vim)

149
autoload/asyncomplete.vim Normal file
View File

@@ -0,0 +1,149 @@
let s:char_inserted = v:false
let s:completions = {'words': [], 'refresh': 'always'}
let s:status = {'pos': [], 'nr': -1, 'input': '', 'ft': ''}
let s:completors = {}
function! s:completions.set(comps) abort
let self.words = a:comps
endfunction
function! s:completions.clear() abort
let self.words = []
endfunction
function! s:completions.empty() abort
return empty(self.words)
endfunction
function! s:get_start_column(findstart, findbase, triggers)
let l:line_string = getline('.')
let l:line = line('.')
let l:col = col('.')
let l:start = l:col - 1
while l:start > 0
let l:char = l:line_string[l:start - 1]
for l:trigger_char in a:triggers
if l:char == l:trigger_char
return l:start
endif
endfor
let l:start -= 1
endwhile
return l:start
endfunction
function! asyncomplete#completefunc(findstart, findbase)
if a:findstart
if s:completions.empty()
return -3
endif
if has_key(s:completors, s:status.ft) && has_key(s:completors[s:status.ft], 'triggers')
return s:get_start_column(a:findstart, a:findbase, s:completors[s:status.ft].triggers)
else
return -3
endif
endif
let l:completions = copy(s:completions)
call s:completions.clear()
let l:results = []
for l:item in l:completions.words
if l:item.word =~ '^' . a:findbase
call add(l:results, l:item)
endif
endfor
return l:results
endfunction
function! s:consistent() abort
return s:status.nr == bufnr('') && s:status.pos == getcurpos() && s:status.ft == &ft
endfunction
function! s:trigger(items) abort
if !s:consistent()
call s:completions.clear()
else
call s:completions.set(a:items)
endif
if s:completions.empty() | return | endif
setlocal completefunc=asyncomplete#completefunc
setlocal completeopt-=longest
setlocal completeopt+=menuone
setlocal completeopt-=menu
if &completeopt !~# 'noinsert\|noselect'
setlocal completeopt+=noselect
endif
call feedkeys("\<C-x>\<C-u>\<C-p>", 'n')
endfunction
function! s:reset() abort
call s:completions.clear()
endfunction
function! s:complete() abort
call s:reset()
if !s:consistent() | return | endif
if has_key(s:completors, s:status.ft)
call s:completors[s:status.ft].completor({'info': s:status, 'done': {items->s:trigger(items)}})
endif
endfunction
function! s:skip() abort
let l:buftype = &buftype
let l:skip = empty(&ft) || buftype == 'nofile' || buftype == 'quickfix'
return l:skip || !s:char_inserted
endfunction
function! s:on_text_change() abort
if s:skip() | return | endif
let s:char_inserted = v:false
if exists('s:timer')
let l:info = timer_info(s:timer)
if !empty(l:info)
call timer_stop(s:timer)
endif
endif
let e = col('.') - 2
let inputted = e >= 0 ? getline('.')[:e] : ''
let s:status = {'input':inputted, 'pos': getcurpos(), 'nr': bufnr(''), 'ft': &ft}
let s:timer = timer_start(g:asyncomplete_completion_delay, {t->s:complete()})
endfunction
function! s:on_insert_char_pre() abort
let s:char_inserted = v:true
endfunction
function! s:set_events() abort
augroup asyncomplete
autocmd!
autocmd TextChangedI * call s:on_text_change()
autocmd InsertCharPre * call s:on_insert_char_pre()
augroup END
endfunction
" public apis {{{
function! asyncomplete#enable() abort
" remove this check when nvim supports lambda
if !has('nvim')
call s:set_events()
endif
endfunction
function! asyncomplete#disable() abort
autocmd! asyncomplete
endfunction
function! asyncomplete#register(filetype, triggers, completor) abort
let s:completors[a:filetype] = { 'triggers': a:triggers, 'completor': a:completor }
endfunction
function! asyncomplete#unregister(filetype) abort
call remove(s:completors, a:filetype)
endfunction
" }}}

11
plugin/asyncomplete.vim Normal file
View File

@@ -0,0 +1,11 @@
if exists('g:asyncomplete_loaded')
finish
endif
let g:asyncomplete_loaded = 1
let g:asyncomplete_completion_delay = get(g:, 'asyncomplete_completion_delay', 80)
augroup asyncomplete
autocmd!
autocmd InsertEnter * call asyncomplete#enable()
augroup END