"============================================================================= " FILE: helper.vim " AUTHOR: Shougo Matsushita " License: MIT license "============================================================================= if !exists('s:internal_candidates_list') let s:internal_candidates_list = {} let s:global_candidates_list = { \ 'dictionary_variables' : {}, 'runtimepath' : &runtimepath } let s:script_candidates_list = {} let s:local_candidates_list = {} endif let s:dictionary_path = \ substitute(fnamemodify(expand(''), ':h'), '\\', '/', 'g') function! necovim#helper#make_cache() abort if &filetype !=# 'vim' return endif let s:script_candidates_list[bufnr('%')] = \ s:get_script_candidates(bufnr('%')) endfunction function! necovim#helper#augroup(cur_text, complete_str) abort " Make cache. if s:check_global_candidates('augroups') let s:global_candidates_list.augroups = s:get_augrouplist() endif return copy(s:global_candidates_list.augroups) endfunction function! necovim#helper#colorscheme_args(cur_text, complete_str) abort return s:make_completion_list(map(split( \ globpath(&runtimepath, 'colors/*.vim'), '\n'), \ 'fnamemodify(v:val, ":t:r")')) endfunction function! necovim#helper#command(cur_text, complete_str) abort if a:cur_text == '' || \ a:cur_text =~ '^[[:digit:],[:space:][:tab:]$''<>]*\h\w*$' " Commands. " Make cache. if s:check_global_candidates('commands') let s:global_candidates_list.commands = s:get_cmdlist() endif if !has_key(s:internal_candidates_list, 'commands') let s:internal_candidates_list.commands = s:make_cache_commands() endif let list = copy(s:internal_candidates_list.commands) \ + copy(s:global_candidates_list.commands) else " Commands args. " Expression. let list = necovim#helper#expression(a:cur_text, a:complete_str) if s:has_cmdline() let list += s:make_completion_list( \ getcompletion(a:cur_text, 'cmdline')) let list = s:uniq_by(list, 'v:val.word') endif endif return list endfunction function! necovim#helper#environment(cur_text, complete_str) abort " Make cache. if s:check_global_candidates('environments') let s:global_candidates_list.environments = s:get_envlist() endif return copy(s:global_candidates_list.environments) endfunction function! necovim#helper#expand(cur_text, complete_str) abort return s:make_completion_list( \ ['', '', '', '', \ '', '', '', '']) endfunction function! necovim#helper#expression(cur_text, complete_str) abort return necovim#helper#function(a:cur_text, a:complete_str) \+ necovim#helper#var(a:cur_text, a:complete_str) endfunction function! necovim#helper#feature(cur_text, complete_str) abort if !has_key(s:internal_candidates_list, 'features') let s:internal_candidates_list.features = s:make_cache_features() endif return copy(s:internal_candidates_list.features) endfunction function! necovim#helper#filetype(cur_text, complete_str) abort if !has_key(s:internal_candidates_list, 'filetypes') let s:internal_candidates_list.filetypes = \ s:make_completion_list(map( \ split(globpath(&runtimepath, 'syntax/*.vim'), '\n') + \ split(globpath(&runtimepath, 'indent/*.vim'), '\n') + \ split(globpath(&runtimepath, 'ftplugin/*.vim'), '\n') \ , "matchstr(fnamemodify(v:val, ':t:r'), '^[[:alnum:]-]*')")) endif return copy(s:internal_candidates_list.filetypes) endfunction function! necovim#helper#function(cur_text, complete_str) abort " Make cache. if s:check_global_candidates('functions') let s:global_candidates_list.functions = s:get_functionlist() endif if !has_key(s:internal_candidates_list, 'functions') let s:internal_candidates_list.functions = s:make_cache_functions() endif let script_functions = values(s:get_cached_script_candidates().functions) if a:complete_str =~ '^s:' let list = script_functions elseif a:complete_str =~ '^\a:' let list = deepcopy(script_functions) for keyword in list let keyword.word = '' . keyword.word[2:] let keyword.abbr = '' . keyword.abbr[2:] endfor else let list = copy(s:internal_candidates_list.functions) \ + copy(s:global_candidates_list.functions) \ + script_functions for functions in map(values(s:script_candidates_list), 'v:val.functions') let list += values(filter(copy(functions), 'v:val.word[:1] !=# "s:"')) endfor endif return list endfunction function! necovim#helper#let(cur_text, complete_str) abort if a:cur_text !~ '=' return necovim#helper#var(a:cur_text, a:complete_str) elseif a:cur_text =~# '\ 100) ? line('.') - 100 : 1 while line_num >= end_line let line = getline(line_num) if line =~ '\' break elseif line =~ '\ 704 || v:version == 704 && has('patch11')) ? \ 'acl' : '^all_builtin_terms')) let end = match(lines, '^x11') for l in lines[start : end] let _ = matchlist(l, '^\(\k\+\)\t\+\(.\+\)$') if !empty(_) call add(features, { \ 'word' : _[1], \ 'menu' : '; ' . _[2], \ }) endif endfor call add(features, { \ 'word' : 'patch', \ 'menu' : '; Included patches Ex: patch123', \ }) if has('patch-7.4.237') call add(features, { \ 'word' : 'patch-', \ 'menu' : '; Version and patches Ex: patch-7.4.237' \ }) endif return features endfunction function! s:make_cache_functions() abort let helpfile = expand(findfile('doc/eval.txt', &runtimepath)) if !filereadable(helpfile) return [] endif let lines = readfile(helpfile) let functions = [] let start = match(lines, '^abs') let end = match(lines, '^abs', start, 2) for i in range(end-1, start, -1) let func = matchstr(lines[i], '^\s*\zs\w\+(.\{-})') if func != '' call insert(functions, { \ 'word' : substitute(func, '(\zs.\+)', '', ''), \ 'abbr' : substitute(func, '(\zs\s\+', '', ''), \ }) endif endfor return functions endfunction function! s:make_cache_commands() abort let helpfile = expand(findfile('doc/index.txt', &runtimepath)) if !filereadable(helpfile) return [] endif let lines = readfile(helpfile) let commands = [] let start = match(lines, '^|:!|') let end = match(lines, '^|:\~|', start) for lnum in range(end, start, -1) let desc = substitute(lines[lnum], '^\s\+\ze', '', 'g') let _ = matchlist(desc, '^|:\(.\{-}\)|\s\+\S\+') if !empty(_) call add(commands, { \ 'word' : _[1], 'kind' : 'c', \ }) endif endfor return commands endfunction function! s:make_cache_autocmds() abort let helpfile = expand(findfile('doc/autocmd.txt', &runtimepath)) if !filereadable(helpfile) return [] endif let lines = readfile(helpfile) let autocmds = [] let start = match(lines, '^|BufNewFile|') let end = match(lines, '^|User|', start) let desc = '' for lnum in range(end, start, -1) let desc = substitute(lines[lnum], '^\s\+\ze', '', 'g') . ' ' . desc let _ = matchlist(desc, '^|\(.\{-}\)|\s\+\S\+') if !empty(_) call add(autocmds, { 'word' : _[1], }) let desc = '' endif endfor return autocmds endfunction function! s:get_cmdlist() abort let list = exists('*getcompletion') ? \ getcompletion('', 'command') : \ split(s:redir('command'), '\n')[1:] return s:make_completion_list(list) endfunction function! s:get_variablelist(dict, prefix) abort let kind_dict = \ ['0', '""', '()', '[]', '{}', '.', 'b', 'no', 'j', 'ch'] return values(map(copy(a:dict), "{ \ 'word' : a:prefix.v:key, \ 'kind' : kind_dict[type(v:val)], \}")) endfunction function! s:get_functionlist() abort let keyword_dict = {} let function_prototypes = {} for line in split(s:redir('function'), '\n') let line = line[9:] if line =~ '^' continue endif let orig_line = line let word = matchstr(line, '\h[[:alnum:]_:#.]*()\?') if word != '' let keyword_dict[word] = { \ 'word' : word, 'abbr' : line, \} let function_prototypes[word] = orig_line[len(word):] endif endfor let s:global_candidates_list.function_prototypes = function_prototypes return values(keyword_dict) endfunction function! s:get_augrouplist() abort let list = exists('*getcompletion') ? \ getcompletion('', 'augroup') : \ split(s:redir('augroup') . ' END', '\s\|\n') return s:make_completion_list(list) endfunction function! s:get_mappinglist() abort let keyword_list = [] for line in split(s:redir('map'), '\n') let map = matchstr(line, '^\a*\s*\zs\S\+') if map !~ '^<' || map =~ '^' continue endif call add(keyword_list, { 'word' : map }) endfor return keyword_list endfunction function! s:get_envlist() abort let keyword_list = [] for line in split(system('set'), '\n') let word = '$' . toupper(matchstr(line, '^\h\w*')) call add(keyword_list, { 'word' : word, 'kind' : 'e' }) endfor return keyword_list endfunction function! s:make_completion_list(list) abort return map(copy(a:list), "{ 'word' : v:val }") endfunction function! s:analyze_function_line(line, keyword_dict, prototype) abort " Get script function. let line = substitute(matchstr(a:line, \ '\ r execute 'silent!' a:command redir END return r endfunction function! s:has_cmdline() abort if !exists('*getcompletion') return 0 endif try call getcompletion('', 'cmdline') catch return 0 endtry return 1 endfunction " Removes duplicates from a list. function! s:uniq(list) abort return s:uniq_by(a:list, 'v:val') endfunction " Removes duplicates from a list. function! s:uniq_by(list, f) abort let list = map(copy(a:list), printf('[v:val, %s]', a:f)) let i = 0 let seen = {} while i < len(list) let key = string(list[i][1]) if has_key(seen, key) call remove(list, i) else let seen[key] = 1 let i += 1 endif endwhile return map(list, 'v:val[0]') endfunction