youcompleteme.vim 31 KB

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