handler.vim 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. "=============================================================================
  2. " FILE: handler.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#handler#_on_moved_i() abort "{{{
  28. let neocomplete = neocomplete#get_current_neocomplete()
  29. if neocomplete.linenr != line('.')
  30. call neocomplete#helper#clear_result()
  31. endif
  32. let neocomplete.linenr = line('.')
  33. call s:close_preview_window()
  34. endfunction"}}}
  35. function! neocomplete#handler#_on_insert_enter() abort "{{{
  36. if !neocomplete#is_enabled()
  37. return
  38. endif
  39. let neocomplete = neocomplete#get_current_neocomplete()
  40. if neocomplete.linenr != line('.')
  41. call neocomplete#helper#clear_result()
  42. endif
  43. let neocomplete.linenr = line('.')
  44. if &l:foldmethod ==# 'expr' && foldlevel('.') != 0
  45. foldopen
  46. endif
  47. endfunction"}}}
  48. function! neocomplete#handler#_on_insert_leave() abort "{{{
  49. call neocomplete#helper#clear_result()
  50. call s:close_preview_window()
  51. call s:make_cache_current_line()
  52. let neocomplete = neocomplete#get_current_neocomplete()
  53. let neocomplete.cur_text = ''
  54. endfunction"}}}
  55. function! neocomplete#handler#_on_complete_done() abort "{{{
  56. let neocomplete = neocomplete#get_current_neocomplete()
  57. if neocomplete.event !=# 'mapping'
  58. \ && !s:is_delimiter() && !get(neocomplete, 'refresh', 0)
  59. call neocomplete#mappings#close_popup()
  60. endif
  61. " Use v:completed_item feature.
  62. if !exists('v:completed_item') || empty(v:completed_item)
  63. return
  64. endif
  65. let complete_str = v:completed_item.word
  66. if complete_str == ''
  67. return
  68. endif
  69. let frequencies = neocomplete#variables#get_frequencies()
  70. if !has_key(frequencies, complete_str)
  71. let frequencies[complete_str] = 20
  72. else
  73. let frequencies[complete_str] += 20
  74. endif
  75. endfunction"}}}
  76. function! neocomplete#handler#_on_insert_char_pre() abort "{{{
  77. let neocomplete = neocomplete#get_current_neocomplete()
  78. let neocomplete.skip_next_complete = 0
  79. if pumvisible() && g:neocomplete#enable_refresh_always
  80. " Auto refresh
  81. call feedkeys("\<Plug>(neocomplete_auto_refresh)")
  82. endif
  83. if neocomplete#is_cache_disabled()
  84. return
  85. endif
  86. let neocomplete.old_char = v:char
  87. endfunction"}}}
  88. function! neocomplete#handler#_on_text_changed() abort "{{{
  89. if neocomplete#is_cache_disabled()
  90. return
  91. endif
  92. if getline('.') == ''
  93. call s:make_cache_current_line()
  94. endif
  95. if !neocomplete#util#is_text_changed()
  96. call s:indent_current_line()
  97. endif
  98. endfunction"}}}
  99. function! s:complete_delay(timer) abort "{{{
  100. let event = s:timer.event
  101. unlet! s:timer
  102. if mode() ==# 'i'
  103. call s:do_auto_complete(event)
  104. endif
  105. endfunction"}}}
  106. function! neocomplete#handler#_do_auto_complete(event) abort "{{{
  107. if s:check_in_do_auto_complete(a:event)
  108. return
  109. endif
  110. if g:neocomplete#auto_complete_delay > 0 && has('timers')
  111. \ && (!has('gui_macvim') || has('patch-8.0.95'))
  112. if exists('s:timer')
  113. call timer_stop(s:timer.id)
  114. endif
  115. if a:event !=# 'Manual'
  116. let s:timer = { 'event': a:event }
  117. let s:timer.id = timer_start(
  118. \ g:neocomplete#auto_complete_delay,
  119. \ function('s:complete_delay'))
  120. return
  121. endif
  122. endif
  123. return s:do_auto_complete(a:event)
  124. endfunction"}}}
  125. function! s:do_auto_complete(event) abort "{{{
  126. let neocomplete = neocomplete#get_current_neocomplete()
  127. if s:check_in_do_auto_complete(a:event)
  128. return
  129. endif
  130. let neocomplete.skipped = 0
  131. let neocomplete.event = a:event
  132. call neocomplete#helper#clear_result()
  133. " Set context filetype.
  134. call neocomplete#context_filetype#set()
  135. let cur_text = neocomplete#get_cur_text(1)
  136. let complete_pos = -1
  137. call neocomplete#print_debug('cur_text = ' . cur_text)
  138. try
  139. " Prevent infinity loop.
  140. if s:is_skip_auto_complete(cur_text)
  141. call neocomplete#print_debug('Skipped.')
  142. return
  143. endif
  144. let complete_pos = s:check_force_omni(cur_text)
  145. if complete_pos >= 0
  146. return
  147. endif
  148. " Check multibyte input or eskk or spaces.
  149. if cur_text =~ '^\s*$'
  150. \ || (!neocomplete#is_eskk_enabled()
  151. \ && neocomplete#is_multibyte_input(cur_text))
  152. call neocomplete#print_debug('Skipped.')
  153. return
  154. endif
  155. try
  156. let neocomplete.is_auto_complete = 1
  157. " Do prefetch.
  158. let neocomplete.complete_sources =
  159. \ neocomplete#complete#_get_results(cur_text)
  160. finally
  161. let neocomplete.is_auto_complete = 0
  162. endtry
  163. if empty(neocomplete.complete_sources)
  164. call s:check_fallback(cur_text)
  165. return
  166. endif
  167. " Start auto complete.
  168. call s:complete_key(
  169. \ "\<Plug>(neocomplete_start_auto_complete)")
  170. finally
  171. call neocomplete#complete#_set_previous_position(cur_text, complete_pos)
  172. endtry
  173. endfunction"}}}
  174. function! s:check_in_do_auto_complete(event) abort "{{{
  175. if neocomplete#is_locked()
  176. \ || (a:event !=# 'InsertEnter' && mode() !=# 'i')
  177. return 1
  178. endif
  179. " Detect completefunc.
  180. if &l:completefunc != '' && &l:buftype =~ 'nofile'
  181. return 1
  182. endif
  183. endfunction"}}}
  184. function! s:is_skip_auto_complete(cur_text) abort "{{{
  185. let neocomplete = neocomplete#get_current_neocomplete()
  186. if (g:neocomplete#lock_iminsert && &l:iminsert)
  187. \ || (&l:formatoptions =~# '[tca]' && &l:textwidth > 0
  188. \ && strdisplaywidth(a:cur_text) >= &l:textwidth)
  189. let neocomplete.skip_next_complete = 0
  190. return 1
  191. endif
  192. let skip = neocomplete.skip_next_complete
  193. if !skip || s:is_delimiter()
  194. return 0
  195. endif
  196. let neocomplete.skip_next_complete = 0
  197. return skip
  198. endfunction"}}}
  199. function! s:close_preview_window() abort "{{{
  200. if g:neocomplete#enable_auto_close_preview
  201. \ && bufname('%') !=# '[Command Line]'
  202. \ && winnr('$') != 1 && !&l:previewwindow
  203. \ && !neocomplete#is_cache_disabled()
  204. " Close preview window.
  205. pclose!
  206. endif
  207. endfunction"}}}
  208. function! s:make_cache_current_line() abort "{{{
  209. let neocomplete = neocomplete#get_current_neocomplete()
  210. if neocomplete#helper#is_enabled_source('buffer',
  211. \ neocomplete.context_filetype)
  212. " Caching current cache line.
  213. call neocomplete#sources#buffer#make_cache_current_line()
  214. endif
  215. if neocomplete#helper#is_enabled_source('member',
  216. \ neocomplete.context_filetype)
  217. " Caching current cache line.
  218. call neocomplete#sources#member#make_cache_current_line()
  219. endif
  220. endfunction"}}}
  221. function! s:check_force_omni(cur_text) abort "{{{
  222. let cur_text = a:cur_text
  223. let complete_pos = neocomplete#helper#get_force_omni_complete_pos(cur_text)
  224. if complete_pos >= 0
  225. \ && !neocomplete#complete#_check_previous_position(
  226. \ cur_text, complete_pos)
  227. call s:complete_key("\<Plug>(neocomplete_start_omni_complete)")
  228. endif
  229. return complete_pos
  230. endfunction"}}}
  231. function! s:check_fallback(cur_text) abort "{{{
  232. let cur_text = a:cur_text
  233. let complete_pos = match(cur_text, '\h\w*$')
  234. let neocomplete = neocomplete#get_current_neocomplete()
  235. if empty(g:neocomplete#fallback_mappings)
  236. \ || len(matchstr(cur_text, '\h\w*$'))
  237. \ < g:neocomplete#auto_completion_start_length
  238. \ || neocomplete.skip_next_complete
  239. \ || neocomplete#complete#_check_previous_position(
  240. \ cur_text, complete_pos)
  241. return
  242. endif
  243. let key = ''
  244. for i in range(0, len(g:neocomplete#fallback_mappings)-1)
  245. let key .= '<C-r>=neocomplete#mappings#fallback(' . i . ')<CR>'
  246. endfor
  247. execute 'inoremap <silent> <Plug>(neocomplete_fallback)' key
  248. " Fallback
  249. call s:complete_key("\<Plug>(neocomplete_fallback)")
  250. endfunction"}}}
  251. function! s:complete_key(key) abort "{{{
  252. call neocomplete#helper#complete_configure()
  253. if has('patch-7.4.601')
  254. call feedkeys(a:key, 'i')
  255. else
  256. call feedkeys(a:key)
  257. endif
  258. endfunction"}}}
  259. function! s:indent_current_line() abort "{{{
  260. " indent line matched by indentkeys
  261. let neocomplete = neocomplete#get_current_neocomplete()
  262. let cur_text = matchstr(getline('.'), '^.*\%'.col('.').'c')
  263. if neocomplete.indent_text == matchstr(getline('.'), '\S.*$')
  264. return
  265. endif
  266. for word in filter(map(split(&l:indentkeys, ','),
  267. \ "v:val =~ '^<.*>$' ? matchstr(v:val, '^<\\zs.*\\ze>$')
  268. \ : matchstr(v:val, ':\\|e\\|=\\zs.*')"),
  269. \ "v:val != ''")
  270. if word ==# 'e'
  271. let word = 'else'
  272. endif
  273. let lastpos = len(cur_text)-len(word)
  274. if lastpos >= 0 && strridx(cur_text, word) == lastpos
  275. call neocomplete#helper#indent_current_line()
  276. let neocomplete.indent_text = matchstr(getline('.'), '\S.*$')
  277. break
  278. endif
  279. endfor
  280. endfunction"}}}
  281. function! s:is_delimiter() abort "{{{
  282. " Check delimiter pattern.
  283. let is_delimiter = 0
  284. let cur_text = neocomplete#get_cur_text(1)
  285. for delimiter in ['/']
  286. if stridx(cur_text, delimiter,
  287. \ len(cur_text) - len(delimiter)) >= 0
  288. let is_delimiter = 1
  289. break
  290. endif
  291. endfor
  292. return is_delimiter
  293. endfunction"}}}
  294. let &cpo = s:save_cpo
  295. unlet s:save_cpo
  296. " vim: foldmethod=marker