diff --git a/README.md b/README.md index db37587..9146e2e 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,14 @@ Clear buffer word cache on events (default: `1`) let g:asyncomplete_buffer_clear_cache = 1 ``` +Custom regex to dedide how to identify word characters (defaults: `\w\+`) +```vim +let g:asyncomplete_buffer_identify_words_regex = '\w\+' +let g:asyncomplete_buffer_identify_words_regex = '\k\+' (uses iskeyword) +``` + + + ### Credits All the credit goes to the following projects * [https://github.com/roxma/nvim-complete-manager](https://github.com/roxma/nvim-complete-manager) diff --git a/autoload/asyncomplete/sources/buffer.vim b/autoload/asyncomplete/sources/buffer.vim index 20ab961..cff03d9 100644 --- a/autoload/asyncomplete/sources/buffer.vim +++ b/autoload/asyncomplete/sources/buffer.vim @@ -1,24 +1,32 @@ let s:words = {} let s:last_word = '' let g:asyncomplete_buffer_clear_cache = get(g:, 'asyncomplete_buffer_clear_cache', 1) +let g:asyncomplete_buffer_identify_words_regex = get(g:, 'asyncomplete_buffer_identify_words_regex', '\w\+') function! asyncomplete#sources#buffer#completor(opt, ctx) - let l:typed = a:ctx['typed'] - - call s:refresh_keyword_incremental(l:typed) + call asyncomplete#log('asyncomplete#buffer ctx', a:ctx) if empty(s:words) return endif let l:matches = [] - let l:col = a:ctx['col'] + let l:typed = a:ctx['typed'] - let l:kw = matchstr(l:typed, '\w\+$') + let l:kw = matchstr(l:typed, g:asyncomplete_buffer_identify_words_regex .'$') let l:kwlen = len(l:kw) - let l:matches = map(keys(s:words),'{"word":v:val,"dup":1,"icase":1,"menu": "[buffer]"}') + if l:kwlen < 1 + return + endif + + let l:words = keys(s:words) + if !empty(s:last_word) && l:kw !=? s:last_word && !has_key(s:words, s:last_word) + let l:words += [s:last_word] + endif + + let l:matches = map(l:words,'{"word":v:val,"dup":1,"icase":1,"menu": "[buffer]"}') let l:startcol = l:col - l:kwlen call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches) @@ -26,12 +34,13 @@ endfunction function! asyncomplete#sources#buffer#get_source_options(opts) return extend({ - \ 'events': ['BufWinEnter'], + \ 'events': ['CursorHold','CursorHoldI','BufWinEnter','BufWritePost','TextChangedI'], \ 'on_event': function('s:on_event'), \}, a:opts) endfunction -function! s:should_ignore(opt) abort +let s:last_ctx = {} +function! s:on_event(opt, ctx, event) abort let l:max_buffer_size = 5000000 " 5mb if has_key(a:opt, 'config') && has_key(a:opt['config'], 'max_buffer_size') let l:max_buffer_size = a:opt['config']['max_buffer_size'] @@ -40,18 +49,17 @@ function! s:should_ignore(opt) abort let l:buffer_size = line2byte(line('$') + 1) if l:buffer_size > l:max_buffer_size call asyncomplete#log('asyncomplete#sources#buffer', 'ignoring buffer autocomplete due to large size', expand('%:p'), l:buffer_size) - return 1 + return endif endif - return 0 -endfunction - -let s:last_ctx = {} -function! s:on_event(opt, ctx, event) abort - if s:should_ignore(a:opt) | return | endif - - if a:event == 'BufWinEnter' + if a:event ==# 'TextChangedI' + call s:refresh_keyword_incr(a:ctx['typed']) + else + if s:last_ctx == a:ctx + return + endif + let s:last_ctx = a:ctx call s:refresh_keywords() endif endfunction @@ -61,20 +69,26 @@ function! s:refresh_keywords() abort let s:words = {} endif let l:text = join(getline(1, '$'), "\n") - for l:word in split(l:text, '\W\+') + for l:word in s:split_words(l:text) if len(l:word) > 1 let s:words[l:word] = 1 endif endfor - call asyncomplete#log('asyncomplete#buffer', 's:refresh_keywords() complete') endfunction -function! s:refresh_keyword_incremental(typed) abort - let l:words = split(a:typed, '\W\+') +function! s:refresh_keyword_incr(typed) abort + let l:words = s:split_words(a:typed) + if len(l:words) > 1 + for l:word in l:words[:len(l:words)-2] + let s:words[l:word] = 1 + endfor + endif + if len(l:words) > 0 + let l:new_last_word = l:words[len(l:words)-1:][0] + let s:last_word = l:new_last_word + endif +endfunction - for l:word in l:words - if len(l:word) > 1 - let s:words[l:word] = 1 - endif - endfor +function! s:split_words(text) + return map(split(a:text, g:asyncomplete_buffer_identify_words_regex.'\zs'),'matchstr(v:val,g:asyncomplete_buffer_identify_words_regex)') endfunction