diff --git a/autoload/asyncomplete.vim b/autoload/asyncomplete.vim index 8cbf30f..9a31372 100644 --- a/autoload/asyncomplete.vim +++ b/autoload/asyncomplete.vim @@ -367,14 +367,21 @@ function! s:recompute_pum(...) abort endif endfor - " TODO: allow users to pass custom filter function. lock the api before making this public. - " Everything in this function should be treated as immutable. filter function shouldn't mutate. - call s:default_filter({ 'ctx': l:ctx, 'base': l:base, 'startcol': l:startcol, 'matches': l:matches_to_filter }) + let l:filter_ctx = extend({ + \ 'base': l:base, + \ 'startcol': l:startcol, + \ }, l:ctx) + + if empty(g:asyncomplete_preprocessor) + call s:default_preprocessor(l:filter_ctx, l:matches_to_filter) + else + call g:asyncomplete_preprocessor[0](l:filter_ctx, l:matches_to_filter) + endif endfunction -function! s:default_filter(options) abort +function! s:default_preprocessor(options, matches) abort let l:items = [] - for [l:source_name, l:matches] in items(a:options['matches']) + for [l:source_name, l:matches] in items(a:matches) for l:item in l:matches['items'] if l:item['word'] =~ '^' . a:options['base'] call add(l:items, l:item) @@ -382,17 +389,17 @@ function! s:default_filter(options) abort endfor endfor - call s:set_pum(a:options['startcol'], l:items) + call asyncomplete#preprocess_complete(a:options, l:items) endfunction -function! s:set_pum(startcol, items) abort - " TODO: handle cases where this is called asynchronsouly +function! asyncomplete#preprocess_complete(ctx, items) + " TODO: handle cases where this is called asynchronsouly. Currently not supported if s:should_skip() | return | endif - call asyncomplete#log('core', 's:set_pum') + call asyncomplete#log('core', 'asyncomplete#preprocess_complete') if asyncomplete#menu_selected() - call asyncomplete#log('core', 's:set_pum', 'ignorning set pum due to menu selection') + call asyncomplete#log('core', 'asyncomplete#preprocess_complete', 'ignorning pum update due to menu selection') return endif @@ -400,8 +407,8 @@ function! s:set_pum(startcol, items) abort setl completeopt=menuone,noinsert,noselect endif - call asyncomplete#log('core', 's:set_pum calling complete()', a:startcol + 1, a:items) - call complete(a:startcol + 1, a:items) + call asyncomplete#log('core', 'asyncomplete#preprocess_complete calling complete()', a:ctx['startcol'] + 1, a:items) + call complete(a:ctx['startcol'] + 1, a:items) endfunction function! asyncomplete#menu_selected() abort diff --git a/doc/asyncomplete.txt b/doc/asyncomplete.txt index 48ddc72..0137be3 100644 --- a/doc/asyncomplete.txt +++ b/doc/asyncomplete.txt @@ -42,7 +42,7 @@ g:asyncomplete_popup_delay *g:asyncomplete_popup_delay* Milliseconds to wait before opening the popup menu -g:asyncomplete_auto_completeopt *g:asyncomplete_auto_completeopt* +g:asyncomplete_auto_completeopt *g:asyncomplete_auto_completeopt* Type: |Number| Default: 1 @@ -52,6 +52,39 @@ g:asyncomplete_auto_completeopt *g:asyncomplete_auto_compl Set to 0 to disable. +g:asyncomplete_preprocessor *g:asyncomplete_preprocessor* + + Type: |Array| for zero or one |Function| + Default: [] + + Set a function to allow custom filtering or sorting. + Below example implements removing duplicates. + + function! s:my_asyncomplete_preprocessor(ctx, matches) abort + let l:dict = {} + let l:items = [] + for [l:source_name, l:matches] in items(a:matches) + for l:item in l:matches['items'] + if l:item['word'] =~ '^' . a:options['base'] + if !has_key(l:dict, l:item['word']) + call add(l:items, l:item) + endif + endif + endfor + endfor + + call asyncomplete#preprocess_complete(a:ctx, l:items) + endfunction + + let g:asyncomplete_preprocessor = [function('s:my_asyncomplete_preprocessor')] + + Note: + asyncomplete#preprocess_complete() must be called synchronously. + Plans to support async preprocessing will be supported in the future. + + context and matches in arguments in preprecessor function should be treated + as immutable. + =============================================================================== 3. Global vim configuration *asyncomplete-global-config* diff --git a/plugin/asyncomplete.vim b/plugin/asyncomplete.vim index 97b2648..8918050 100644 --- a/plugin/asyncomplete.vim +++ b/plugin/asyncomplete.vim @@ -18,5 +18,6 @@ let g:asyncomplete_auto_completeopt = get(g:, 'asyncomplete_auto_completeopt', 1 let g:asyncomplete_auto_popup = get(g:, 'asyncomplete_auto_popup', 1) let g:asyncomplete_popup_delay = get(g:, 'asyncomplete_popup_delay', 30) let g:asyncomplete_log_file = get(g:, 'asyncomplete_log_file', '') +let g:asyncomplete_preprocessor = get(g:, 'asyncomplete_preprocessor', []) inoremap (asyncomplete_force_refresh) asyncomplete#force_refresh()