omni.vim 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. "=============================================================================
  2. " FILE: omni.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. " Global options definition. "{{{
  28. let g:neocomplete#sources#omni#functions =
  29. \ get(g:, 'neocomplete#sources#omni#functions', {})
  30. let g:neocomplete#sources#omni#input_patterns =
  31. \ get(g:, 'neocomplete#sources#omni#input_patterns', {})
  32. "}}}
  33. let s:source = {
  34. \ 'name' : 'omni',
  35. \ 'kind' : 'manual',
  36. \ 'mark' : '[O]',
  37. \ 'rank' : 50,
  38. \ 'min_pattern_length' : 0,
  39. \ 'hooks' : {},
  40. \}
  41. let s:List = neocomplete#util#get_vital().import('Data.List')
  42. function! s:source.hooks.on_init(context) abort "{{{
  43. " Initialize omni completion pattern. "{{{
  44. call neocomplete#util#set_default_dictionary(
  45. \'g:neocomplete#sources#omni#input_patterns',
  46. \'html,xhtml,xml,markdown,mkd',
  47. \'<\|\s[[:alnum:]-]*')
  48. call neocomplete#util#set_default_dictionary(
  49. \'g:neocomplete#sources#omni#input_patterns',
  50. \'css,scss,sass',
  51. \'\w\{' . g:neocomplete#min_keyword_length . '\}\|\w\+[):;]\s*\w*\|[@!]')
  52. call neocomplete#util#set_default_dictionary(
  53. \'g:neocomplete#sources#omni#input_patterns',
  54. \'javascript',
  55. \'[^. \t]\.\%(\h\w*\)\?')
  56. call neocomplete#util#set_default_dictionary(
  57. \'g:neocomplete#sources#omni#input_patterns',
  58. \'actionscript',
  59. \'[^. \t][.:]\h\w*')
  60. "call neocomplete#util#set_default_dictionary(
  61. "\'g:neocomplete#sources#omni#input_patterns',
  62. "\'php',
  63. "\'[^. \t]->\h\w*\|\h\w*::\w*')
  64. call neocomplete#util#set_default_dictionary(
  65. \'g:neocomplete#sources#omni#input_patterns',
  66. \'java',
  67. \'\%(\h\w*\|)\)\.\w*')
  68. "call neocomplete#util#set_default_dictionary(
  69. "\'g:neocomplete#sources#omni#input_patterns',
  70. "\'perl',
  71. "\'\h\w*->\h\w*\|\h\w*::\w*')
  72. "call neocomplete#util#set_default_dictionary(
  73. "\'g:neocomplete#sources#omni#input_patterns',
  74. "\'c',
  75. "\'[^.[:digit:] *\t]\%(\.\|->\)\w*'
  76. "call neocomplete#util#set_default_dictionary(
  77. "\'g:neocomplete#sources#omni#input_patterns',
  78. "\'cpp',
  79. "\'[^.[:digit:] *\t]\%(\.\|->\)\w*\|\h\w*::\w*')
  80. call neocomplete#util#set_default_dictionary(
  81. \'g:neocomplete#sources#omni#input_patterns',
  82. \'objc',
  83. \'[^.[:digit:] *\t]\%(\.\|->\)\w*')
  84. call neocomplete#util#set_default_dictionary(
  85. \'g:neocomplete#sources#omni#input_patterns',
  86. \'objj',
  87. \'[\[ \.]\w\+$\|:\w*$')
  88. call neocomplete#util#set_default_dictionary(
  89. \'g:neocomplete#sources#omni#input_patterns',
  90. \'go',
  91. \'[^.[:digit:] *\t]\.\w*')
  92. call neocomplete#util#set_default_dictionary(
  93. \'g:neocomplete#sources#omni#input_patterns',
  94. \'clojure',
  95. \'\%(([^)]\+\)\|\*[[:alnum:]_-]\+')
  96. call neocomplete#util#set_default_dictionary(
  97. \'g:neocomplete#sources#omni#input_patterns',
  98. \'rust',
  99. \'[^.[:digit:] *\t]\%(\.\|\::\)\%(\h\w*\)\?')
  100. " External language interface check.
  101. if has('ruby')
  102. " call neocomplete#util#set_default_dictionary(
  103. "\'g:neocomplete#sources#omni#input_patterns', 'ruby',
  104. "\'[^. *\t]\.\h\w*\|\h\w*::\w*')
  105. endif
  106. if has('python') || has('python3')
  107. call neocomplete#util#set_default_dictionary(
  108. \'g:neocomplete#sources#omni#input_patterns',
  109. \'python', '[^. \t]\.\w*')
  110. endif
  111. "}}}
  112. endfunction"}}}
  113. function! s:source.get_complete_position(context) abort "{{{
  114. let a:context.source__complete_results =
  115. \ s:set_complete_results_pos(
  116. \ s:get_omni_funcs(a:context.filetype), a:context.input)
  117. return s:get_complete_pos(a:context.source__complete_results)
  118. endfunction"}}}
  119. function! s:source.gather_candidates(context) abort "{{{
  120. return s:get_candidates(
  121. \ s:set_complete_results_words(
  122. \ a:context.source__complete_results),
  123. \ a:context.complete_pos, a:context.complete_str)
  124. endfunction"}}}
  125. function! neocomplete#sources#omni#define() abort "{{{
  126. return s:source
  127. endfunction"}}}
  128. function! s:get_omni_funcs(filetype) abort "{{{
  129. let funcs = []
  130. for ft in insert(split(a:filetype, '\.'), '_')
  131. let omnifuncs = neocomplete#util#convert2list(
  132. \ get(g:neocomplete#sources#omni#functions, ft, &l:omnifunc))
  133. for omnifunc in omnifuncs
  134. if neocomplete#helper#check_invalid_omnifunc(omnifunc)
  135. " omnifunc is irregal.
  136. continue
  137. endif
  138. if get(g:neocomplete#sources#omni#input_patterns, omnifunc, '') != ''
  139. let pattern = g:neocomplete#sources#omni#input_patterns[omnifunc]
  140. elseif get(g:neocomplete#sources#omni#input_patterns, ft, '') != ''
  141. let pattern = g:neocomplete#sources#omni#input_patterns[ft]
  142. else
  143. let pattern = ''
  144. endif
  145. if pattern == ''
  146. continue
  147. endif
  148. call add(funcs, [omnifunc, pattern])
  149. endfor
  150. endfor
  151. return s:List.uniq(funcs)
  152. endfunction"}}}
  153. function! s:get_omni_list(list) abort "{{{
  154. let omni_list = []
  155. " Convert string list.
  156. for val in deepcopy(a:list)
  157. let dict = (type(val) == type('') ?
  158. \ { 'word' : val } : val)
  159. call add(omni_list, dict)
  160. unlet val
  161. endfor
  162. return omni_list
  163. endfunction"}}}
  164. function! s:set_complete_results_pos(funcs, cur_text) abort "{{{
  165. " Try omnifunc completion. "{{{
  166. let complete_results = {}
  167. for [omnifunc, pattern] in a:funcs
  168. if neocomplete#is_auto_complete()
  169. \ && (pattern == ''
  170. \ || a:cur_text !~# '\%(' . pattern . '\m\)$')
  171. continue
  172. endif
  173. " Save pos.
  174. let pos = getpos('.')
  175. try
  176. let complete_pos = call(omnifunc, [1, ''])
  177. catch
  178. call neocomplete#print_error(
  179. \ 'Error occurred calling omnifunction: ' . omnifunc)
  180. call neocomplete#print_error(v:throwpoint)
  181. call neocomplete#print_error(v:exception)
  182. let complete_pos = -1
  183. finally
  184. if getpos('.') != pos
  185. call setpos('.', pos)
  186. endif
  187. endtry
  188. if complete_pos < 0
  189. continue
  190. endif
  191. let complete_str = a:cur_text[complete_pos :]
  192. let complete_results[omnifunc] = {
  193. \ 'candidates' : [],
  194. \ 'complete_pos' : complete_pos,
  195. \ 'complete_str' : complete_str,
  196. \ 'omnifunc' : omnifunc,
  197. \}
  198. endfor
  199. "}}}
  200. return complete_results
  201. endfunction"}}}
  202. function! s:set_complete_results_words(complete_results) abort "{{{
  203. " Try source completion.
  204. for [omnifunc, result] in items(a:complete_results)
  205. if neocomplete#complete_check()
  206. return a:complete_results
  207. endif
  208. let pos = getpos('.')
  209. try
  210. let ret = call(omnifunc, [0, result.complete_str])
  211. let list = type(ret) == type(0) ? [] :
  212. \ type(ret) == type([]) ? ret : ret.words
  213. catch
  214. call neocomplete#print_error(
  215. \ 'Error occurred calling omnifunction: ' . omnifunc)
  216. call neocomplete#print_error(v:throwpoint)
  217. call neocomplete#print_error(v:exception)
  218. let list = []
  219. finally
  220. call setpos('.', pos)
  221. endtry
  222. let list = s:get_omni_list(list)
  223. let result.candidates = list
  224. endfor
  225. return a:complete_results
  226. endfunction"}}}
  227. function! s:get_complete_pos(complete_results) abort "{{{
  228. if empty(a:complete_results)
  229. return -1
  230. endif
  231. let complete_pos = col('.')
  232. for result in values(a:complete_results)
  233. if complete_pos > result.complete_pos
  234. let complete_pos = result.complete_pos
  235. endif
  236. endfor
  237. return complete_pos
  238. endfunction"}}}
  239. function! s:get_candidates(complete_results, complete_pos, complete_str) abort "{{{
  240. " Append prefix.
  241. let candidates = []
  242. for result in values(a:complete_results)
  243. if result.complete_pos > a:complete_pos
  244. let prefix = a:complete_str[: result.complete_pos
  245. \ - a:complete_pos - 1]
  246. for keyword in result.candidates
  247. let keyword.word = prefix . keyword.word
  248. endfor
  249. endif
  250. let candidates += result.candidates
  251. endfor
  252. return candidates
  253. endfunction"}}}
  254. let &cpo = s:save_cpo
  255. unlet s:save_cpo
  256. " vim: foldmethod=marker