[
  {
    "path": ".gitignore",
    "content": "*.py[cod]\ndoc/tags\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT license\n\nCopyright (c) Shougo Matsushita <Shougo.Matsu at gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "autoload/cm/sources/necovim.vim",
    "content": "\"=============================================================================\n\" FILE: necovim.vim (NCM source)\n\" AUTHOR:  Karl Yngve Lervåg <karl.yngve@gmail.com>\n\" License: MIT license\n\"=============================================================================\n\nfunction! cm#sources#necovim#refresh(opt, ctx) abort\n  let startcol = necovim#get_complete_position(a:ctx.typed)\n  let base = strpart(a:ctx.typed, startcol)\n  let cnd = necovim#gather_candidates(a:ctx.typed, base)\n  call cm#complete(a:opt.name, a:ctx, startcol+1, cnd)\nendfunction\n"
  },
  {
    "path": "autoload/necovim/helper.vim",
    "content": "\"=============================================================================\n\" FILE: helper.vim\n\" AUTHOR:  Shougo Matsushita <Shougo.Matsu@gmail.com>\n\" License: MIT license\n\"=============================================================================\n\nif !exists('s:internal_candidates_list')\n  let s:internal_candidates_list = {}\n  let s:global_candidates_list = {\n        \\ 'dictionary_variables' : {}, 'runtimepath' : &runtimepath }\n  let s:script_candidates_list = {}\n  let s:local_candidates_list = {}\nendif\n\nlet s:dictionary_path =\n      \\ substitute(fnamemodify(expand('<sfile>'), ':h'), '\\\\', '/', 'g')\n\nfunction! necovim#helper#make_cache() abort\n  if &filetype !=# 'vim'\n    return\n  endif\n\n  let s:script_candidates_list[bufnr('%')] =\n        \\ s:get_script_candidates(bufnr('%'))\nendfunction\n\nfunction! necovim#helper#augroup(cur_text, complete_str) abort\n  \" Make cache.\n  if s:check_global_candidates('augroups')\n    let s:global_candidates_list.augroups = s:get_augrouplist()\n  endif\n\n  return copy(s:global_candidates_list.augroups)\nendfunction\nfunction! necovim#helper#command(cur_text, complete_str) abort\n  if a:complete_str ==# ''\n    \" Disable for huge candidates\n    return []\n  endif\n\n  if a:cur_text ==# '' ||\n        \\ a:cur_text =~# '^[[:digit:],[:space:][:tab:]$''<>]*\\h\\w*$'\n    \" Commands.\n\n    \" Make cache.\n    if s:check_global_candidates('commands')\n      let s:global_candidates_list.commands = s:get_cmdlist()\n    endif\n    if !has_key(s:internal_candidates_list, 'commands')\n      let s:internal_candidates_list.commands = s:make_cache_commands()\n    endif\n\n    let list = copy(s:internal_candidates_list.commands)\n          \\ + copy(s:global_candidates_list.commands)\n  else\n    \" Commands args.\n\n    \" Expression.\n    \" Note: In command line window, expression completion should be disabled.\n    let list = bufname('%') ==# '[Command Line]' ? [] :\n          \\ necovim#helper#expression(a:cur_text, a:complete_str)\n\n    try\n      let list += s:make_completion_list(\n            \\ getcompletion(a:cur_text, 'cmdline'))\n    catch\n      \" Ignore getcompletion() error\n    endtry\n  endif\n\n  \" Filter by complete_str to reduce candidates\n  let prefix = a:complete_str[:1]\n  return filter(s:uniq_by(list, 'v:val.word'),\n        \\ { _, val -> stridx(val.word, prefix) == 0})\nendfunction\nfunction! necovim#helper#environment(cur_text, complete_str) abort\n  \" Make cache.\n  if s:check_global_candidates('environments')\n    let s:global_candidates_list.environments = s:get_envlist()\n  endif\n\n  return copy(s:global_candidates_list.environments)\nendfunction\nfunction! necovim#helper#expand(cur_text, complete_str) abort\n  return s:make_completion_list([\n        \\ '<cfile>', '<afile>', '<abuf>', '<amatch>',\n        \\ '<sfile>', '<cword>', '<cWORD>', '<client>'\n        \\ ])\nendfunction\nfunction! necovim#helper#expression(cur_text, complete_str) abort\n  return necovim#helper#function(a:cur_text, a:complete_str)\n        \\+ necovim#helper#var(a:cur_text, a:complete_str)\nendfunction\nfunction! necovim#helper#feature(cur_text, complete_str) abort\n  if !has_key(s:internal_candidates_list, 'features')\n    let s:internal_candidates_list.features = s:make_cache_features()\n  endif\n  return copy(s:internal_candidates_list.features)\nendfunction\nfunction! necovim#helper#filetype(cur_text, complete_str) abort\n  if !has_key(s:internal_candidates_list, 'filetypes')\n    let s:internal_candidates_list.filetypes =\n          \\ s:make_completion_list(map(\n          \\ split(globpath(&runtimepath, 'syntax/*.vim'), '\\n') +\n          \\ split(globpath(&runtimepath, 'indent/*.vim'), '\\n') +\n          \\ split(globpath(&runtimepath, 'ftplugin/*.vim'), '\\n')\n          \\ , { _, val -> matchstr(\n          \\    fnamemodify(val, ':t:r'), '^[[:alnum:]-]*')}))\n  endif\n\n  return copy(s:internal_candidates_list.filetypes)\nendfunction\nfunction! necovim#helper#function(cur_text, complete_str) abort\n  \" Make cache.\n  if s:check_global_candidates('functions')\n    let s:global_candidates_list.functions = s:get_functionlist()\n  endif\n  if !has_key(s:internal_candidates_list, 'functions')\n    let s:internal_candidates_list.functions = s:make_cache_functions()\n    if has('nvim')\n      let s:internal_candidates_list.functions +=\n            \\ s:make_cache_functions_nvim()\n    endif\n  endif\n\n  let script_functions = values(s:get_cached_script_candidates().functions)\n  if a:complete_str =~# '^s:'\n    let list = script_functions\n  elseif a:complete_str =~# '^\\a:'\n    let list = deepcopy(script_functions)\n    for keyword in list\n      let keyword.word = '<SID>' . keyword.word[2:]\n      let keyword.abbr = '<SID>' . keyword.abbr[2:]\n    endfor\n  else\n    let list = copy(s:internal_candidates_list.functions)\n          \\ + copy(s:global_candidates_list.functions)\n          \\ + script_functions\n    for functions in map(values(s:script_candidates_list),\n          \\ { _, val -> val.functions})\n      let list += values(filter(copy(functions),\n            \\ { _, val -> val.word[:1] !=# 's:'}))\n    endfor\n  endif\n\n  return list\nendfunction\nfunction! necovim#helper#let(cur_text, complete_str) abort\n  if a:cur_text !~# '='\n    return necovim#helper#var(a:cur_text, a:complete_str)\n  elseif a:cur_text =~# '\\<let\\s\\+&\\%([lg]:\\)\\?filetype\\s*=\\s*'\n    \" FileType.\n    return necovim#helper#filetype(a:cur_text, a:complete_str)\n  else\n    return necovim#helper#expression(a:cur_text, a:complete_str)\n  endif\nendfunction\nfunction! necovim#helper#option(cur_text, complete_str) abort\n  \" Make cache.\n  if !has_key(s:internal_candidates_list, 'options')\n    let s:internal_candidates_list.options = s:make_cache_options()\n  endif\n\n  if a:cur_text =~# '\\<set\\%[local]\\s\\+\\%(filetype\\|ft\\)='\n    return necovim#helper#filetype(a:cur_text, a:complete_str)\n  else\n    return copy(s:internal_candidates_list.options)\n  endif\nendfunction\nfunction! necovim#helper#var_dictionary(cur_text, complete_str) abort\n  let var_name = matchstr(a:cur_text,\n        \\'\\%(\\a:\\)\\?\\h\\w*\\ze\\.\\%(\\h\\w*\\%(()\\?\\)\\?\\)\\?$')\n  let list = []\n  if a:cur_text =~# '[btwg]:\\h\\w*\\.\\%(\\h\\w*\\%(()\\?\\)\\?\\)\\?$'\n    let list = get(\n          \\ s:global_candidates_list.dictionary_variables, var_name, [])\n  elseif a:cur_text =~# 's:\\h\\w*\\.\\%(\\h\\w*\\%(()\\?\\)\\?\\)\\?$'\n    let list = values(get(\n          \\ s:get_cached_script_candidates().dictionary_variables,\n          \\ var_name, {}))\n  endif\n\n  return list\nendfunction\nfunction! necovim#helper#var(cur_text, complete_str) abort\n  \" Make cache.\n  if s:check_global_candidates('variables')\n    let s:global_candidates_list.variables =\n          \\ s:get_variablelist(g:, 'g:') + s:get_variablelist(v:, 'v:')\n          \\ + s:make_completion_list(['v:val'])\n  endif\n\n  if a:complete_str =~# '^[swtb]:'\n    let list = values(s:get_cached_script_candidates().variables)\n    if a:complete_str !~# '^s:'\n      let prefix = matchstr(a:complete_str, '^[swtb]:')\n      let list += s:get_variablelist(eval(prefix), prefix)\n    endif\n  elseif a:complete_str =~# '^[vg]:'\n    let list = copy(s:global_candidates_list.variables)\n  else\n    let list = s:get_local_variables()\n  endif\n\n  return list\nendfunction\n\nfunction! s:get_local_variables() abort\n  \" Get local variable list.\n\n  let keyword_dict = {}\n  \" Search function.\n  let line_num = line('.') - 1\n  let end_line = max([line('.') - 100, 1])\n  while line_num >= end_line\n    let line = getline(line_num)\n    if line =~# '\\<endf\\%[unction]\\>'\n      break\n    elseif line =~# '\\<fu\\%[nction]!\\?\\s\\+'\n      \" Get function arguments.\n      call s:analyze_variable_line(line, keyword_dict)\n      break\n    endif\n\n    let line_num -= 1\n  endwhile\n  let line_num += 1\n\n  let end_line = line('.') - 1\n  while line_num <= end_line\n    let line = getline(line_num)\n\n    if line =~# '\\<\\%(let\\|const\\|for\\)\\s\\+'\n      if line =~# '\\<\\%(let\\|const\\|for\\)\\s\\+s:'\n            \\ && has_key(get(s:script_candidates_list,\n            \\                bufnr('%'), {}), 'variables')\n        let candidates_list = s:script_candidates_list[bufnr('%')].variables\n      else\n        let candidates_list = keyword_dict\n      endif\n\n      call s:analyze_variable_line(line, candidates_list)\n    endif\n\n    let line_num += 1\n  endwhile\n\n  return values(keyword_dict)\nendfunction\n\nfunction! s:get_cached_script_candidates() abort\n  return has_key(s:script_candidates_list, bufnr('%')) ?\n        \\ s:script_candidates_list[bufnr('%')] : {\n        \\   'functions' : {}, 'variables' : {},\n        \\   'function_prototypes' : {}, 'dictionary_variables' : {} }\nendfunction\nfunction! s:get_script_candidates(bufnumber) abort\n  \" Get script candidate list.\n\n  let function_dict = {}\n  let variable_dict = {}\n  let dictionary_variable_dict = {}\n  let function_prototypes = {}\n  let var_pattern = '\\a:[[:alnum:]_:]*\\.\\h\\w*\\%(()\\?\\)\\?'\n\n  for line in getbufline(a:bufnumber, 1, '$')\n    if line =~# '\\<fu\\%[nction]!\\?\\s\\+'\n      call s:analyze_function_line(\n            \\ line, function_dict, function_prototypes)\n    elseif line =~# '\\<let\\s\\+'\n      \" Get script variable.\n      call s:analyze_variable_line(line, variable_dict)\n    elseif line =~ var_pattern\n      while line =~ var_pattern\n        let var_name = matchstr(line, '\\a:[[:alnum:]_:]*\\ze\\.\\h\\w*')\n        let candidates_dict = dictionary_variable_dict\n        if !has_key(candidates_dict, var_name)\n          let candidates_dict[var_name] = {}\n        endif\n\n        call s:analyze_dictionary_variable_line(\n              \\ line, candidates_dict[var_name], var_name)\n\n        let line = line[matchend(line, var_pattern) :]\n      endwhile\n    endif\n  endfor\n\n  return {\n        \\ 'functions' : function_dict,\n        \\ 'variables' : variable_dict,\n        \\ 'function_prototypes' : function_prototypes,\n        \\ 'dictionary_variables' : dictionary_variable_dict,\n        \\ }\nendfunction\n\nfunction! s:make_cache_options() abort\n  let options = map(filter(split(execute('set all'), '\\s\\{2,}\\|\\n')[1:],\n        \\ { _, val -> !empty(val) && val =~# '^\\h\\w*=\\?' }),\n        \\ { _, val -> substitute(val, '^no\\|=\\zs.*$', '', '') })\n  for option in copy(options)\n    if option[-1:] !=# '='\n      call add(options, 'no'.option)\n    endif\n  endfor\n\n  return map(filter(options, { _, val -> val =~# '^\\h\\w*=\\?' }),\n        \\ { _, val -> {\n        \\     'word': substitute(val, '=$', '', ''), 'kind' : 'o',\n        \\   }\n        \\ })\nendfunction\nfunction! s:make_cache_features() abort\n  let helpfile = expand(findfile('doc/eval.txt', &runtimepath))\n\n  if !filereadable(helpfile)\n    return []\n  endif\n\n  let features = []\n  let lines = readfile(helpfile)\n  let start = match(lines, 'acl')\n  let end = match(lines, has('nvim') ? '^wsl' : '^x11')\n  for l in lines[start : end]\n    let _ = matchlist(l, '^\\(\\k\\+\\)\\t\\+\\(.\\+\\)$')\n    if !empty(_)\n      call add(features, {\n            \\ 'word' : _[1],\n            \\ 'info' : _[2],\n            \\ })\n    endif\n  endfor\n\n  call add(features, {\n        \\ 'word' : 'patch',\n        \\ 'menu' : '; Included patches Ex: patch123',\n        \\ })\n  call add(features, {\n        \\ 'word' : 'patch-',\n        \\ 'menu' : '; Version and patches Ex: patch-7.4.237'\n        \\ })\n\n  return features\nendfunction\nfunction! s:make_cache_functions() abort\n  let helpfile = expand(findfile('doc/builtin.txt', &runtimepath))\n  if !filereadable(helpfile)\n    return []\n  endif\n\n  let lines = readfile(helpfile)\n  let functions = []\n  let start = match(lines, '^abs')\n  let end = match(lines, '^abs', start, 2)\n  if end <= 0\n    \" NOTE: In neovim 0.10+, |builtin-function-list| is removed.  Too bad.\n    let end = match(lines, '^xor', start)\n  endif\n  for i in range(end - 1, start, -1)\n    let func = matchstr(lines[i], '^\\s*\\zs\\w\\+(.\\{-})')\n    if func !=# ''\n      call insert(functions, {\n            \\ 'word' : substitute(func, '(\\zs.\\+)', '', ''),\n            \\ 'abbr' : substitute(func, '(\\zs\\s\\+', '', ''),\n            \\ 'info' : substitute(lines[i], '\\t', ' ', 'g'),\n            \\ })\n    endif\n  endfor\n\n  return functions\nendfunction\nfunction! s:make_cache_functions_nvim() abort\n  let helpfile = expand(findfile('doc/api.txt', &runtimepath))\n  if !filereadable(helpfile)\n    return []\n  endif\n\n  let lines = readfile(helpfile)\n  let functions = []\n  let start = match(lines, '^nvim__get_hl_defs')\n  let end = match(lines, '^nvim_ui_try_resize_grid')\n  for i in range(end, start, -1)\n    let func = matchstr(lines[i], '^\\s*\\zs\\w\\+(.\\{-})')\n    if func !=# ''\n      call insert(functions, {\n            \\ 'word' : substitute(func, '(\\zs.\\+)', '', ''),\n            \\ 'abbr' : substitute(func, '(\\zs\\s\\+', '', ''),\n            \\ 'info' : substitute(lines[i], '\\t', ' ', 'g'),\n            \\ })\n    endif\n  endfor\n\n  return functions\nendfunction\nfunction! s:make_cache_commands() abort\n  let helpfile = expand(findfile('doc/index.txt', &runtimepath))\n  if !filereadable(helpfile)\n    return []\n  endif\n\n  let lines = readfile(helpfile)\n  let commands = []\n  let start = match(lines, '^|:!|')\n  let end = match(lines, '^|:\\~|', start)\n  for lnum in range(end, start, -1)\n    let desc = substitute(lines[lnum], '^\\s\\+\\ze', '', 'g')\n    let _ = matchlist(desc, '^|:\\(.\\{-}\\)|\\s\\+\\S\\+\\s\\+\\(.*\\)$')\n    if !empty(_)\n      call add(commands, {\n            \\ 'word' : _[1], 'kind' : 'c',\n            \\ 'info': _[2],\n            \\ })\n    endif\n  endfor\n\n  return commands\nendfunction\n\nfunction! s:get_cmdlist() abort\n  let list = exists('*nvim_get_commands') ?\n        \\ keys(nvim_get_commands({'builtin': v:false})) :\n        \\ getcompletion('', 'command')\n  return s:make_completion_list(list)\nendfunction\nfunction! s:get_variablelist(dict, prefix) abort\n  let kind_dict =\n        \\ ['0', '\"\"', '()', '[]', '{}', '.', 'b', 'no', 'j', 'ch']\n\n  let list = []\n  for [key, Val] in items(a:dict)\n    let kind = '?'\n    silent! let kind = get(kind_dict, type(Val), '?')\n    call add(list, {\n          \\ 'word' : a:prefix . key,\n          \\ 'kind' : kind,\n          \\ })\n  endfor\n  return list\nendfunction\nfunction! s:get_functionlist() abort\n  let keyword_dict = {}\n  let function_prototypes = {}\n  for line in split(execute('function'), '\\n')\n    let line = line[9:]\n    if line =~# '^<SNR>'\n      continue\n    endif\n    let orig_line = line\n\n    let word = matchstr(line, '\\h[[:alnum:]_:#.]*()\\?')\n    if word !=# ''\n      let keyword_dict[word] = {\n            \\ 'word' : word, 'abbr' : line,\n            \\}\n\n      let function_prototypes[word] = orig_line[len(word):]\n    endif\n  endfor\n\n  let s:global_candidates_list.function_prototypes = function_prototypes\n\n  return values(keyword_dict)\nendfunction\nfunction! s:get_augrouplist() abort\n  return s:make_completion_list(getcompletion('', 'augroup'))\nendfunction\nfunction! s:get_mappinglist() abort\n  let keyword_list = []\n  for line in split(execute('map'), '\\n')\n    let map = matchstr(line, '^\\a*\\s*\\zs\\S\\+')\n    if map !~# '^<' || map =~# '^<SNR>'\n      continue\n    endif\n    call add(keyword_list, { 'word' : map })\n  endfor\n  return keyword_list\nendfunction\nfunction! s:get_envlist() abort\n  let keyword_list = []\n  for line in split(system('set'), '\\n')\n    let word = '$' . toupper(matchstr(line, '^\\h\\w*'))\n    call add(keyword_list, { 'word' : word, 'kind' : 'e' })\n  endfor\n  return keyword_list\nendfunction\n\nfunction! s:make_completion_list(list) abort\n  return map(copy(a:list), { _, val -> val !=# '' && val[-1:] ==# '/' ?\n        \\  { 'word': val[:-2], 'abbr': val } : { 'word': val }\n        \\ })\nendfunction\nfunction! s:analyze_function_line(line, keyword_dict, prototype) abort\n  \" Get script function.\n  let line = substitute(matchstr(a:line,\n        \\ '\\<fu\\%[nction]!\\?\\s\\+\\zs.*)'), '\".*$', '', '')\n  let orig_line = line\n  let word = matchstr(line, '^\\h[[:alnum:]_:#.]*()\\?')\n  if word !=# '' && !has_key(a:keyword_dict, word)\n    let a:keyword_dict[word] = {\n          \\ 'word' : word, 'abbr' : line, 'kind' : 'f'\n          \\}\n    let a:prototype[word] = orig_line[len(word):]\n  endif\nendfunction\nfunction! s:analyze_variable_line(line, keyword_dict) abort\n  if a:line =~# '\\<\\%(let\\|const\\|for\\)\\s\\+\\a[[:alnum:]_:]*'\n    \" let var = pattern.\n    let word = matchstr(a:line,\n          \\ '\\<\\%(let\\|const\\|for\\)\\s\\+\\zs\\a[[:alnum:]_:]*')\n    let expression = matchstr(a:line,\n          \\ '\\<\\%(let\\|const\\)\\s\\+\\a[[:alnum:]_:]*\\s*=\\s*\\zs.*$')\n    if !has_key(a:keyword_dict, word)\n      let a:keyword_dict[word] = {\n            \\ 'word' : word,\n            \\ 'kind' : s:get_variable_type(expression)\n            \\}\n    elseif expression !=# '' && a:keyword_dict[word].kind ==# ''\n      \" Update kind.\n      let a:keyword_dict[word].kind = s:get_variable_type(expression)\n    endif\n  elseif a:line =~# '\\<\\%(let\\|const\\|for\\)\\s\\+\\[.\\{-}\\]'\n    \" let [var1, var2] = pattern.\n    let words = split(matchstr(a:line,\n          \\'\\<\\%(let\\|const\\|for\\)\\s\\+\\[\\zs.\\{-}\\ze\\]'), '[,[:space:]]\\+')\n    let expressions = split(matchstr(a:line,\n          \\ '\\<\\%(let\\|const\\)\\s\\+\\[.\\{-}\\]\\s*=\\s*\\[\\zs.\\{-}\\ze\\]$'),\n          \\ '[,[:space:];]\\+')\n\n    let i = 0\n    while i < len(words)\n      let expression = get(expressions, i, '')\n      let word = words[i]\n\n      if !has_key(a:keyword_dict, word) \n        let a:keyword_dict[word] = {\n              \\ 'word' : word,\n              \\ 'kind' : s:get_variable_type(expression)\n              \\}\n      elseif expression !=# '' && a:keyword_dict[word].kind ==# ''\n        \" Update kind.\n        let a:keyword_dict[word].kind = s:get_variable_type(expression)\n      endif\n\n      let i += 1\n    endwhile\n  elseif a:line =~# '\\<fu\\%[nction]!\\?\\s\\+'\n    \" Get function arguments.\n    for arg in split(matchstr(a:line, '^[^(]*(\\zs[^)]*'), '\\s*,\\s*')\n      let word = 'a:' . (arg ==# '...' ?  '000' : matchstr(arg, '\\w\\+'))\n      let a:keyword_dict[word] = {\n            \\ 'word' : word,\n            \\ 'kind' : (arg ==# '...' ?  '[]' : '')\n            \\}\n\n    endfor\n    if a:line =~# '\\.\\.\\.)'\n      \" Extra arguments.\n      for arg in range(5)\n        let word = 'a:' . arg\n        let a:keyword_dict[word] = {\n              \\ 'word' : word,\n              \\ 'kind' : (arg == 0 ?  '0' : '')\n              \\}\n      endfor\n    endif\n  endif\nendfunction\nfunction! s:analyze_dictionary_variable_line(line, keyword_dict, var_name) abort\n  let let_pattern = '\\<let\\s\\+'.a:var_name.'\\.\\h\\w*'\n  let call_pattern = '\\<call\\s\\+'.a:var_name.'\\.\\h\\w*()\\?'\n\n  if a:line =~ let_pattern\n    let word = matchstr(a:line, a:var_name.'\\zs\\.\\h\\w*')\n    let kind = ''\n  elseif a:line =~ call_pattern\n    let word = matchstr(a:line, a:var_name.'\\zs\\.\\h\\w*()\\?')\n    let kind = '()'\n  else\n    let word = matchstr(a:line, a:var_name.'\\zs.\\h\\w*\\%(()\\?\\)\\?')\n    let kind = s:get_variable_type(\n          \\ matchstr(a:line, a:var_name.'\\.\\h\\w*\\zs.*$'))\n  endif\n\n  if !has_key(a:keyword_dict, word)\n    let a:keyword_dict[word] = { 'word' : word, 'kind' : kind }\n  elseif kind !=# '' && a:keyword_dict[word].kind ==# ''\n    \" Update kind.\n    let a:keyword_dict[word].kind = kind\n  endif\nendfunction\n\n\" Initialize return types.\nfunction! s:set_dictionary_helper(variable, keys, value) abort\n  for key in split(a:keys, ',')\n    let a:variable[key] = a:value\n  endfor\nendfunction\nlet s:function_return_types = {}\ncall s:set_dictionary_helper(\n      \\ s:function_return_types,\n      \\ 'len,match,matchend',\n      \\ '0')\ncall s:set_dictionary_helper(\n      \\ s:function_return_types,\n      \\ 'input,matchstr',\n      \\ '\"\"')\ncall s:set_dictionary_helper(\n      \\ s:function_return_types,\n      \\ 'expand,filter,sort,split',\n      \\ '[]')\n\nfunction! s:get_variable_type(expression) abort\n  \" Analyze variable type.\n  if a:expression =~# '^\\%(\\s*+\\)\\?\\s*\\d\\+\\.\\d\\+'\n    return '.'\n  elseif a:expression =~# '^\\%(\\s*+\\)\\?\\s*\\d\\+'\n    return '0'\n  elseif a:expression =~# '^\\%(\\s*\\.\\)\\?\\s*[\"'']'\n    return '\"\"'\n  elseif a:expression =~# '\\<function('\n    return '()'\n  elseif a:expression =~# '^\\%(\\s*+\\)\\?\\s*\\['\n    return '[]'\n  elseif a:expression =~# '^\\s*{\\|^\\.\\h[[:alnum:]_:]*'\n    return '{}'\n  elseif a:expression =~# '\\<\\h\\w*('\n    \" Function.\n    let func_name = matchstr(a:expression, '\\<\\zs\\h\\w*\\ze(')\n    return get(s:function_return_types, func_name, '')\n  else\n    return ''\n  endif\nendfunction\n\nfunction! s:set_dictionary_helper(variable, keys, pattern) abort\n  for key in split(a:keys, '\\s*,\\s*')\n    if !has_key(a:variable, key)\n      let a:variable[key] = a:pattern\n    endif\n  endfor\nendfunction\n\nfunction! s:check_global_candidates(key) abort\n  if s:global_candidates_list.runtimepath !=# &runtimepath\n    let s:global_candidates_list.runtimepath = &runtimepath\n    return 1\n  endif\n\n  return !has_key(s:global_candidates_list, a:key)\nendfunction\n\n\" Removes duplicates from a list.\nfunction! s:uniq(list) abort\n  return s:uniq_by(a:list, 'v:val')\nendfunction\n\n\" Removes duplicates from a list.\nfunction! s:uniq_by(list, f) abort\n  let list = map(copy(a:list), printf('[v:val, %s]', a:f))\n  let i = 0\n  let seen = {}\n  while i < len(list)\n    let key = string(list[i][1])\n    if has_key(seen, key)\n      call remove(list, i)\n    else\n      let seen[key] = 1\n      let i += 1\n    endif\n  endwhile\n  return map(list, { _, val -> val[0]})\nendfunction\n"
  },
  {
    "path": "autoload/necovim.vim",
    "content": "\"=============================================================================\n\" FILE: necovim.vim\n\" AUTHOR:  Shougo Matsushita <Shougo.Matsu@gmail.com>\n\" License: MIT license\n\"=============================================================================\n\n\" Global options definition.\nlet g:necovim#keyword_pattern =\n      \\ get(g:, 'necovim#keyword_pattern',\n      \\'\\h[[:alnum:]-]*=\\?\\|\\c\\[:\\%(\\h\\w*:\\]\\)\\?\\|&\\h[[:alnum:]_:]*\\|'.\n      \\'<SID>\\%(\\h\\w*\\)\\?\\|<Plug>([^)]*)\\?'.\n      \\'\\|<\\h[[:alnum:]_-]*>\\?\\|\\h[[:alnum:]_:#]*[!(]\\?\\|$\\h\\w*')\n\n\nfunction! necovim#get_complete_position(input) abort\n  if v:version < 800\n    echohl Error\n    echomsg '[neco-vim] Vim 8.0 compatible is required'\n    echohl None\n    return -1\n  endif\n\n  let cur_text = necovim#get_cur_text(a:input)\n\n  if cur_text =~# '^\\s*\"'\n    \" Comment.\n    return -1\n  endif\n\n  let pattern = '\\.\\%(\\h\\w*\\)\\?$\\|\\%(' .\n        \\ g:necovim#keyword_pattern . '\\)$'\n\n  let [complete_pos, complete_str] =\n        \\ necovim#match_word(a:input, pattern)\n  if a:input =~# '\\<e\\%[dit]\\s' || complete_pos < 0\n    \" Use args pattern.\n    let [complete_pos, complete_str] =\n          \\ necovim#match_word(a:input, '\\S\\+$')\n  endif\n\n  return complete_pos\nendfunction\n\nfunction! necovim#gather_candidates(input, complete_str) abort\n  if v:version < 800\n    echohl Error\n    echomsg '[neco-vim] Vim 8.0 compatible is required'\n    echohl None\n    return []\n  endif\n\n  let cur_text = necovim#get_cur_text(a:input)\n\n  if cur_text =~# '\\h\\w*\\.\\%(\\h\\w*\\)\\?$'\n    \" Dictionary.\n    let complete_str = matchstr(cur_text, '.\\%(\\h\\w*\\)\\?$')\n    return necovim#helper#var_dictionary(\n          \\ cur_text, complete_str)\n  elseif cur_text =~# '\\<set\\%(l\\%[ocal]\\|g\\%[lobal]\\)\\?\\s'\n    let list = necovim#helper#option(cur_text, a:complete_str)\n  elseif a:complete_str =~# '^&\\%([gl]:\\)\\?'\n    \" Options.\n    let prefix = matchstr(a:complete_str, '^&\\%([gl]:\\)\\?')\n    let list = deepcopy(necovim#helper#option(cur_text, a:complete_str))\n    for keyword in list\n      let keyword.word = prefix . keyword.word\n    endfor\n  elseif a:complete_str =~? '^\\c<sid>'\n    \" SID functions.\n    let prefix = matchstr(a:complete_str, '^\\c<sid>')\n    let complete_str = substitute(\n          \\ a:complete_str, '^\\c<sid>', 's:', '')\n    let list = deepcopy(necovim#helper#function(cur_text, complete_str))\n    for keyword in list\n      let keyword.word = prefix . keyword.word[2:]\n      let keyword.abbr = prefix .\n            \\ get(keyword, 'abbr', keyword.word)[2:]\n    endfor\n  elseif cur_text =~# '\\<let\\s'\n    let list = necovim#helper#let(cur_text, a:complete_str)\n  elseif cur_text =~# '\\<has([''\"]\\w*$'\n    \" Features.\n    let list = necovim#helper#feature(cur_text, a:complete_str)\n  elseif cur_text =~# '\\<expand([''\"][<>[:alnum:]]*$'\n    \" Expand.\n    let list = necovim#helper#expand(cur_text, a:complete_str)\n  elseif a:complete_str =~# '^\\$'\n    \" Environment.\n    let list = necovim#helper#environment(cur_text, a:complete_str)\n  else\n    \" Commands.\n    let list = necovim#helper#command(cur_text, a:complete_str)\n  endif\n\n  return list\nendfunction\n\nfunction! necovim#get_cur_text(input) abort\n  let cur_text = a:input\n  if &filetype ==# 'vimshell' && exists('*vimshell#get_secondary_prompt')\n        \\   && empty(b:vimshell.continuation)\n    return cur_text[len(vimshell#get_secondary_prompt()) :]\n  endif\n\n  let line = line('.')\n  let cnt = 0\n  while cur_text =~# '^\\s*\\\\' && line > 1 && cnt < 5\n    let cur_text = getline(line - 1) .\n          \\ substitute(cur_text, '^\\s*\\\\', '', '')\n    let line -= 1\n    let cnt += 1\n  endwhile\n\n  return split(cur_text, '\\s\\+|\\s\\+\\|<bar>', 1)[-1]\nendfunction\n\nfunction! necovim#match_word(cur_text, pattern) abort\n  let complete_pos = match(a:cur_text, a:pattern)\n\n  let complete_str = (complete_pos >=0) ?\n        \\ a:cur_text[complete_pos :] : ''\n\n  return [complete_pos, complete_str]\nendfunction\n"
  },
  {
    "path": "autoload/neocomplete/sources/vim.vim",
    "content": "\"=============================================================================\n\" FILE: vim.vim\n\" AUTHOR:  Shougo Matsushita <Shougo.Matsu@gmail.com>\n\" License: MIT license\n\"=============================================================================\n\nlet s:source = {\n      \\ 'name' : 'vim',\n      \\ 'kind' : 'manual',\n      \\ 'filetypes' : { 'vim' : 1, 'vimconsole' : 1, },\n      \\ 'mark' : '[vim]',\n      \\ 'is_volatile' : 1,\n      \\ 'rank' : 300,\n      \\ 'input_pattern' : '\\.\\w*',\n      \\}\n\nfunction! s:source.get_complete_position(context) abort\n  return necovim#get_complete_position(a:context.input)\nendfunction\n\nfunction! s:source.gather_candidates(context) abort\n  return necovim#gather_candidates(a:context.input, a:context.complete_str)\nendfunction\n\nfunction! neocomplete#sources#vim#define() abort\n  return s:source\nendfunction\n"
  },
  {
    "path": "denops/@ddc-sources/necovim.ts",
    "content": "import {\n  BaseSource,\n  Context,\n  Item,\n  Previewer,\n} from \"https://deno.land/x/ddc_vim@v4.0.4/types.ts\";\nimport { Denops, fn } from \"https://deno.land/x/ddc_vim@v4.0.4/deps.ts\";\n\ntype Params = Record<string, never>;\n\nexport class Source extends BaseSource<Params> {\n  isBytePos = true;\n\n  override async getCompletePosition(args: {\n    denops: Denops,\n    context: Context,\n  }): Promise<number> {\n    return await args.denops.call(\n      'necovim#get_complete_position', args.context.input) as number;\n  }\n\n  override async gather(args: {\n    denops: Denops,\n    context: Context,\n    completeStr: string,\n  }): Promise<Item[]> {\n    return await args.denops.call(\n        'necovim#gather_candidates',\n        args.context.input, args.completeStr) as Item[];\n  }\n\n  override async getPreviewer(args: {\n    denops: Denops,\n    item: Item;\n  }): Promise<Previewer> {\n    const help = await fn.getcompletion(args.denops, args.item.word, \"help\");\n    if (help.length === 0) {\n      return {\n        kind: \"empty\",\n      };\n    } else {\n      return {\n        kind: \"help\",\n        tag: args.item.word,\n      };\n    }\n  }\n\n  override params(): Params { return {}; }\n}\n"
  },
  {
    "path": "doc/necovim.txt",
    "content": "*necovim.txt*\tVim completion source for neocomplete/deoplete/ddc.\n\nVersion: 1.0\nAuthor: Shougo <Shougo.Matsu at gmail.com>\nLicense: MIT license\n\nCONTENTS\t\t\t\t\t*necovim-contents*\n\nIntroduction\t\t|necovim-introduction|\nInstall\t\t\t|necovim-install|\nInterface\t\t|necovim-interface|\n  Variables\t\t  |necovim-variables|\nFAQ\t\t\t|necovim-faq|\n\n==============================================================================\nINTRODUCTION\t\t\t\t\t*necovim-introduction*\n\n*neco-vim* is the Vim completion source for neocomplete/deoplete/ddc.\n\n==============================================================================\nINSTALL\t\t\t\t\t\t*necovim-install*\n\nVim 8.0+ or neovim 0.5.0+ is required.\n\n\n==============================================================================\nINTERFACE\t\t\t\t\t*necovim-interface*\n\n------------------------------------------------------------------------------\nVARIABLES \t\t\t\t\t*necovim-variables*\n\n\t\t\t\t*g:necovim#complete_functions*\ng:necovim#complete_functions\n\t\tIt which appoints vim source call function when completes\n\t\tcustom and customlist command.  The key is command name.  The\n\t\tvalue is function name.\n\n\t\tDefault value is {}.\n>\n\t\t\" Examples:\n\t\tif !exists('g:necovim#complete_functions')\n\t\t  let g:necovim#complete_functions = {}\n\t\tendif\n\t\tlet g:necovim#complete_functions.Ref =\n\t\t\\ 'ref#complete'\n<\n==============================================================================\nFAQ\t\t\t\t\t\t*necovim-faq*\n\nQ. How to enable neco-vim the completion in ddc.vim?\n\nA.\n>\n\tcall ddc#custom#patch_filetype(\n\t    \\ ['vim', 'toml'], 'sources', ['necovim'])\n\tcall ddc#custom#patch_global('sourceOptions', {\n\t    \\ '_': {\n\t    \\   'matchers': ['matcher_head'],\n\t    \\   'sorters': ['sorter_rank']\n\t    \\ },\n\t    \\ 'necovim': {'mark': 'vim'},\n\t    \\ })\n\n==============================================================================\nvim:tw=78:ts=8:ft=help:norl:noet:fen:noet:\n"
  },
  {
    "path": "plugin/necovim.vim",
    "content": "\"=============================================================================\n\" FILE: necovim.vim\n\" AUTHOR:  Shougo Matsushita <Shougo.Matsu@gmail.com>\n\" License: MIT license\n\"=============================================================================\n\naugroup necovim\n  autocmd!\n  autocmd BufWritePost,FileType vim call necovim#helper#make_cache()\n\n  \" Register source for NCM\n  autocmd User CmSetup call cm#register_source({\n        \\ 'name': 'vim',\n        \\ 'abbreviation': 'vim',\n        \\ 'priority': 9,\n        \\ 'scoping': 1,\n        \\ 'scopes': ['vim'],\n        \\ 'cm_refresh': 'cm#sources#necovim#refresh',\n        \\ 'cm_refresh_patterns': ['\\w\\+\\.$'],\n        \\ })\naugroup END\n\nlet g:loaded_necovim = 1\n"
  },
  {
    "path": "rplugin/python3/deoplete/source/vim.py",
    "content": "#=============================================================================\n# FILE: vim.py\n# AUTHOR:  Shougo Matsushita <Shougo.Matsu at gmail.com>\n# License: MIT license\n#=============================================================================\n\nfrom deoplete.base.source import Base\n\nimport deoplete.util\n\nclass Source(Base):\n    def __init__(self, vim):\n        Base.__init__(self, vim)\n\n        self.name = 'vim'\n        self.mark = '[vim]'\n        self.filetypes = ['vim']\n        self.is_bytepos = True\n        self.rank = 500\n        self.input_pattern = r'\\.\\w*'\n\n    def get_complete_position(self, context):\n        return self.vim.call('necovim#get_complete_position',\n                             context['input'])\n\n    def gather_candidates(self, context):\n        return self.vim.call('necovim#gather_candidates',\n                             context['input'],\n                             context['complete_str'])\n"
  }
]