Skip to content

Instantly share code, notes, and snippets.

@tarruda
Created July 2, 2014 15:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tarruda/e33a5b87c0b1bfdf9beb to your computer and use it in GitHub Desktop.
Save tarruda/e33a5b87c0b1bfdf9beb to your computer and use it in GitHub Desktop.
Implementing support functions neovim asynchronous services
" create this file at autoload/async.vim
let s:next_completion_id = 1
let s:current_completion_id = 0
function! async#CompletionBegin()
let s:current_completion_id = s:next_completion_id
let s:next_completion_id += 1
let data = {
\ 'id': s:current_completion_id,
\ 'position': s:GetCompletionPosition(),
\ 'filetype': &filetype,
\ 'extra_data': 0,
\ }
" Broadcast the 'completion_begin' event
call send_event(0, 'completion_begin', data)
return ''
endfunction
function! async#CompletionEnd(results, data)
if mode() != 'i'
" Not in insert mode, ignore
return
endif
let completion_id = a:data['id']
if s:current_completion_id != completion_id
" Completion expired
return
endif
let completion_pos = a:data['position']
let current_pos = s:GetCompletionPosition()
if current_pos[0] != completion_pos[0] || current_pos[1] != completion_pos[1]
" Completion position changed
return
endif
call complete(completion_pos[1] + 1, a:results)
" Like YCM, do not select the first match automatically
call feedkeys("\<c-p>")
endfunction
function! s:GetCompletionPosition()
" The completion position is the start of the current identifier
return searchpos('\i\@!', 'bn', line('.'))
endfunction
" create this file at plugin/async.vim
if exists("g:loaded_async")
finish
endif
let g:loaded_async = 1
let g:async_key_completion_begin =
\ get(g:, 'async_key_completion_begin', '<c-space>')
let g:async_key_completion_next =
\ get(g:, 'async_key_completion_next', ['<tab>', '<down>'])
let g:async_key_completion_prev =
\ get(g:, 'async_key_completion_prev', ['<s-tab>', '<up>'])
function! s:Setup()
call s:SetupKeys()
endfunction
function! s:SetupKeys()
if !empty(g:async_key_completion_begin)
let invoke_key = g:async_key_completion_begin
if invoke_key ==# '<c-space>'
let invoke_key = '<nul>'
endif
" <c-x><c-o> trigger omni completion, <c-p> deselects the first completion
" candidate that vim selects by default
silent! exe 'inoremap ' . invoke_key . ' <c-r>=async#CompletionBegin()<cr>'
endif
for key in g:async_key_completion_next
exe 'inoremap <expr>' . key . ' pumvisible() ? "\<c-n>" : "\' . key .'"'
endfor
for key in g:async_key_completion_prev
exe 'inoremap <expr>' . key . ' pumvisible() ? "\<c-p>" : "\' . key .'"'
endfor
endfunction
augroup asyncStart
autocmd!
autocmd VimEnter * call s:Setup()
augroup END
# create this file at pythonx/nvim_async.py
from threading import Timer
from json import dumps
class NvimAsync(object):
def __init__(self, vim):
self.vim = vim
def on_completion_begin(self, data):
vim = self.vim
self.t = Timer(1, lambda: vim.push_message('completion_end', data))
self.t.start()
def on_completion_end(self, data):
results = []
for k, v in data.items():
results.append({'word': str(v), 'info': str(k), 'menu': '(' + str(k) + ')'})
cmd = 'call async#CompletionEnd({0}, {1})'.format(dumps(results),
dumps(data))
self.vim.command(cmd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment