"============================================================================= " FILE: complete.vim " AUTHOR: Shougo Matsushita " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the " "Software"), to deal in the Software without restriction, including " without limitation the rights to use, copy, modify, merge, publish, " distribute, sublicense, and/or sell copies of the Software, and to " permit persons to whom the Software is furnished to do so, subject to " the following conditions: " " The above copyright notice and this permission notice shall be included " in all copies or substantial portions of the Software. " " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " }}} "============================================================================= let s:save_cpo = &cpo set cpo&vim function! neocomplete#complete#_get_results(cur_text, ...) abort "{{{ call neocomplete#print_debug('start get_complete_sources') let neocomplete = neocomplete#get_current_neocomplete() let neocomplete.start_time = reltime() " Comment check. let neocomplete.within_comment = \ neocomplete#helper#get_syn_name(1) ==# 'Comment' let complete_sources = call( \ 'neocomplete#complete#_set_results_pos', [a:cur_text] + a:000) if empty(complete_sources) call neocomplete#print_debug('Skipped.') return [] endif if neocomplete#is_auto_complete() let complete_pos = \ neocomplete#complete#_get_complete_pos(complete_sources) call neocomplete#complete#_set_previous_position(a:cur_text, complete_pos) endif call neocomplete#complete#_set_results_words(complete_sources) return filter(copy(complete_sources), \ '!empty(v:val.neocomplete__context.candidates)') endfunction"}}} function! neocomplete#complete#_get_complete_pos(sources) abort "{{{ if empty(a:sources) return -1 endif return min([col('.')] + map(copy(a:sources), \ 'v:val.neocomplete__context.complete_pos')) endfunction"}}} function! neocomplete#complete#_get_words(sources, complete_pos, complete_str) abort "{{{ let frequencies = neocomplete#variables#get_frequencies() if exists('*neocomplete#sources#buffer#get_frequencies') let frequencies = extend(copy( \ neocomplete#sources#buffer#get_frequencies()), \ frequencies) endif " Append prefix. let candidates = [] let len_words = 0 for source in sort(filter(deepcopy(a:sources), \ '!empty(v:val.neocomplete__context.candidates)'), \ 's:compare_source_rank') let context = source.neocomplete__context let words = type(context.candidates[0]) == type('') ? \ map(copy(context.candidates), "{'word': v:val}") : \ deepcopy(context.candidates) let context.candidates = words call neocomplete#helper#call_hook( \ source, 'on_post_filter', {}) if context.complete_pos > a:complete_pos let prefix = a:complete_str[: context.complete_pos \ - a:complete_pos - 1] " Fix complete position. let context.complete_pos = a:complete_pos let context.complete_str = prefix for candidate in words let candidate.word = prefix . candidate.word endfor endif lua << EOF do local frequencies = vim.eval('frequencies') local candidates = vim.eval('words') for i = 0, #candidates-1 do if frequencies[candidates[i].word] ~= nil then candidates[i].rank = frequencies[candidates[i].word] end end end EOF let words = neocomplete#helper#call_filters( \ source.neocomplete__sorters, source, {}) if empty(words) continue endif if source.max_candidates > 0 let words = words[: len(source.max_candidates)-1] endif let words = neocomplete#helper#call_filters( \ source.neocomplete__converters, source, {}) if empty(words) continue endif " Set default menu. if get(words[0], 'menu', '') !~ '^\[.*\' call s:set_default_menu(words, source) endif let candidates += words let len_words += len(words) if g:neocomplete#max_list > 0 \ && len_words > g:neocomplete#max_list break endif if neocomplete#complete_check() return [] endif endfor call filter(candidates, 'v:val.word !=# a:complete_str') if g:neocomplete#max_list > 0 let candidates = candidates[: g:neocomplete#max_list] endif " Check dup and set icase. let icase = g:neocomplete#enable_ignore_case && \ !((g:neocomplete#enable_smart_case \ || g:neocomplete#enable_camel_case) && a:complete_str =~ '\u') if icase for candidate in candidates let candidate.icase = 1 endfor endif if neocomplete#complete_check() return [] endif return candidates endfunction"}}} function! neocomplete#complete#_set_results_pos(cur_text, ...) abort "{{{ " Initialize sources. let neocomplete = neocomplete#get_current_neocomplete() let filetype = neocomplete#get_context_filetype() let sources = (a:0 > 0) ? a:1 : \ (filetype ==# neocomplete.sources_filetype) ? \ neocomplete.sources : neocomplete#helper#get_sources_list() let pos = winsaveview() " Try source completion. "{{{ let complete_sources = [] for source in filter(values(sources), \ 'neocomplete#helper#is_enabled_source(v:val, filetype)') if !source.loaded call neocomplete#helper#call_hook(source, 'on_init', {}) let source.loaded = 1 endif let context = source.neocomplete__context let context.input = a:cur_text let context.filetype = filetype let context.filetypes = neocomplete#context_filetype#filetypes() try let complete_pos = s:use_previous_result(source, context) ? \ context.prev_complete_pos : \ has_key(source, 'get_complete_position') ? \ source.get_complete_position(context) : \ neocomplete#helper#match_word(context.input, \ neocomplete#get_keyword_pattern_end(filetype, source.name))[0] catch call neocomplete#print_error(v:throwpoint) call neocomplete#print_error(v:exception) call neocomplete#print_error( \ 'Error occurred in source''s get_complete_position()!') call neocomplete#print_error( \ 'Source name is ' . source.name) return complete_sources finally if winsaveview() != pos call winrestview(pos) endif endtry if complete_pos < 0 let context.complete_pos = -1 let context.complete_str = '' continue endif let complete_str = context.input[complete_pos :] if neocomplete#is_auto_complete() && \ (source.input_pattern == '' || \ context.input !~# '\%(' . source.input_pattern.'\m\)$') && \ len(complete_str) < source.min_pattern_length " Skip. let context.complete_pos = -1 let context.complete_str = '' continue endif let context.complete_pos = complete_pos let context.complete_str = complete_str call add(complete_sources, source) endfor "}}} return complete_sources endfunction"}}} function! neocomplete#complete#_set_results_words(sources) abort "{{{ " Try source completion. " Save options. let ignorecase_save = &ignorecase let pos = winsaveview() try for source in a:sources if neocomplete#complete_check() return endif let context = source.neocomplete__context let &ignorecase = (g:neocomplete#enable_smart_case \ || g:neocomplete#enable_camel_case) ? \ context.complete_str !~ '\u' \ : g:neocomplete#enable_ignore_case if s:use_previous_result(source, context) " Use previous candidates. let context.candidates = deepcopy(context.prev_candidates) else try let context.candidates = source.gather_candidates(context) catch call neocomplete#print_error(v:throwpoint) call neocomplete#print_error(v:exception) call neocomplete#print_error( \ 'Source name is ' . source.name) call neocomplete#print_error( \ 'Error occurred in source''s gather_candidates()!') return finally if winsaveview() != pos call winrestview(pos) endif endtry let context.prev_line = context.input let context.prev_candidates = copy(context.candidates) let context.prev_complete_pos = context.complete_pos endif if !empty(context.candidates) let matchers = empty(source.neocomplete__matchers) ? \ neocomplete#get_current_neocomplete().default_matchers \ : source.neocomplete__matchers let context.candidates = neocomplete#helper#call_filters( \ matchers, source, {}) endif call neocomplete#print_debug(source.name) endfor finally let &ignorecase = ignorecase_save endtry endfunction"}}} function! neocomplete#complete#_check_previous_position(cur_text, complete_pos) abort "{{{ let neocomplete = neocomplete#get_current_neocomplete() return a:complete_pos == neocomplete.old_complete_pos \ && line('.') == neocomplete.old_linenr \ && a:cur_text ==# neocomplete.old_cur_text endfunction"}}} function! neocomplete#complete#_set_previous_position(cur_text, complete_pos) abort "{{{ let neocomplete = neocomplete#get_current_neocomplete() let neocomplete.old_complete_pos = a:complete_pos let neocomplete.old_linenr = line('.') let neocomplete.old_cur_text = a:cur_text endfunction"}}} " Source rank order. "{{{ function! s:compare_source_rank(i1, i2) abort return a:i2.rank - a:i1.rank endfunction"}}} function! s:set_default_menu(words, source) abort "{{{ lua << EOF do local candidates = vim.eval('a:words') local mark = vim.eval('a:source.mark') .. ' ' for i = 0, #candidates-1 do candidates[i].menu = mark .. (candidates[i].menu ~= nil and candidates[i].menu or '') end end EOF endfunction"}}} function! s:use_previous_result(source, context) abort "{{{ let neocomplete = neocomplete#get_current_neocomplete() return !a:source.is_volatile \ && substitute(a:context.input, '\k\+$', '', '') \ ==# substitute(a:context.prev_line, '\k\+$', '', '') \ && stridx(a:context.input, a:context.prev_line) == 0 \ && !empty(a:context.prev_candidates) \ && line('.') == neocomplete.old_linenr endfunction"}}} let &cpo = s:save_cpo unlet s:save_cpo " vim: foldmethod=marker