1
0

youcompleteme.vim 29 KB

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