helper.vim 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. "=============================================================================
  2. " FILE: helper.vim
  3. " AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
  4. " License: MIT license {{{
  5. " Permission is hereby granted, free of charge, to any person obtaining
  6. " a copy of this software and associated documentation files (the
  7. " "Software"), to deal in the Software without restriction, including
  8. " without limitation the rights to use, copy, modify, merge, publish,
  9. " distribute, sublicense, and/or sell copies of the Software, and to
  10. " permit persons to whom the Software is furnished to do so, subject to
  11. " the following conditions:
  12. "
  13. " The above copyright notice and this permission notice shall be included
  14. " in all copies or substantial portions of the Software.
  15. "
  16. " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20. " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22. " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. " }}}
  24. "=============================================================================
  25. let s:save_cpo = &cpo
  26. set cpo&vim
  27. function! neocomplete#helper#get_cur_text(...) abort "{{{
  28. let neocomplete = neocomplete#get_current_neocomplete()
  29. let is_skip_char = get(a:000, 0, 0)
  30. let mode = mode()
  31. if neocomplete.event ==# 'InsertEnter'
  32. let mode = 'i'
  33. endif
  34. let cur_text =
  35. \ (mode ==# 'i' ?
  36. \ (col('.')-1) : col('.')) >= len(getline('.')) ?
  37. \ getline('.') :
  38. \ matchstr(getline('.'),
  39. \ '^.*\%' . (mode ==# 'i' && !is_skip_char ?
  40. \ col('.') : col('.') - 1)
  41. \ . 'c' . (mode ==# 'i' ? '' : '.'))
  42. if cur_text =~ '^.\{-}\ze\S\+$'
  43. let complete_str = matchstr(cur_text, '\S\+$')
  44. let cur_text = matchstr(cur_text, '^.\{-}\ze\S\+$')
  45. else
  46. let complete_str = ''
  47. endif
  48. if neocomplete.event ==# 'InsertCharPre'
  49. let complete_str .= v:char
  50. endif
  51. let neocomplete.cur_text = cur_text . complete_str
  52. " Save cur_text.
  53. return neocomplete.cur_text
  54. endfunction"}}}
  55. function! neocomplete#helper#get_force_omni_complete_pos(cur_text) abort "{{{
  56. let filetype = neocomplete#get_context_filetype()
  57. let omnifunc = &l:omnifunc
  58. if neocomplete#helper#check_invalid_omnifunc(omnifunc)
  59. return -1
  60. endif
  61. let pattern = ''
  62. if has_key(g:neocomplete#force_omni_input_patterns, omnifunc)
  63. let pattern = g:neocomplete#force_omni_input_patterns[omnifunc]
  64. elseif filetype != '' &&
  65. \ get(g:neocomplete#force_omni_input_patterns, filetype, '') != ''
  66. let pattern = g:neocomplete#force_omni_input_patterns[filetype]
  67. endif
  68. if pattern == ''
  69. return -1
  70. endif
  71. return match(a:cur_text, '\%(' . pattern . '\m\)$')
  72. endfunction"}}}
  73. function! neocomplete#helper#is_enabled_source(source, filetype) abort "{{{
  74. let source = type(a:source) == type('') ?
  75. \ get(neocomplete#variables#get_sources(), a:source, {})
  76. \ : a:source
  77. return !empty(source) && (empty(source.filetypes) ||
  78. \ neocomplete#helper#check_filetype(source.filetypes))
  79. \ && (!get(source.disabled_filetypes, '_', 0) &&
  80. \ !neocomplete#helper#check_filetype(source.disabled_filetypes))
  81. endfunction"}}}
  82. function! neocomplete#helper#get_source_filetypes(filetype) abort "{{{
  83. return neocomplete#context_filetype#filetypes()
  84. endfunction"}}}
  85. function! neocomplete#helper#complete_check() abort "{{{
  86. let neocomplete = neocomplete#get_current_neocomplete()
  87. if g:neocomplete#enable_debug
  88. echomsg split(reltimestr(reltime(neocomplete.start_time)))[0]
  89. endif
  90. let ret =
  91. \ neocomplete#is_auto_complete()
  92. \ && g:neocomplete#skip_auto_completion_time != ''
  93. \ && split(reltimestr(reltime(neocomplete.start_time)))[0] >
  94. \ g:neocomplete#skip_auto_completion_time
  95. if ret
  96. let neocomplete = neocomplete#get_current_neocomplete()
  97. let neocomplete.skipped = 1
  98. call neocomplete#print_debug('Skipped.')
  99. endif
  100. return ret
  101. endfunction"}}}
  102. function! neocomplete#helper#get_syn_name(is_trans) abort "{{{
  103. return len(getline('.')) < 200 ?
  104. \ synIDattr(synIDtrans(synID(line('.'), mode() ==# 'i' ?
  105. \ col('.')-1 : col('.'), a:is_trans)), 'name') : ''
  106. endfunction"}}}
  107. function! neocomplete#helper#match_word(cur_text, ...) abort "{{{
  108. let pattern = a:0 >= 1 ? a:1 : neocomplete#get_keyword_pattern_end()
  109. " Check wildcard.
  110. let complete_pos = match(a:cur_text, pattern)
  111. let complete_str = (complete_pos >=0) ?
  112. \ a:cur_text[complete_pos :] : ''
  113. return [complete_pos, complete_str]
  114. endfunction"}}}
  115. function! neocomplete#helper#filetype_complete(arglead, cmdline, cursorpos) abort "{{{
  116. " Dup check.
  117. let ret = {}
  118. for item in map(
  119. \ split(globpath(&runtimepath, 'syntax/*.vim'), '\n') +
  120. \ split(globpath(&runtimepath, 'indent/*.vim'), '\n') +
  121. \ split(globpath(&runtimepath, 'ftplugin/*.vim'), '\n')
  122. \ , 'fnamemodify(v:val, ":t:r")')
  123. if !has_key(ret, item) && item =~ '^'.a:arglead
  124. let ret[item] = 1
  125. endif
  126. endfor
  127. return sort(keys(ret))
  128. endfunction"}}}
  129. function! neocomplete#helper#unite_patterns(pattern_var, filetype) abort "{{{
  130. let keyword_patterns = []
  131. lua << EOF
  132. do
  133. local patterns = vim.eval('keyword_patterns')
  134. local filetypes = vim.eval("split(a:filetype, '\\.')")
  135. local pattern_var = vim.eval('a:pattern_var')
  136. local dup_check = {}
  137. for i = 0, #filetypes-1 do
  138. local ft = filetypes[i]
  139. -- Composite filetype.
  140. if pattern_var[ft] ~= nil and dup_check[ft] == nil then
  141. dup_check[ft] = 1
  142. patterns:add(pattern_var[ft])
  143. end
  144. end
  145. if #patterns == 0 then
  146. local default = pattern_var['_']
  147. if default == nil then
  148. default = pattern_var['default']
  149. end
  150. if default ~= nil and default ~= '' then
  151. patterns:add(default)
  152. end
  153. end
  154. end
  155. EOF
  156. return join(keyword_patterns, '\m\|')
  157. endfunction"}}}
  158. function! neocomplete#helper#check_filetype(dictionary) abort "{{{
  159. return !empty(filter(neocomplete#context_filetype#filetypes(),
  160. \ 'get(a:dictionary, v:val, 0)'))
  161. endfunction"}}}
  162. function! neocomplete#helper#get_sources_list(...) abort "{{{
  163. let filetype = neocomplete#get_context_filetype()
  164. let source_names = exists('b:neocomplete_sources') ?
  165. \ b:neocomplete_sources :
  166. \ get(a:000, 0,
  167. \ get(g:neocomplete#sources, filetype,
  168. \ get(g:neocomplete#sources, '_', ['_'])))
  169. call neocomplete#init#_sources(source_names)
  170. let all_sources = neocomplete#available_sources()
  171. let sources = {}
  172. for source_name in source_names
  173. if source_name ==# '_'
  174. " All sources.
  175. let sources = all_sources
  176. break
  177. endif
  178. if !has_key(all_sources, source_name)
  179. call neocomplete#print_warning(printf(
  180. \ 'Invalid source name "%s" is given.', source_name))
  181. continue
  182. endif
  183. let sources[source_name] = all_sources[source_name]
  184. endfor
  185. let neocomplete = neocomplete#get_current_neocomplete()
  186. let neocomplete.sources = filter(sources, "
  187. \ empty(v:val.filetypes) ||
  188. \ neocomplete#helper#check_filetype(v:val.filetypes)")
  189. let neocomplete.sources_filetype = neocomplete.context_filetype
  190. return neocomplete.sources
  191. endfunction"}}}
  192. function! neocomplete#helper#clear_result() abort "{{{
  193. let neocomplete = neocomplete#get_current_neocomplete()
  194. let neocomplete.complete_str = ''
  195. let neocomplete.candidates = []
  196. let neocomplete.complete_sources = []
  197. let neocomplete.complete_pos = -1
  198. " Restore completeopt.
  199. if neocomplete.completeopt !=# &completeopt
  200. " Restore completeopt.
  201. let &completeopt = neocomplete.completeopt
  202. endif
  203. endfunction"}}}
  204. function! neocomplete#helper#call_hook(sources, hook_name, context) abort "{{{
  205. for source in neocomplete#util#convert2list(a:sources)
  206. try
  207. if has_key(source.hooks, a:hook_name)
  208. call call(source.hooks[a:hook_name],
  209. \ [extend(source.neocomplete__context, a:context)],
  210. \ source.hooks)
  211. endif
  212. catch
  213. call neocomplete#print_error(v:throwpoint)
  214. call neocomplete#print_error(v:exception)
  215. call neocomplete#print_error(
  216. \ 'Error occurred in calling hook "' . a:hook_name . '"!')
  217. call neocomplete#print_error(
  218. \ 'Source name is ' . source.name)
  219. endtry
  220. endfor
  221. endfunction"}}}
  222. function! neocomplete#helper#call_filters(filters, source, context) abort "{{{
  223. let context = extend(a:source.neocomplete__context, a:context)
  224. for filter in a:filters
  225. try
  226. let context.candidates = call(filter.filter, [context], filter)
  227. catch
  228. call neocomplete#print_error(v:throwpoint)
  229. call neocomplete#print_error(v:exception)
  230. call neocomplete#print_error(
  231. \ 'Error occurred in calling filter '
  232. \ . filter.name . '!')
  233. call neocomplete#print_error(
  234. \ 'Source name is ' . a:source.name)
  235. endtry
  236. endfor
  237. return context.candidates
  238. endfunction"}}}
  239. function! neocomplete#helper#sort_human(candidates) abort "{{{
  240. " Use lua interface.
  241. lua << EOF
  242. do
  243. local candidates = vim.eval('a:candidates')
  244. local t = {}
  245. for i = 1, #candidates do
  246. t[i] = candidates[i-1]
  247. end
  248. table.sort(t, function(a, b) return a.word < b.word end)
  249. for i = 0, #candidates-1 do
  250. candidates[i] = t[i+1]
  251. end
  252. end
  253. EOF
  254. return a:candidates
  255. endfunction"}}}
  256. function! neocomplete#helper#check_invalid_omnifunc(omnifunc) abort "{{{
  257. return a:omnifunc == '' || (a:omnifunc !~ '#' && !exists('*' . a:omnifunc))
  258. endfunction"}}}
  259. function! neocomplete#helper#indent_current_line() abort "{{{
  260. let pos = getpos('.')
  261. let len = len(getline('.'))
  262. let equalprg = &l:equalprg
  263. try
  264. setlocal equalprg=
  265. silent normal! ==
  266. finally
  267. let &l:equalprg = equalprg
  268. let pos[2] += len(getline('.')) - len
  269. call setpos('.', pos)
  270. endtry
  271. endfunction"}}}
  272. function! neocomplete#helper#complete_configure() abort "{{{
  273. set completeopt-=menu
  274. set completeopt-=longest
  275. set completeopt+=menuone
  276. " Set options.
  277. let neocomplete = neocomplete#get_current_neocomplete()
  278. let neocomplete.completeopt = &completeopt
  279. if neocomplete#util#is_complete_select()
  280. \ && &completeopt !~# 'noinsert\|noselect'
  281. if g:neocomplete#enable_auto_select
  282. set completeopt-=noselect
  283. set completeopt+=noinsert
  284. else
  285. set completeopt-=noinsert
  286. set completeopt+=noselect
  287. endif
  288. endif
  289. endfunction"}}}
  290. function! neocomplete#helper#clean(directory) abort "{{{
  291. let directory = neocomplete#get_data_directory() .'/'.a:directory
  292. for file in split(glob(directory . '/*'), '\n')
  293. let orig = substitute(substitute(fnamemodify(file, ':t'),
  294. \ '=-', ':', 'g'), '=+', '/', 'g')
  295. if !filereadable(orig)
  296. call delete(file)
  297. endif
  298. endfor
  299. endfunction"}}}
  300. let &cpo = s:save_cpo
  301. unlet s:save_cpo
  302. " vim: foldmethod=marker