youcompleteme.vim 30 KB

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