youcompleteme.vim 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. " Copyright (C) 2011-2018 YouCompleteMe contributors
  2. "
  3. " This file is part of YouCompleteMe.
  4. "
  5. " YouCompleteMe is free software: you can redistribute it and/or modify
  6. " it under the terms of the GNU General Public License as published by
  7. " the Free Software Foundation, either version 3 of the License, or
  8. " (at your option) any later version.
  9. "
  10. " YouCompleteMe is distributed in the hope that it will be useful,
  11. " but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. " GNU General Public License for more details.
  14. "
  15. " You should have received a copy of the GNU General Public License
  16. " along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
  17. " This is basic vim plugin boilerplate
  18. let s:save_cpo = &cpo
  19. set cpo&vim
  20. " This needs to be called outside of a function
  21. let s:script_folder_path = escape( expand( '<sfile>:p:h' ), '\' )
  22. let s:force_semantic = 0
  23. let s:completion_stopped = 0
  24. " These two variables are initialized in youcompleteme#Enable.
  25. let s:default_completion = {}
  26. let s:completion = s:default_completion
  27. let s:default_signature_help = {}
  28. let s:signature_help = s:default_completion
  29. let s:previous_allowed_buffer_number = 0
  30. let s:pollers = {
  31. \ 'completion': {
  32. \ 'id': -1,
  33. \ 'wait_milliseconds': 10
  34. \ },
  35. \ 'signature_help': {
  36. \ 'id': -1,
  37. \ 'wait_milliseconds': 10
  38. \ },
  39. \ 'file_parse_response': {
  40. \ 'id': -1,
  41. \ 'wait_milliseconds': 100
  42. \ },
  43. \ 'server_ready': {
  44. \ 'id': -1,
  45. \ 'wait_milliseconds': 100
  46. \ },
  47. \ 'receive_messages': {
  48. \ 'id': -1,
  49. \ 'wait_milliseconds': 100
  50. \ }
  51. \ }
  52. let s:buftype_blacklist = {
  53. \ 'help': 1,
  54. \ 'terminal': 1,
  55. \ 'quickfix': 1
  56. \ }
  57. " When both versions are available, we prefer Python 3 over Python 2:
  58. " - faster startup (no monkey-patching from python-future);
  59. " - better Windows support (e.g. temporary paths are not returned in all
  60. " lowercase);
  61. " - Python 2 support will eventually be dropped.
  62. function! s:UsingPython3()
  63. if has('python3')
  64. return 1
  65. endif
  66. return 0
  67. endfunction
  68. let s:using_python3 = s:UsingPython3()
  69. let s:python_until_eof = s:using_python3 ? "python3 << EOF" : "python << EOF"
  70. let s:python_command = s:using_python3 ? "py3 " : "py "
  71. function! s:Pyeval( eval_string )
  72. if s:using_python3
  73. return py3eval( a:eval_string )
  74. endif
  75. return pyeval( a:eval_string )
  76. endfunction
  77. function! s:StartMessagePoll()
  78. if s:pollers.receive_messages.id < 0
  79. let s:pollers.receive_messages.id = timer_start(
  80. \ s:pollers.receive_messages.wait_milliseconds,
  81. \ function( 's:ReceiveMessages' ) )
  82. endif
  83. endfunction
  84. function! s:ReceiveMessages( timer_id )
  85. let poll_again = s:Pyeval( 'ycm_state.OnPeriodicTick()' )
  86. if poll_again
  87. let s:pollers.receive_messages.id = timer_start(
  88. \ s:pollers.receive_messages.wait_milliseconds,
  89. \ function( 's:ReceiveMessages' ) )
  90. else
  91. " Don't poll again until we open another buffer
  92. let s:pollers.receive_messages.id = -1
  93. endif
  94. endfunction
  95. function! s:SetUpOptions()
  96. call s:SetUpCommands()
  97. call s:SetUpCpoptions()
  98. call s:SetUpCompleteopt()
  99. call s:SetUpKeyMappings()
  100. if g:ycm_show_diagnostics_ui
  101. call s:TurnOffSyntasticForCFamily()
  102. endif
  103. call s:SetUpSigns()
  104. call s:SetUpSyntaxHighlighting()
  105. endfunction
  106. function! youcompleteme#Enable()
  107. call s:SetUpBackwardsCompatibility()
  108. if !s:SetUpPython()
  109. return
  110. endif
  111. call s:SetUpOptions()
  112. call youcompleteme#EnableCursorMovedAutocommands()
  113. augroup youcompleteme
  114. autocmd!
  115. " Note that these events will NOT trigger for the file vim is started with;
  116. " so if you do "vim foo.cc", these events will not trigger when that buffer
  117. " is read. This is because youcompleteme#Enable() is called on VimEnter and
  118. " that happens *after* FileType has already triggered for the initial file.
  119. " We don't parse the buffer on the BufRead event since it would only be
  120. " useful if the buffer filetype is set (we ignore the buffer if there is no
  121. " filetype) and if so, the FileType event has triggered before and thus the
  122. " buffer is already parsed.
  123. autocmd FileType * call s:OnFileTypeSet()
  124. autocmd BufEnter,CmdwinEnter * call s:OnBufferEnter()
  125. autocmd BufUnload * call s:OnBufferUnload()
  126. autocmd InsertLeave * call s:OnInsertLeave()
  127. autocmd VimLeave * call s:OnVimLeave()
  128. autocmd CompleteDone * call s:OnCompleteDone()
  129. if exists( '##CompleteChanged' )
  130. autocmd CompleteChanged * call s:OnCompleteChanged()
  131. endif
  132. autocmd BufEnter,WinEnter * call s:UpdateMatches()
  133. augroup END
  134. " The FileType event is not triggered for the first loaded file. We wait until
  135. " the server is ready to manually run the s:OnFileTypeSet function.
  136. let s:pollers.server_ready.id = timer_start(
  137. \ s:pollers.server_ready.wait_milliseconds,
  138. \ function( 's:PollServerReady' ) )
  139. let s:default_completion = s:Pyeval( 'vimsupport.NO_COMPLETIONS' )
  140. let s:completion = s:default_completion
  141. if exists( '*prop_type_add' ) && exists( '*prop_type_delete' )
  142. call prop_type_delete( 'YCM-signature-help-current-argument' )
  143. call prop_type_delete( 'YCM-signature-help-current-signature' )
  144. call prop_type_delete( 'YCM-signature-help-signature' )
  145. call prop_type_add( 'YCM-signature-help-current-argument', {
  146. \ 'highlight': 'PMenuSel',
  147. \ 'combine': 0,
  148. \ 'priority': 50,
  149. \ } )
  150. call prop_type_add( 'YCM-signature-help-current-signature', {
  151. \ 'highlight': 'PMenu',
  152. \ 'combine': 0,
  153. \ 'priority': 40,
  154. \ } )
  155. call prop_type_add( 'YCM-signature-help-signature', {
  156. \ 'highlight': 'PMenuSbar',
  157. \ 'combine': 0,
  158. \ 'priority': 40,
  159. \ } )
  160. endif
  161. endfunction
  162. function! youcompleteme#EnableCursorMovedAutocommands()
  163. augroup ycmcompletemecursormove
  164. autocmd!
  165. autocmd CursorMoved * call s:OnCursorMovedNormalMode()
  166. autocmd TextChanged * call s:OnTextChangedNormalMode()
  167. autocmd TextChangedI * call s:OnTextChangedInsertMode()
  168. " The TextChangedI event is not triggered when inserting a character while
  169. " the completion menu is open. We handle this by closing the completion menu
  170. " just before inserting a character.
  171. autocmd InsertCharPre * call s:OnInsertChar()
  172. augroup END
  173. endfunction
  174. function! youcompleteme#DisableCursorMovedAutocommands()
  175. autocmd! ycmcompletemecursormove
  176. endfunction
  177. function! youcompleteme#GetErrorCount()
  178. return s:Pyeval( 'ycm_state.GetErrorCount()' )
  179. endfunction
  180. function! youcompleteme#GetWarningCount()
  181. return s:Pyeval( 'ycm_state.GetWarningCount()' )
  182. endfunction
  183. function! s:SetUpPython() abort
  184. exec s:python_until_eof
  185. from __future__ import unicode_literals
  186. from __future__ import print_function
  187. from __future__ import division
  188. from __future__ import absolute_import
  189. import os.path as p
  190. import re
  191. import sys
  192. import traceback
  193. import vim
  194. root_folder = p.normpath( p.join( vim.eval( 's:script_folder_path' ), '..' ) )
  195. third_party_folder = p.join( root_folder, 'third_party' )
  196. python_stdlib_zip_regex = re.compile( 'python[23][0-9]\\.zip' )
  197. def IsStandardLibraryFolder( path ):
  198. return ( ( p.isfile( path )
  199. and python_stdlib_zip_regex.match( p.basename( path ) ) )
  200. or p.isfile( p.join( path, 'os.py' ) ) )
  201. def IsVirtualEnvLibraryFolder( path ):
  202. return p.isfile( p.join( path, 'orig-prefix.txt' ) )
  203. def GetStandardLibraryIndexInSysPath():
  204. for index, path in enumerate( sys.path ):
  205. if ( IsStandardLibraryFolder( path ) and
  206. not IsVirtualEnvLibraryFolder( path ) ):
  207. return index
  208. raise RuntimeError( 'Could not find standard library path in Python path.' )
  209. # Add dependencies to Python path.
  210. dependencies = [ p.join( root_folder, 'python' ),
  211. p.join( third_party_folder, 'requests-futures' ),
  212. p.join( third_party_folder, 'ycmd' ),
  213. p.join( third_party_folder, 'requests_deps', 'idna' ),
  214. p.join( third_party_folder, 'requests_deps', 'chardet' ),
  215. p.join( third_party_folder,
  216. 'requests_deps',
  217. 'urllib3',
  218. 'src' ),
  219. p.join( third_party_folder, 'requests_deps', 'certifi' ),
  220. p.join( third_party_folder, 'requests_deps', 'requests' ) ]
  221. # The concurrent.futures module is part of the standard library on Python 3.
  222. if sys.version_info[ 0 ] == 2:
  223. dependencies.append( p.join( third_party_folder, 'pythonfutures' ) )
  224. sys.path[ 0:0 ] = dependencies
  225. # We enclose this code in a try/except block to avoid backtraces in Vim.
  226. try:
  227. # The python-future module must be inserted after the standard library path.
  228. sys.path.insert( GetStandardLibraryIndexInSysPath() + 1,
  229. p.join( third_party_folder, 'python-future', 'src' ) )
  230. # Import the modules used in this file.
  231. from ycm import base, vimsupport, youcompleteme
  232. if 'ycm_state' in globals():
  233. # If re-initializing, pretend that we shut down
  234. ycm_state.OnVimLeave()
  235. del ycm_state
  236. ycm_state = youcompleteme.YouCompleteMe()
  237. except Exception as error:
  238. # We don't use PostVimMessage or EchoText from the vimsupport module because
  239. # importing this module may fail.
  240. vim.command( 'redraw | echohl WarningMsg' )
  241. for line in traceback.format_exc().splitlines():
  242. vim.command( "echom '{0}'".format( line.replace( "'", "''" ) ) )
  243. vim.command( "echo 'YouCompleteMe unavailable: {0}'"
  244. .format( str( error ).replace( "'", "''" ) ) )
  245. vim.command( 'echohl None' )
  246. vim.command( 'return 0' )
  247. else:
  248. vim.command( 'return 1' )
  249. EOF
  250. endfunction
  251. function! s:SetUpKeyMappings()
  252. " The g:ycm_key_select_completion and g:ycm_key_previous_completion used to
  253. " exist and are now here purely for the sake of backwards compatibility; we
  254. " don't want to break users if we can avoid it.
  255. if exists('g:ycm_key_select_completion') &&
  256. \ index(g:ycm_key_list_select_completion,
  257. \ g:ycm_key_select_completion) == -1
  258. call add(g:ycm_key_list_select_completion, g:ycm_key_select_completion)
  259. endif
  260. if exists('g:ycm_key_previous_completion') &&
  261. \ index(g:ycm_key_list_previous_completion,
  262. \ g:ycm_key_previous_completion) == -1
  263. call add(g:ycm_key_list_previous_completion, g:ycm_key_previous_completion)
  264. endif
  265. for key in g:ycm_key_list_select_completion
  266. " With this command, when the completion window is visible, the tab key
  267. " (default) will select the next candidate in the window. In vim, this also
  268. " changes the typed-in text to that of the candidate completion.
  269. exe 'inoremap <expr>' . key .
  270. \ ' pumvisible() ? "\<C-n>" : "\' . key .'"'
  271. endfor
  272. for key in g:ycm_key_list_previous_completion
  273. " This selects the previous candidate for shift-tab (default)
  274. exe 'inoremap <expr>' . key .
  275. \ ' pumvisible() ? "\<C-p>" : "\' . key .'"'
  276. endfor
  277. for key in g:ycm_key_list_stop_completion
  278. " When selecting a candidate and closing the completion menu with the <C-y>
  279. " key, the menu will automatically be reopened because of the TextChangedI
  280. " event. We define a command to prevent that.
  281. exe 'inoremap <expr>' . key . ' <SID>StopCompletion( "\' . key . '" )'
  282. endfor
  283. if !empty( g:ycm_key_invoke_completion )
  284. let invoke_key = g:ycm_key_invoke_completion
  285. " Inside the console, <C-Space> is passed as <Nul> to Vim
  286. if invoke_key ==# '<C-Space>'
  287. imap <Nul> <C-Space>
  288. endif
  289. silent! exe 'inoremap <unique> <silent> ' . invoke_key .
  290. \ ' <C-R>=<SID>RequestSemanticCompletion()<CR>'
  291. endif
  292. if !empty( g:ycm_key_detailed_diagnostics )
  293. silent! exe 'nnoremap <unique> ' . g:ycm_key_detailed_diagnostics .
  294. \ ' :YcmShowDetailedDiagnostic<CR>'
  295. endif
  296. " The TextChangedI event is not triggered when deleting a character while the
  297. " completion menu is open. We handle this by closing the completion menu on
  298. " the keys that delete a character in insert mode.
  299. for key in [ "<BS>", "<C-h>" ]
  300. silent! exe 'inoremap <unique> <expr> ' . key .
  301. \ ' <SID>OnDeleteChar( "\' . key . '" )'
  302. endfor
  303. endfunction
  304. function! s:SetUpSigns()
  305. " We try to ensure backwards compatibility with Syntastic if the user has
  306. " already defined styling for Syntastic highlight groups.
  307. if !hlexists( 'YcmErrorSign' )
  308. if hlexists( 'SyntasticErrorSign')
  309. highlight link YcmErrorSign SyntasticErrorSign
  310. else
  311. highlight link YcmErrorSign error
  312. endif
  313. endif
  314. if !hlexists( 'YcmWarningSign' )
  315. if hlexists( 'SyntasticWarningSign')
  316. highlight link YcmWarningSign SyntasticWarningSign
  317. else
  318. highlight link YcmWarningSign todo
  319. endif
  320. endif
  321. if !hlexists( 'YcmErrorLine' )
  322. highlight link YcmErrorLine SyntasticErrorLine
  323. endif
  324. if !hlexists( 'YcmWarningLine' )
  325. highlight link YcmWarningLine SyntasticWarningLine
  326. endif
  327. exe 'sign define YcmError text=' . g:ycm_error_symbol .
  328. \ ' texthl=YcmErrorSign linehl=YcmErrorLine'
  329. exe 'sign define YcmWarning text=' . g:ycm_warning_symbol .
  330. \ ' texthl=YcmWarningSign linehl=YcmWarningLine'
  331. endfunction
  332. function! s:SetUpSyntaxHighlighting()
  333. " We try to ensure backwards compatibility with Syntastic if the user has
  334. " already defined styling for Syntastic highlight groups.
  335. if !hlexists( 'YcmErrorSection' )
  336. if hlexists( 'SyntasticError' )
  337. highlight link YcmErrorSection SyntasticError
  338. else
  339. highlight link YcmErrorSection SpellBad
  340. endif
  341. endif
  342. if !hlexists( 'YcmWarningSection' )
  343. if hlexists( 'SyntasticWarning' )
  344. highlight link YcmWarningSection SyntasticWarning
  345. else
  346. highlight link YcmWarningSection SpellCap
  347. endif
  348. endif
  349. endfunction
  350. function! s:SetUpBackwardsCompatibility()
  351. let complete_in_comments_and_strings =
  352. \ get( g:, 'ycm_complete_in_comments_and_strings', 0 )
  353. if complete_in_comments_and_strings
  354. let g:ycm_complete_in_strings = 1
  355. let g:ycm_complete_in_comments = 1
  356. endif
  357. " ycm_filetypes_to_completely_ignore is the old name for fileype_blacklist
  358. if has_key( g:, 'ycm_filetypes_to_completely_ignore' )
  359. let g:filetype_blacklist = g:ycm_filetypes_to_completely_ignore
  360. endif
  361. endfunction
  362. " Needed so that YCM is used instead of Syntastic
  363. function! s:TurnOffSyntasticForCFamily()
  364. let g:syntastic_cpp_checkers = []
  365. let g:syntastic_c_checkers = []
  366. let g:syntastic_objc_checkers = []
  367. let g:syntastic_objcpp_checkers = []
  368. let g:syntastic_cuda_checkers = []
  369. endfunction
  370. function! s:DisableOnLargeFile( buffer )
  371. if exists( 'b:ycm_largefile' )
  372. return b:ycm_largefile
  373. endif
  374. let threshold = g:ycm_disable_for_files_larger_than_kb * 1024
  375. let b:ycm_largefile =
  376. \ threshold > 0 && getfsize( expand( a:buffer ) ) > threshold
  377. if b:ycm_largefile
  378. exec s:python_command "vimsupport.PostVimMessage(" .
  379. \ "'YouCompleteMe is disabled in this buffer; " .
  380. \ "the file exceeded the max size (see YCM options).' )"
  381. endif
  382. return b:ycm_largefile
  383. endfunction
  384. function! s:AllowedToCompleteInBuffer( buffer )
  385. let buftype = getbufvar( a:buffer, '&buftype' )
  386. if has_key( s:buftype_blacklist, buftype )
  387. return 0
  388. endif
  389. let filetype = getbufvar( a:buffer, '&filetype' )
  390. if empty( filetype ) || s:DisableOnLargeFile( a:buffer )
  391. return 0
  392. endif
  393. let whitelist_allows = type( g:ycm_filetype_whitelist ) != type( {} ) ||
  394. \ has_key( g:ycm_filetype_whitelist, '*' ) ||
  395. \ has_key( g:ycm_filetype_whitelist, filetype )
  396. let blacklist_allows = type( g:ycm_filetype_blacklist ) != type( {} ) ||
  397. \ !has_key( g:ycm_filetype_blacklist, filetype )
  398. let allowed = whitelist_allows && blacklist_allows
  399. if allowed
  400. let s:previous_allowed_buffer_number = bufnr( a:buffer )
  401. endif
  402. return allowed
  403. endfunction
  404. function! s:AllowedToCompleteInCurrentBuffer()
  405. return s:AllowedToCompleteInBuffer( '%' )
  406. endfunction
  407. function! s:VisitedBufferRequiresReparse()
  408. if bufnr( '%' ) ==# s:previous_allowed_buffer_number
  409. return 0
  410. endif
  411. return s:AllowedToCompleteInCurrentBuffer()
  412. endfunction
  413. function! s:SetUpCpoptions()
  414. " Without this flag in cpoptions, critical YCM mappings do not work. There's
  415. " no way to not have this and have YCM working, so force the flag.
  416. set cpoptions+=B
  417. " This prevents the display of "Pattern not found" & similar messages during
  418. " completion.
  419. set shortmess+=c
  420. endfunction
  421. function! s:SetUpCompleteopt()
  422. " Some plugins (I'm looking at you, vim-notes) change completeopt by for
  423. " instance adding 'longest'. This breaks YCM. So we force our settings.
  424. " There's no two ways about this: if you want to use YCM then you have to
  425. " have these completeopt settings, otherwise YCM won't work at all.
  426. " We need menuone in completeopt, otherwise when there's only one candidate
  427. " for completion, the menu doesn't show up.
  428. set completeopt-=menu
  429. set completeopt+=menuone
  430. " This is unnecessary with our features. People use this option to insert
  431. " the common prefix of all the matches and then add more differentiating chars
  432. " so that they can select a more specific match. With our features, they
  433. " don't need to insert the prefix; they just type the differentiating chars.
  434. " Also, having this option set breaks the plugin.
  435. set completeopt-=longest
  436. if g:ycm_add_preview_to_completeopt
  437. set completeopt+=preview
  438. endif
  439. endfunction
  440. function! s:SetCompleteFunc()
  441. let &completefunc = 'youcompleteme#CompleteFunc'
  442. endfunction
  443. function! s:OnVimLeave()
  444. " Workaround a NeoVim issue - not shutting down timers correctly
  445. " https://github.com/neovim/neovim/issues/6840
  446. for poller in values( s:pollers )
  447. call timer_stop( poller.id )
  448. endfor
  449. exec s:python_command "ycm_state.OnVimLeave()"
  450. endfunction
  451. function! s:OnCompleteDone()
  452. if !s:AllowedToCompleteInCurrentBuffer()
  453. return
  454. endif
  455. exec s:python_command "ycm_state.OnCompleteDone()"
  456. call s:UpdateSignatureHelp()
  457. endfunction
  458. function! s:OnCompleteChanged()
  459. if !s:AllowedToCompleteInCurrentBuffer()
  460. return
  461. endif
  462. call s:UpdateSignatureHelp()
  463. endfunction
  464. function! s:OnFileTypeSet()
  465. " The contents of the command-line window are empty when the filetype is set
  466. " for the first time. Users should never change its filetype so we only rely
  467. " on the CmdwinEnter event for that window.
  468. if !empty( getcmdwintype() )
  469. return
  470. endif
  471. if !s:AllowedToCompleteInCurrentBuffer()
  472. return
  473. endif
  474. call s:SetUpCompleteopt()
  475. call s:SetCompleteFunc()
  476. call s:StartMessagePoll()
  477. exec s:python_command "ycm_state.OnBufferVisit()"
  478. call s:OnFileReadyToParse( 1 )
  479. endfunction
  480. function! s:OnBufferEnter()
  481. if !s:VisitedBufferRequiresReparse()
  482. return
  483. endif
  484. call s:SetUpCompleteopt()
  485. call s:SetCompleteFunc()
  486. call s:StartMessagePoll()
  487. exec s:python_command "ycm_state.OnBufferVisit()"
  488. " Last parse may be outdated because of changes from other buffers. Force a
  489. " new parse.
  490. call s:OnFileReadyToParse( 1 )
  491. endfunction
  492. function! s:OnBufferUnload()
  493. " Expanding <abuf> returns the unloaded buffer number as a string but we want
  494. " it as a true number for the getbufvar function.
  495. let buffer_number = str2nr( expand( '<abuf>' ) )
  496. if !s:AllowedToCompleteInBuffer( buffer_number )
  497. return
  498. endif
  499. exec s:python_command "ycm_state.OnBufferUnload( " . buffer_number . " )"
  500. endfunction
  501. function! s:UpdateMatches()
  502. exec s:python_command "ycm_state.UpdateMatches()"
  503. endfunction
  504. function! s:PollServerReady( timer_id )
  505. if !s:Pyeval( 'ycm_state.IsServerAlive()' )
  506. exec s:python_command "ycm_state.NotifyUserIfServerCrashed()"
  507. " Server crashed. Don't poll it again.
  508. return
  509. endif
  510. if !s:Pyeval( 'ycm_state.CheckIfServerIsReady()' )
  511. let s:pollers.server_ready.id = timer_start(
  512. \ s:pollers.server_ready.wait_milliseconds,
  513. \ function( 's:PollServerReady' ) )
  514. return
  515. endif
  516. call s:OnFileTypeSet()
  517. endfunction
  518. function! s:OnFileReadyToParse( ... )
  519. " Accepts an optional parameter that is either 0 or 1. If 1, send a
  520. " FileReadyToParse event notification, whether the buffer has changed or not;
  521. " effectively forcing a parse of the buffer. Default is 0.
  522. let force_parsing = a:0 > 0 && a:1
  523. " We only want to send a new FileReadyToParse event notification if the buffer
  524. " has changed since the last time we sent one, or if forced.
  525. if force_parsing || s:Pyeval( "ycm_state.NeedsReparse()" )
  526. " We switched buffers or somethuing, so claer.
  527. " FIXME: sig hekp should be buffer local?
  528. call s:ClearSignatureHelp()
  529. exec s:python_command "ycm_state.OnFileReadyToParse()"
  530. call timer_stop( s:pollers.file_parse_response.id )
  531. let s:pollers.file_parse_response.id = timer_start(
  532. \ s:pollers.file_parse_response.wait_milliseconds,
  533. \ function( 's:PollFileParseResponse' ) )
  534. endif
  535. endfunction
  536. function! s:PollFileParseResponse( ... )
  537. if !s:Pyeval( "ycm_state.FileParseRequestReady()" )
  538. let s:pollers.file_parse_response.id = timer_start(
  539. \ s:pollers.file_parse_response.wait_milliseconds,
  540. \ function( 's:PollFileParseResponse' ) )
  541. return
  542. endif
  543. exec s:python_command "ycm_state.HandleFileParseRequest()"
  544. if s:Pyeval( "ycm_state.ShouldResendFileParseRequest()" )
  545. call s:OnFileReadyToParse( 1 )
  546. endif
  547. endfunction
  548. function! s:SendKeys( keys )
  549. " By default keys are added to the end of the typeahead buffer. If there are
  550. " already keys in the buffer, they will be processed first and may change the
  551. " state that our keys combination was sent for (e.g. <C-X><C-U><C-P> in normal
  552. " mode instead of insert mode or <C-e> outside of completion mode). We avoid
  553. " that by inserting the keys at the start of the typeahead buffer with the 'i'
  554. " option. Also, we don't want the keys to be remapped to something else so we
  555. " add the 'n' option.
  556. call feedkeys( a:keys, 'in' )
  557. endfunction
  558. function! s:CloseCompletionMenu()
  559. if pumvisible()
  560. call s:SendKeys( "\<C-e>" )
  561. endif
  562. endfunction
  563. function! s:OnInsertChar()
  564. if !s:AllowedToCompleteInCurrentBuffer()
  565. return
  566. endif
  567. call timer_stop( s:pollers.completion.id )
  568. call s:CloseCompletionMenu()
  569. " TODO: Do we really need this here?
  570. call timer_stop( s:pollers.signature_help.id )
  571. endfunction
  572. function! s:OnDeleteChar( key )
  573. if !s:AllowedToCompleteInCurrentBuffer()
  574. return a:key
  575. endif
  576. call timer_stop( s:pollers.completion.id )
  577. "
  578. " TODO: Do we really need this here?
  579. call timer_stop( s:pollers.signature_help.id )
  580. if pumvisible()
  581. return "\<C-y>" . a:key
  582. endif
  583. return a:key
  584. endfunction
  585. function! s:StopCompletion( key )
  586. call timer_stop( s:pollers.completion.id )
  587. call s:ClearSignatureHelp()
  588. if pumvisible()
  589. let s:completion_stopped = 1
  590. return "\<C-y>"
  591. endif
  592. return a:key
  593. endfunction
  594. function! s:OnCursorMovedNormalMode()
  595. if !s:AllowedToCompleteInCurrentBuffer()
  596. return
  597. endif
  598. exec s:python_command "ycm_state.OnCursorMoved()"
  599. endfunction
  600. function! s:OnTextChangedNormalMode()
  601. if !s:AllowedToCompleteInCurrentBuffer()
  602. return
  603. endif
  604. call s:OnFileReadyToParse()
  605. endfunction
  606. function! s:OnTextChangedInsertMode()
  607. if !s:AllowedToCompleteInCurrentBuffer()
  608. return
  609. endif
  610. if s:completion_stopped
  611. let s:completion_stopped = 0
  612. let s:completion = s:default_completion
  613. return
  614. endif
  615. call s:IdentifierFinishedOperations()
  616. " We have to make sure we correctly leave semantic mode even when the user
  617. " inserts something like a "operator[]" candidate string which fails
  618. " CurrentIdentifierFinished check.
  619. if s:force_semantic && !s:Pyeval( 'base.LastEnteredCharIsIdentifierChar()' )
  620. let s:force_semantic = 0
  621. endif
  622. if &completefunc == "youcompleteme#CompleteFunc" &&
  623. \ ( g:ycm_auto_trigger || s:force_semantic ) &&
  624. \ !s:InsideCommentOrStringAndShouldStop() &&
  625. \ !s:OnBlankLine()
  626. " Immediately call previous completion to avoid flickers.
  627. call s:Complete()
  628. call s:RequestCompletion()
  629. call s:UpdateSignatureHelp()
  630. call s:RequestSignatureHelp()
  631. endif
  632. exec s:python_command "ycm_state.OnCursorMoved()"
  633. if g:ycm_autoclose_preview_window_after_completion
  634. call s:ClosePreviewWindowIfNeeded()
  635. endif
  636. endfunction
  637. function! s:OnInsertLeave()
  638. if !s:AllowedToCompleteInCurrentBuffer()
  639. return
  640. endif
  641. call timer_stop( s:pollers.completion.id )
  642. let s:force_semantic = 0
  643. let s:completion = s:default_completion
  644. call s:OnFileReadyToParse()
  645. exec s:python_command "ycm_state.OnInsertLeave()"
  646. if g:ycm_autoclose_preview_window_after_completion ||
  647. \ g:ycm_autoclose_preview_window_after_insertion
  648. call s:ClosePreviewWindowIfNeeded()
  649. endif
  650. call s:ClearSignatureHelp()
  651. endfunction
  652. function! s:ClosePreviewWindowIfNeeded()
  653. let current_buffer_name = bufname('')
  654. " We don't want to try to close the preview window in special buffers like
  655. " "[Command Line]"; if we do, Vim goes bonkers. Special buffers always start
  656. " with '['.
  657. if current_buffer_name[ 0 ] == '['
  658. return
  659. endif
  660. " This command does the actual closing of the preview window. If no preview
  661. " window is shown, nothing happens.
  662. pclose
  663. endfunction
  664. function! s:IdentifierFinishedOperations()
  665. if !s:Pyeval( 'base.CurrentIdentifierFinished()' )
  666. return
  667. endif
  668. exec s:python_command "ycm_state.OnCurrentIdentifierFinished()"
  669. let s:force_semantic = 0
  670. let s:completion = s:default_completion
  671. endfunction
  672. " Returns 1 when inside comment and 2 when inside string
  673. function! s:InsideCommentOrString()
  674. " Has to be col('.') -1 because col('.') doesn't exist at this point. We are
  675. " in insert mode when this func is called.
  676. let syntax_group = synIDattr(
  677. \ synIDtrans( synID( line( '.' ), col( '.' ) - 1, 1 ) ), 'name')
  678. if stridx(syntax_group, 'Comment') > -1
  679. return 1
  680. endif
  681. if stridx(syntax_group, 'String') > -1
  682. return 2
  683. endif
  684. return 0
  685. endfunction
  686. function! s:InsideCommentOrStringAndShouldStop()
  687. let retval = s:InsideCommentOrString()
  688. let inside_comment = retval == 1
  689. let inside_string = retval == 2
  690. if inside_comment && g:ycm_complete_in_comments ||
  691. \ inside_string && g:ycm_complete_in_strings
  692. return 0
  693. endif
  694. return retval
  695. endfunction
  696. function! s:OnBlankLine()
  697. return s:Pyeval( 'not vim.current.line or vim.current.line.isspace()' )
  698. endfunction
  699. function! s:RequestCompletion()
  700. exec s:python_command "ycm_state.SendCompletionRequest(" .
  701. \ "vimsupport.GetBoolValue( 's:force_semantic' ) )"
  702. call s:PollCompletion()
  703. endfunction
  704. function! s:RequestSemanticCompletion()
  705. if &completefunc == "youcompleteme#CompleteFunc"
  706. let s:force_semantic = 1
  707. exec s:python_command "ycm_state.SendCompletionRequest( True )"
  708. call s:PollCompletion()
  709. endif
  710. " Since this function is called in a mapping through the expression register
  711. " <C-R>=, its return value is inserted (see :h c_CTRL-R_=). We don't want to
  712. " insert anything so we return an empty string.
  713. return ''
  714. endfunction
  715. function! s:PollCompletion( ... )
  716. if !s:Pyeval( 'ycm_state.CompletionRequestReady()' )
  717. let s:pollers.completion.id = timer_start(
  718. \ s:pollers.completion.wait_milliseconds,
  719. \ function( 's:PollCompletion' ) )
  720. return
  721. endif
  722. let s:completion = s:Pyeval( 'ycm_state.GetCompletionResponse()' )
  723. call s:Complete()
  724. endfunction
  725. function! s:ShouldUseSignatureHelp()
  726. return s:Pyeval( 'vimsupport.VimSupportsPopupWindows()' )
  727. endfunction
  728. function! s:RequestSignatureHelp()
  729. if !s:ShouldUseSignatureHelp()
  730. return
  731. endif
  732. exec s:python_command "ycm_state.SendSignatureHelpRequest()"
  733. call s:PollSignatureHelp()
  734. endfunction
  735. function! s:PollSignatureHelp( ... )
  736. if !s:ShouldUseSignatureHelp()
  737. return
  738. endif
  739. if !s:Pyeval( 'ycm_state.SignatureHelpRequestReady()' )
  740. let s:pollers.signature_help.id = timer_start(
  741. \ s:pollers.signature_help.wait_milliseconds,
  742. \ function( 's:PollSignatureHelp' ) )
  743. return
  744. endif
  745. let s:signature_help = s:Pyeval( 'ycm_state.GetSignatureHelpResponse()' )
  746. call s:UpdateSignatureHelp()
  747. endfunction
  748. function! s:Complete()
  749. " Do not call user's completion function if the start column is after the
  750. " current column or if there are no candidates. Close the completion menu
  751. " instead. This avoids keeping the user in completion mode.
  752. if s:completion.completion_start_column > s:completion.column ||
  753. \ empty( s:completion.completions )
  754. call s:CloseCompletionMenu()
  755. else
  756. " <c-x><c-u> invokes the user's completion function (which we have set to
  757. " youcompleteme#CompleteFunc), and <c-p> tells Vim to select the previous
  758. " completion candidate. This is necessary because by default, Vim selects
  759. " the first candidate when completion is invoked, and selecting a candidate
  760. " automatically replaces the current text with it. Calling <c-p> forces Vim
  761. " to deselect the first candidate and in turn preserve the user's current
  762. " text until he explicitly chooses to replace it with a completion.
  763. call s:SendKeys( "\<C-X>\<C-U>\<C-P>" )
  764. endif
  765. " Displaying or hiding the PUM might mean we need to hide the sig help
  766. call s:UpdateSignatureHelp()
  767. endfunction
  768. function! youcompleteme#CompleteFunc( findstart, base )
  769. if a:findstart
  770. " When auto-wrapping is enabled, Vim wraps the current line after the
  771. " completion request is sent but before calling this function. The starting
  772. " column returned by the server is invalid in that case and must be
  773. " recomputed.
  774. if s:completion.line != line( '.' )
  775. " Given
  776. " scb: column where the completion starts before auto-wrapping
  777. " cb: cursor column before auto-wrapping
  778. " sca: column where the completion starts after auto-wrapping
  779. " ca: cursor column after auto-wrapping
  780. " we have
  781. " ca - sca = cb - scb
  782. " sca = scb + ca - cb
  783. let s:completion.completion_start_column +=
  784. \ col( '.' ) - s:completion.column
  785. endif
  786. return s:completion.completion_start_column - 1
  787. endif
  788. return s:completion.completions
  789. endfunction
  790. function! s:UpdateSignatureHelp()
  791. if !s:ShouldUseSignatureHelp()
  792. return
  793. endif
  794. call s:Pyeval(
  795. \ 'ycm_state.UpdateSignatureHelp( vim.eval( "s:signature_help" ) )' )
  796. endfunction
  797. function! s:ClearSignatureHelp()
  798. if !s:ShouldUseSignatureHelp()
  799. return
  800. endif
  801. call timer_stop( s:pollers.signature_help.id )
  802. let s:signature_help = s:default_signature_help
  803. call s:Pyeval( 'ycm_state.ClearSignatureHelp()' )
  804. endfunction
  805. function! youcompleteme#ServerPid()
  806. return s:Pyeval( 'ycm_state.ServerPid()' )
  807. endfunction
  808. function! s:SetUpCommands()
  809. command! YcmRestartServer call s:RestartServer()
  810. command! YcmDebugInfo call s:DebugInfo()
  811. command! -nargs=* -complete=custom,youcompleteme#LogsComplete
  812. \ YcmToggleLogs call s:ToggleLogs(<f-args>)
  813. if s:Pyeval( 'vimsupport.VimVersionAtLeast( "7.4.1898" )' )
  814. command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete -range
  815. \ YcmCompleter call s:CompleterCommand(<q-mods>,
  816. \ <count>,
  817. \ <line1>,
  818. \ <line2>,
  819. \ <f-args>)
  820. else
  821. command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete -range
  822. \ YcmCompleter call s:CompleterCommand('',
  823. \ <count>,
  824. \ <line1>,
  825. \ <line2>,
  826. \ <f-args>)
  827. endif
  828. command! YcmDiags call s:ShowDiagnostics()
  829. command! YcmShowDetailedDiagnostic call s:ShowDetailedDiagnostic()
  830. command! YcmForceCompileAndDiagnostics call s:ForceCompileAndDiagnostics()
  831. endfunction
  832. function! s:RestartServer()
  833. call s:SetUpOptions()
  834. exec s:python_command "ycm_state.RestartServer()"
  835. call timer_stop( s:pollers.receive_messages.id )
  836. let s:pollers.receive_messages.id = -1
  837. call s:ClearSignatureHelp()
  838. call timer_stop( s:pollers.server_ready.id )
  839. let s:pollers.server_ready.id = timer_start(
  840. \ s:pollers.server_ready.wait_milliseconds,
  841. \ function( 's:PollServerReady' ) )
  842. endfunction
  843. function! s:DebugInfo()
  844. echom "Printing YouCompleteMe debug information..."
  845. let debug_info = s:Pyeval( 'ycm_state.DebugInfo()' )
  846. for line in split( debug_info, "\n" )
  847. echom '-- ' . line
  848. endfor
  849. endfunction
  850. function! s:ToggleLogs(...)
  851. exec s:python_command "ycm_state.ToggleLogs( *vim.eval( 'a:000' ) )"
  852. endfunction
  853. function! youcompleteme#LogsComplete( arglead, cmdline, cursorpos )
  854. return join( s:Pyeval( 'list( ycm_state.GetLogfiles() )' ), "\n" )
  855. endfunction
  856. function! s:CompleterCommand( mods, count, line1, line2, ... )
  857. exec s:python_command "ycm_state.SendCommandRequest(" .
  858. \ "vim.eval( 'a:000' )," .
  859. \ "vim.eval( 'a:mods' )," .
  860. \ "vimsupport.GetBoolValue( 'a:count != -1' )," .
  861. \ "vimsupport.GetIntValue( 'a:line1' )," .
  862. \ "vimsupport.GetIntValue( 'a:line2' ) )"
  863. endfunction
  864. function! youcompleteme#SubCommandsComplete( arglead, cmdline, cursorpos )
  865. return join( s:Pyeval( 'ycm_state.GetDefinedSubcommands()' ), "\n" )
  866. endfunction
  867. function! youcompleteme#OpenGoToList()
  868. exec s:python_command "vimsupport.PostVimMessage(" .
  869. \ "'WARNING: youcompleteme#OpenGoToList function is deprecated. " .
  870. \ "Do NOT use it.' )"
  871. exec s:python_command "vimsupport.OpenQuickFixList( True, True )"
  872. endfunction
  873. function! s:ShowDiagnostics()
  874. exec s:python_command "ycm_state.ShowDiagnostics()"
  875. endfunction
  876. function! s:ShowDetailedDiagnostic()
  877. exec s:python_command "ycm_state.ShowDetailedDiagnostic()"
  878. endfunction
  879. function! s:ForceCompileAndDiagnostics()
  880. exec s:python_command "ycm_state.ForceCompileAndDiagnostics()"
  881. endfunction
  882. " This is basic vim plugin boilerplate
  883. let &cpo = s:save_cpo
  884. unlet s:save_cpo