youcompleteme.vim 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440
  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. \ 'command': {
  52. \ 'id': -1,
  53. \ 'wait_milliseconds': 100
  54. \ }
  55. \ }
  56. let s:buftype_blacklist = {
  57. \ 'help': 1,
  58. \ 'terminal': 1,
  59. \ 'quickfix': 1
  60. \ }
  61. let s:last_char_inserted_by_user = v:true
  62. let s:enable_hover = 0
  63. let s:cursorhold_popup = -1
  64. " We can use one of two approaches to auto-triggering completion
  65. " * completefunc - the classic way - we set completefunc to our function and
  66. " use feedkeys() to trigger user-defined
  67. " * complete() - the 'new' way - this uses complete() and TextChangedP to avoid
  68. " closing the pum on every keystroke. This reduces redraw and flickering
  69. " appreciably, but is only supported on more recent vims.
  70. let s:COMPLETION_COMPLETEFUNC = 0
  71. let s:COMPLETION_TEXTCHANGEDP = 1
  72. " By default (if possible) use the new complete()/TextChangedP API
  73. let s:completion_api = get( g:,
  74. \ 'ycm_use_completion_api',
  75. \ s:COMPLETION_TEXTCHANGEDP )
  76. " Fall back to using completefunc if the TextChangedP/CompleteChanged API
  77. " isn't available. Both are needed to ensure correct behaviour with the 'new'
  78. " complete() api
  79. if !exists( '##TextChangedP' ) || !exists( '##CompleteChanged' )
  80. \ || s:completion_api != s:COMPLETION_TEXTCHANGEDP
  81. let s:completion_api = s:COMPLETION_COMPLETEFUNC
  82. endif
  83. function! s:StartMessagePoll()
  84. if s:pollers.receive_messages.id < 0
  85. let s:pollers.receive_messages.id = timer_start(
  86. \ s:pollers.receive_messages.wait_milliseconds,
  87. \ function( 's:ReceiveMessages' ) )
  88. endif
  89. endfunction
  90. function! s:ReceiveMessages( timer_id )
  91. let poll_again = v:false
  92. if s:AllowedToCompleteInCurrentBuffer()
  93. let poll_again = py3eval( 'ycm_state.OnPeriodicTick()' )
  94. endif
  95. if poll_again
  96. let s:pollers.receive_messages.id = timer_start(
  97. \ s:pollers.receive_messages.wait_milliseconds,
  98. \ function( 's:ReceiveMessages' ) )
  99. else
  100. " Don't poll again until we open another buffer
  101. let s:pollers.receive_messages.id = -1
  102. endif
  103. endfunction
  104. function! s:SetUpOptions()
  105. call s:SetUpCommands()
  106. call s:SetUpCpoptions()
  107. call s:SetUpCompleteopt()
  108. call s:SetUpKeyMappings()
  109. if g:ycm_show_diagnostics_ui
  110. call s:TurnOffSyntasticForCFamily()
  111. endif
  112. call s:SetUpSigns()
  113. call s:SetUpSyntaxHighlighting()
  114. endfunction
  115. function! youcompleteme#Enable()
  116. call s:SetUpBackwardsCompatibility()
  117. if !s:SetUpPython()
  118. return
  119. endif
  120. call s:SetUpOptions()
  121. call youcompleteme#EnableCursorMovedAutocommands()
  122. augroup youcompleteme
  123. autocmd!
  124. " Note that these events will NOT trigger for the file vim is started with;
  125. " so if you do "vim foo.cc", these events will not trigger when that buffer
  126. " is read. This is because youcompleteme#Enable() is called on VimEnter and
  127. " that happens *after* FileType has already triggered for the initial file.
  128. " We don't parse the buffer on the BufRead event since it would only be
  129. " useful if the buffer filetype is set (we ignore the buffer if there is no
  130. " filetype) and if so, the FileType event has triggered before and thus the
  131. " buffer is already parsed.
  132. autocmd BufWritePost,FileWritePost * call s:OnFileSave()
  133. autocmd FileType * call s:OnFileTypeSet()
  134. autocmd BufEnter,CmdwinEnter * call s:OnBufferEnter()
  135. autocmd BufUnload * call s:OnBufferUnload()
  136. autocmd InsertLeave * call s:OnInsertLeave()
  137. autocmd VimLeave * call s:OnVimLeave()
  138. autocmd CompleteDone * call s:OnCompleteDone()
  139. if exists( '##CompleteChanged' )
  140. autocmd CompleteChanged * call s:OnCompleteChanged()
  141. endif
  142. autocmd BufEnter,WinEnter * call s:UpdateMatches()
  143. augroup END
  144. " The FileType event is not triggered for the first loaded file. We wait until
  145. " the server is ready to manually run the s:OnFileTypeSet function.
  146. let s:pollers.server_ready.id = timer_start(
  147. \ s:pollers.server_ready.wait_milliseconds,
  148. \ function( 's:PollServerReady' ) )
  149. let s:default_completion = py3eval( 'vimsupport.NO_COMPLETIONS' )
  150. let s:completion = s:default_completion
  151. if exists( '*prop_type_add' ) && exists( '*prop_type_delete' )
  152. hi default YCMInverse term=reverse cterm=reverse gui=reverse
  153. call prop_type_delete( 'YCM-signature-help-current-argument' )
  154. call prop_type_add( 'YCM-signature-help-current-argument', {
  155. \ 'highlight': 'YCMInverse',
  156. \ 'combine': 1,
  157. \ 'priority': 50,
  158. \ } )
  159. endif
  160. endfunction
  161. function! youcompleteme#EnableCursorMovedAutocommands()
  162. augroup ycmcompletemecursormove
  163. autocmd!
  164. autocmd CursorMoved * call s:OnCursorMovedNormalMode()
  165. autocmd TextChanged * call s:OnTextChangedNormalMode()
  166. autocmd TextChangedI * call s:OnTextChangedInsertMode( v:false )
  167. if s:completion_api == s:COMPLETION_TEXTCHANGEDP
  168. autocmd TextChangedP * call s:OnTextChangedInsertMode( v:true )
  169. endif
  170. autocmd InsertCharPre * call s:OnInsertChar()
  171. augroup END
  172. endfunction
  173. function! youcompleteme#DisableCursorMovedAutocommands()
  174. autocmd! ycmcompletemecursormove
  175. endfunction
  176. function! youcompleteme#GetErrorCount()
  177. return py3eval( 'ycm_state.GetErrorCount()' )
  178. endfunction
  179. function! youcompleteme#GetWarningCount()
  180. return py3eval( 'ycm_state.GetWarningCount()' )
  181. endfunction
  182. function! s:SetUpPython() abort
  183. py3 << EOF
  184. import os.path as p
  185. import sys
  186. import traceback
  187. import vim
  188. root_folder = p.normpath( p.join( vim.eval( 's:script_folder_path' ), '..' ) )
  189. third_party_folder = p.join( root_folder, 'third_party' )
  190. # Add dependencies to Python path.
  191. dependencies = [ p.join( root_folder, 'python' ),
  192. p.join( third_party_folder, 'requests-futures' ),
  193. p.join( third_party_folder, 'ycmd' ),
  194. p.join( third_party_folder, 'requests_deps', 'idna' ),
  195. p.join( third_party_folder, 'requests_deps', 'chardet' ),
  196. p.join( third_party_folder,
  197. 'requests_deps',
  198. 'urllib3',
  199. 'src' ),
  200. p.join( third_party_folder, 'requests_deps', 'certifi' ),
  201. p.join( third_party_folder, 'requests_deps', 'requests' ) ]
  202. sys.path[ 0:0 ] = dependencies
  203. # We enclose this code in a try/except block to avoid backtraces in Vim.
  204. try:
  205. # Import the modules used in this file.
  206. from ycm import base, vimsupport, youcompleteme
  207. if 'ycm_state' in globals():
  208. # If re-initializing, pretend that we shut down
  209. ycm_state.OnVimLeave()
  210. del ycm_state
  211. ycm_state = youcompleteme.YouCompleteMe()
  212. except Exception as error:
  213. # We don't use PostVimMessage or EchoText from the vimsupport module because
  214. # importing this module may fail.
  215. vim.command( 'redraw | echohl WarningMsg' )
  216. for line in traceback.format_exc().splitlines():
  217. vim.command( "echom '{0}'".format( line.replace( "'", "''" ) ) )
  218. vim.command( "echo 'YouCompleteMe unavailable: {0}'"
  219. .format( str( error ).replace( "'", "''" ) ) )
  220. vim.command( 'echohl None' )
  221. vim.command( 'return 0' )
  222. else:
  223. vim.command( 'return 1' )
  224. EOF
  225. endfunction
  226. function! s:SetUpKeyMappings()
  227. " The g:ycm_key_select_completion and g:ycm_key_previous_completion used to
  228. " exist and are now here purely for the sake of backwards compatibility; we
  229. " don't want to break users if we can avoid it.
  230. if exists('g:ycm_key_select_completion') &&
  231. \ index(g:ycm_key_list_select_completion,
  232. \ g:ycm_key_select_completion) == -1
  233. call add(g:ycm_key_list_select_completion, g:ycm_key_select_completion)
  234. endif
  235. if exists('g:ycm_key_previous_completion') &&
  236. \ index(g:ycm_key_list_previous_completion,
  237. \ g:ycm_key_previous_completion) == -1
  238. call add(g:ycm_key_list_previous_completion, g:ycm_key_previous_completion)
  239. endif
  240. for key in g:ycm_key_list_select_completion
  241. " With this command, when the completion window is visible, the tab key
  242. " (default) will select the next candidate in the window. In vim, this also
  243. " changes the typed-in text to that of the candidate completion.
  244. exe 'inoremap <expr>' . key . ' pumvisible() ? "\<C-n>" : "\' . key .'"'
  245. endfor
  246. for key in g:ycm_key_list_previous_completion
  247. " This selects the previous candidate for shift-tab (default)
  248. exe 'inoremap <expr>' . key . ' pumvisible() ? "\<C-p>" : "\' . key .'"'
  249. endfor
  250. for key in g:ycm_key_list_stop_completion
  251. " When selecting a candidate and closing the completion menu with the <C-y>
  252. " key, the menu will automatically be reopened because of the TextChangedI
  253. " event. We define a command to prevent that.
  254. exe 'inoremap <expr>' . key . ' <SID>StopCompletion( "\' . key . '" )'
  255. endfor
  256. if !empty( g:ycm_key_invoke_completion )
  257. let invoke_key = g:ycm_key_invoke_completion
  258. " Inside the console, <C-Space> is passed as <Nul> to Vim
  259. if invoke_key ==# '<C-Space>'
  260. imap <Nul> <C-Space>
  261. endif
  262. silent! exe 'inoremap <unique> <silent> ' . invoke_key .
  263. \ ' <C-R>=<SID>RequestSemanticCompletion()<CR>'
  264. endif
  265. if !empty( g:ycm_key_detailed_diagnostics )
  266. silent! exe 'nnoremap <unique> ' . g:ycm_key_detailed_diagnostics .
  267. \ ' :YcmShowDetailedDiagnostic<CR>'
  268. endif
  269. if s:completion_api == s:COMPLETION_COMPLETEFUNC
  270. " The TextChangedI event is not triggered when deleting a character while
  271. " the completion menu is open. We handle this by closing the completion menu
  272. " on the keys that delete a character in insert mode.
  273. for key in [ "<BS>", "<C-h>" ]
  274. silent! exe 'inoremap <unique> <expr> ' . key .
  275. \ ' <SID>OnDeleteChar( "\' . key . '" )'
  276. endfor
  277. endif
  278. endfunction
  279. function! s:SetUpSigns()
  280. " We try to ensure backwards compatibility with Syntastic if the user has
  281. " already defined styling for Syntastic highlight groups.
  282. if !hlexists( 'YcmErrorSign' )
  283. if hlexists( 'SyntasticErrorSign')
  284. highlight link YcmErrorSign SyntasticErrorSign
  285. else
  286. highlight link YcmErrorSign error
  287. endif
  288. endif
  289. if !hlexists( 'YcmWarningSign' )
  290. if hlexists( 'SyntasticWarningSign')
  291. highlight link YcmWarningSign SyntasticWarningSign
  292. else
  293. highlight link YcmWarningSign todo
  294. endif
  295. endif
  296. if !hlexists( 'YcmErrorLine' )
  297. highlight link YcmErrorLine SyntasticErrorLine
  298. endif
  299. if !hlexists( 'YcmWarningLine' )
  300. highlight link YcmWarningLine SyntasticWarningLine
  301. endif
  302. exe 'sign define YcmError text=' . g:ycm_error_symbol .
  303. \ ' texthl=YcmErrorSign linehl=YcmErrorLine'
  304. exe 'sign define YcmWarning text=' . g:ycm_warning_symbol .
  305. \ ' texthl=YcmWarningSign linehl=YcmWarningLine'
  306. endfunction
  307. function! s:SetUpSyntaxHighlighting()
  308. " We try to ensure backwards compatibility with Syntastic if the user has
  309. " already defined styling for Syntastic highlight groups.
  310. if !hlexists( 'YcmErrorSection' )
  311. if hlexists( 'SyntasticError' )
  312. highlight link YcmErrorSection SyntasticError
  313. else
  314. highlight link YcmErrorSection SpellBad
  315. endif
  316. endif
  317. if !hlexists( 'YcmWarningSection' )
  318. if hlexists( 'SyntasticWarning' )
  319. highlight link YcmWarningSection SyntasticWarning
  320. else
  321. highlight link YcmWarningSection SpellCap
  322. endif
  323. endif
  324. endfunction
  325. function! s:SetUpBackwardsCompatibility()
  326. let complete_in_comments_and_strings =
  327. \ get( g:, 'ycm_complete_in_comments_and_strings', 0 )
  328. if complete_in_comments_and_strings
  329. let g:ycm_complete_in_strings = 1
  330. let g:ycm_complete_in_comments = 1
  331. endif
  332. " ycm_filetypes_to_completely_ignore is the old name for fileype_blacklist
  333. if has_key( g:, 'ycm_filetypes_to_completely_ignore' )
  334. let g:filetype_blacklist = g:ycm_filetypes_to_completely_ignore
  335. endif
  336. endfunction
  337. " Needed so that YCM is used instead of Syntastic
  338. function! s:TurnOffSyntasticForCFamily()
  339. let g:syntastic_cpp_checkers = []
  340. let g:syntastic_c_checkers = []
  341. let g:syntastic_objc_checkers = []
  342. let g:syntastic_objcpp_checkers = []
  343. let g:syntastic_cuda_checkers = []
  344. endfunction
  345. function! s:DisableOnLargeFile( buffer )
  346. if exists( 'b:ycm_largefile' )
  347. return b:ycm_largefile
  348. endif
  349. let threshold = g:ycm_disable_for_files_larger_than_kb * 1024
  350. let b:ycm_largefile =
  351. \ threshold > 0 && getfsize( expand( a:buffer ) ) > threshold
  352. if b:ycm_largefile
  353. py3 vimsupport.PostVimMessage( 'YouCompleteMe is disabled in this buffer;' +
  354. \ ' the file exceeded the max size (see YCM options).' )
  355. endif
  356. return b:ycm_largefile
  357. endfunction
  358. function! s:HasAnyKey( dict, keys )
  359. for key in a:keys
  360. if has_key( a:dict, key )
  361. return 1
  362. endif
  363. endfor
  364. return 0
  365. endfunction
  366. function! s:AllowedToCompleteInBuffer( buffer )
  367. let buftype = getbufvar( a:buffer, '&buftype' )
  368. if has_key( s:buftype_blacklist, buftype )
  369. return 0
  370. endif
  371. let filetype = getbufvar( a:buffer, '&filetype' )
  372. if empty( filetype ) || s:DisableOnLargeFile( a:buffer )
  373. return 0
  374. endif
  375. let whitelist_allows = type( g:ycm_filetype_whitelist ) != type( {} ) ||
  376. \ has_key( g:ycm_filetype_whitelist, '*' ) ||
  377. \ s:HasAnyKey( g:ycm_filetype_whitelist, split( filetype, '\.' ) )
  378. let blacklist_allows = type( g:ycm_filetype_blacklist ) != type( {} ) ||
  379. \ !s:HasAnyKey( g:ycm_filetype_blacklist, split( filetype, '\.' ) )
  380. let allowed = whitelist_allows && blacklist_allows
  381. if allowed
  382. let s:previous_allowed_buffer_number = bufnr( a:buffer )
  383. endif
  384. return allowed
  385. endfunction
  386. function! s:AllowedToCompleteInCurrentBuffer()
  387. return s:AllowedToCompleteInBuffer( '%' )
  388. endfunction
  389. function! s:VisitedBufferRequiresReparse()
  390. if bufnr( '%' ) ==# s:previous_allowed_buffer_number
  391. return 0
  392. endif
  393. return s:AllowedToCompleteInCurrentBuffer()
  394. endfunction
  395. function! s:SetUpCpoptions()
  396. " Without this flag in cpoptions, critical YCM mappings do not work. There's
  397. " no way to not have this and have YCM working, so force the flag.
  398. set cpoptions+=B
  399. " This prevents the display of "Pattern not found" & similar messages during
  400. " completion.
  401. set shortmess+=c
  402. endfunction
  403. function! s:SetUpCompleteopt()
  404. " Some plugins (I'm looking at you, vim-notes) change completeopt by for
  405. " instance adding 'longest'. This breaks YCM. So we force our settings.
  406. " There's no two ways about this: if you want to use YCM then you have to
  407. " have these completeopt settings, otherwise YCM won't work at all.
  408. " We need menuone in completeopt, otherwise when there's only one candidate
  409. " for completion, the menu doesn't show up.
  410. set completeopt-=menu
  411. set completeopt+=menuone
  412. " This is unnecessary with our features. People use this option to insert
  413. " the common prefix of all the matches and then add more differentiating chars
  414. " so that they can select a more specific match. With our features, they
  415. " don't need to insert the prefix; they just type the differentiating chars.
  416. " Also, having this option set breaks the plugin.
  417. set completeopt-=longest
  418. " A non-numeric string compares equal to an integer zero. Without the type
  419. " check, users on a recent vim and disabling preview by setting it to 0
  420. " get `popup` added instead.
  421. if type( g:ycm_add_preview_to_completeopt ) == type( '' ) &&
  422. \ g:ycm_add_preview_to_completeopt ==# 'popup' &&
  423. \ ( v:version > 801 || ( v:version == 801 && has( 'patch1880' ) ) )
  424. set completeopt+=popup
  425. elseif g:ycm_add_preview_to_completeopt
  426. set completeopt+=preview
  427. endif
  428. endfunction
  429. function! s:SetCompleteFunc()
  430. if s:completion_api == s:COMPLETION_COMPLETEFUNC
  431. let &completefunc = 'youcompleteme#CompleteFunc'
  432. endif
  433. let b:ycm_completing = 1
  434. endfunction
  435. function s:StopPoller( poller ) abort
  436. call timer_stop( a:poller.id )
  437. let a:poller.id = -1
  438. endfunction
  439. function! s:OnVimLeave()
  440. " Workaround a NeoVim issue - not shutting down timers correctly
  441. " https://github.com/neovim/neovim/issues/6840
  442. for poller in values( s:pollers )
  443. call s:StopPoller( poller )
  444. endfor
  445. py3 ycm_state.OnVimLeave()
  446. endfunction
  447. function! s:OnCompleteDone()
  448. if !s:AllowedToCompleteInCurrentBuffer()
  449. return
  450. endif
  451. let s:last_char_inserted_by_user = v:false
  452. py3 ycm_state.OnCompleteDone()
  453. call s:UpdateSignatureHelp()
  454. endfunction
  455. function! s:OnCompleteChanged()
  456. if !s:AllowedToCompleteInCurrentBuffer()
  457. return
  458. endif
  459. if ! empty( v:event.completed_item )
  460. let s:last_char_inserted_by_user = v:false
  461. endif
  462. call s:UpdateSignatureHelp()
  463. endfunction
  464. function! s:EnableAutoHover()
  465. if g:ycm_auto_hover ==# 'CursorHold' && s:enable_hover
  466. augroup YcmBufHover
  467. autocmd! * <buffer>
  468. autocmd CursorHold <buffer> call s:Hover()
  469. augroup END
  470. endif
  471. endfunction
  472. function! s:DisableAutoHover()
  473. augroup YcmBufHover
  474. autocmd! * <buffer>
  475. augroup END
  476. endfunction
  477. function! s:OnFileTypeSet()
  478. " The contents of the command-line window are empty when the filetype is set
  479. " for the first time. Users should never change its filetype so we only rely
  480. " on the CmdwinEnter event for that window.
  481. if !empty( getcmdwintype() )
  482. return
  483. endif
  484. if !s:AllowedToCompleteInCurrentBuffer()
  485. return
  486. endif
  487. call s:SetUpCompleteopt()
  488. call s:SetCompleteFunc()
  489. call s:StartMessagePoll()
  490. call s:EnableAutoHover()
  491. py3 ycm_state.OnFileTypeSet()
  492. call s:OnFileReadyToParse( 1 )
  493. endfunction
  494. function! s:OnFileSave()
  495. let buffer_number = str2nr( expand( '<abuf>' ) )
  496. if !s:AllowedToCompleteInBuffer( buffer_number )
  497. return
  498. endif
  499. py3 ycm_state.OnFileSave( vimsupport.GetIntValue( 'buffer_number' ) )
  500. endfunction
  501. function! s:OnBufferEnter()
  502. call s:StartMessagePoll()
  503. if !s:VisitedBufferRequiresReparse()
  504. return
  505. endif
  506. call s:SetUpCompleteopt()
  507. call s:SetCompleteFunc()
  508. py3 ycm_state.OnBufferVisit()
  509. " Last parse may be outdated because of changes from other buffers. Force a
  510. " new parse.
  511. call s:OnFileReadyToParse( 1 )
  512. endfunction
  513. function! s:OnBufferUnload()
  514. " Expanding <abuf> returns the unloaded buffer number as a string but we want
  515. " it as a true number for the getbufvar function.
  516. let buffer_number = str2nr( expand( '<abuf>' ) )
  517. if !s:AllowedToCompleteInBuffer( buffer_number )
  518. return
  519. endif
  520. py3 ycm_state.OnBufferUnload( vimsupport.GetIntValue( 'buffer_number' ) )
  521. endfunction
  522. function! s:UpdateMatches()
  523. py3 ycm_state.UpdateMatches()
  524. endfunction
  525. function! s:PollServerReady( timer_id )
  526. if !py3eval( 'ycm_state.IsServerAlive()' )
  527. py3 ycm_state.NotifyUserIfServerCrashed()
  528. " Server crashed. Don't poll it again.
  529. return
  530. endif
  531. if !py3eval( 'ycm_state.CheckIfServerIsReady()' )
  532. let s:pollers.server_ready.id = timer_start(
  533. \ s:pollers.server_ready.wait_milliseconds,
  534. \ function( 's:PollServerReady' ) )
  535. return
  536. endif
  537. call s:OnFileTypeSet()
  538. endfunction
  539. function! s:OnFileReadyToParse( ... )
  540. " Accepts an optional parameter that is either 0 or 1. If 1, send a
  541. " FileReadyToParse event notification, whether the buffer has changed or not;
  542. " effectively forcing a parse of the buffer. Default is 0.
  543. let force_parsing = a:0 > 0 && a:1
  544. " We only want to send a new FileReadyToParse event notification if the buffer
  545. " has changed since the last time we sent one, or if forced.
  546. if force_parsing || py3eval( "ycm_state.NeedsReparse()" )
  547. " We switched buffers or somethuing, so claer.
  548. " FIXME: sig hekp should be buffer local?
  549. call s:ClearSignatureHelp()
  550. py3 ycm_state.OnFileReadyToParse()
  551. call s:StopPoller( s:pollers.file_parse_response )
  552. let s:pollers.file_parse_response.id = timer_start(
  553. \ s:pollers.file_parse_response.wait_milliseconds,
  554. \ function( 's:PollFileParseResponse' ) )
  555. endif
  556. endfunction
  557. function! s:PollFileParseResponse( ... )
  558. if !py3eval( "ycm_state.FileParseRequestReady()" )
  559. let s:pollers.file_parse_response.id = timer_start(
  560. \ s:pollers.file_parse_response.wait_milliseconds,
  561. \ function( 's:PollFileParseResponse' ) )
  562. return
  563. endif
  564. py3 ycm_state.HandleFileParseRequest()
  565. if py3eval( "ycm_state.ShouldResendFileParseRequest()" )
  566. call s:OnFileReadyToParse( 1 )
  567. endif
  568. endfunction
  569. function! s:SendKeys( keys )
  570. " By default keys are added to the end of the typeahead buffer. If there are
  571. " already keys in the buffer, they will be processed first and may change
  572. " the state that our keys combination was sent for (e.g. <C-X><C-U><C-P> in
  573. " normal mode instead of insert mode or <C-e> outside of completion mode).
  574. " We avoid that by inserting the keys at the start of the typeahead buffer
  575. " with the 'i' option. Also, we don't want the keys to be remapped to
  576. " something else so we add the 'n' option.
  577. call feedkeys( a:keys, 'in' )
  578. endfunction
  579. function! s:CloseCompletionMenu()
  580. if pumvisible()
  581. call s:SendKeys( "\<C-e>" )
  582. endif
  583. endfunction
  584. function! s:OnInsertChar()
  585. if !s:AllowedToCompleteInCurrentBuffer()
  586. return
  587. endif
  588. let s:last_char_inserted_by_user = v:true
  589. if s:completion_api == s:COMPLETION_COMPLETEFUNC
  590. call s:StopPoller( s:pollers.completion )
  591. call s:StopPoller( s:pollers.signature_help )
  592. call s:CloseCompletionMenu()
  593. endif
  594. endfunction
  595. if s:completion_api == s:COMPLETION_COMPLETEFUNC
  596. function! s:OnDeleteChar( key )
  597. if !s:AllowedToCompleteInCurrentBuffer()
  598. return a:key
  599. endif
  600. call s:StopPoller( s:pollers.completion )
  601. call s:StopPoller( s:pollers.signature_help )
  602. if pumvisible()
  603. return "\<C-y>" . a:key
  604. endif
  605. return a:key
  606. endfunction
  607. endif
  608. function! s:StopCompletion( key )
  609. call s:StopPoller( s:pollers.completion )
  610. call s:ClearSignatureHelp()
  611. if pumvisible()
  612. let s:completion_stopped = 1
  613. return "\<C-y>"
  614. endif
  615. return a:key
  616. endfunction
  617. function! s:OnCursorMovedNormalMode()
  618. if !s:AllowedToCompleteInCurrentBuffer()
  619. return
  620. endif
  621. py3 ycm_state.OnCursorMoved()
  622. endfunction
  623. function! s:OnTextChangedNormalMode()
  624. if !s:AllowedToCompleteInCurrentBuffer()
  625. return
  626. endif
  627. call s:OnFileReadyToParse()
  628. endfunction
  629. function! s:OnTextChangedInsertMode( popup_is_visible )
  630. if !s:AllowedToCompleteInCurrentBuffer()
  631. return
  632. endif
  633. if a:popup_is_visible && !s:last_char_inserted_by_user
  634. " If the last "input" wasn't from a user typing (i.e. didn't come from
  635. " InsertCharPre, then ignore this change in the text. This prevents ctrl-n
  636. " or tab from causing us to re-filter the list based on the now-selected
  637. " item.
  638. return
  639. endif
  640. if s:completion_stopped
  641. let s:completion_stopped = 0
  642. let s:completion = s:default_completion
  643. return
  644. endif
  645. call s:IdentifierFinishedOperations()
  646. " We have to make sure we correctly leave semantic mode even when the user
  647. " inserts something like a "operator[]" candidate string which fails
  648. " CurrentIdentifierFinished check.
  649. if s:force_semantic && !py3eval( 'base.LastEnteredCharIsIdentifierChar()' )
  650. let s:force_semantic = 0
  651. endif
  652. if get( b:, 'ycm_completing' ) &&
  653. \ ( g:ycm_auto_trigger || s:force_semantic ) &&
  654. \ !s:InsideCommentOrStringAndShouldStop() &&
  655. \ !s:OnBlankLine()
  656. " The call to s:Complete here is necessary, to minimize flicker when we
  657. " close the pum on every keypress. In that case, we try to quickly show it
  658. " again with whatver the latest completion result is. When using complete(),
  659. " we don't need to do this, as we only close the pum when there are no
  660. " completions. However, it's still useful as we don't want Vim's filtering
  661. " to _ever_ apply. Examples of when this is problematic is when typing some
  662. " keys to filter (that are not a prefix of the completion), then deleting a
  663. " character. Normally Vim would re-filter based on the new "query", but we
  664. " don't want that.
  665. call s:Complete()
  666. call s:RequestCompletion()
  667. call s:UpdateSignatureHelp()
  668. call s:RequestSignatureHelp()
  669. endif
  670. py3 ycm_state.OnCursorMoved()
  671. if g:ycm_autoclose_preview_window_after_completion
  672. call s:ClosePreviewWindowIfNeeded()
  673. endif
  674. endfunction
  675. function! s:OnInsertLeave()
  676. if !s:AllowedToCompleteInCurrentBuffer()
  677. return
  678. endif
  679. let s:last_char_inserted_by_user = v:false
  680. call s:StopPoller( s:pollers.completion )
  681. let s:force_semantic = 0
  682. let s:completion = s:default_completion
  683. call s:OnFileReadyToParse()
  684. py3 ycm_state.OnInsertLeave()
  685. if g:ycm_autoclose_preview_window_after_completion ||
  686. \ g:ycm_autoclose_preview_window_after_insertion
  687. call s:ClosePreviewWindowIfNeeded()
  688. endif
  689. call s:ClearSignatureHelp()
  690. endfunction
  691. function! s:ClosePreviewWindowIfNeeded()
  692. let current_buffer_name = bufname('')
  693. " We don't want to try to close the preview window in special buffers like
  694. " "[Command Line]"; if we do, Vim goes bonkers. Special buffers always start
  695. " with '['.
  696. if current_buffer_name[ 0 ] == '['
  697. return
  698. endif
  699. " This command does the actual closing of the preview window. If no preview
  700. " window is shown, nothing happens.
  701. pclose
  702. endfunction
  703. function! s:IdentifierFinishedOperations()
  704. if !py3eval( 'base.CurrentIdentifierFinished()' )
  705. return
  706. endif
  707. py3 ycm_state.OnCurrentIdentifierFinished()
  708. let s:force_semantic = 0
  709. let s:completion = s:default_completion
  710. endfunction
  711. " Returns 1 when inside comment and 2 when inside string
  712. function! s:InsideCommentOrString()
  713. " Has to be col('.') -1 because col('.') doesn't exist at this point. We are
  714. " in insert mode when this func is called.
  715. let syntax_group = synIDattr(
  716. \ synIDtrans( synID( line( '.' ), col( '.' ) - 1, 1 ) ), 'name')
  717. if stridx(syntax_group, 'Comment') > -1
  718. return 1
  719. endif
  720. if stridx(syntax_group, 'String') > -1
  721. return 2
  722. endif
  723. return 0
  724. endfunction
  725. function! s:InsideCommentOrStringAndShouldStop()
  726. let retval = s:InsideCommentOrString()
  727. let inside_comment = retval == 1
  728. let inside_string = retval == 2
  729. if inside_comment && g:ycm_complete_in_comments ||
  730. \ inside_string && g:ycm_complete_in_strings
  731. return 0
  732. endif
  733. return retval
  734. endfunction
  735. function! s:OnBlankLine()
  736. return py3eval( 'not vim.current.line or vim.current.line.isspace()' )
  737. endfunction
  738. function! s:RequestCompletion()
  739. if s:completion_api == s:COMPLETION_TEXTCHANGEDP
  740. call s:StopPoller( s:pollers.completion )
  741. endif
  742. py3 ycm_state.SendCompletionRequest(
  743. \ vimsupport.GetBoolValue( 's:force_semantic' ) )
  744. if s:completion_api == s:COMPLETION_TEXTCHANGEDP &&
  745. \ py3eval( 'ycm_state.CompletionRequestReady()' )
  746. " We can't call complete() syncrhounsouly in the TextChangedI/TextChangedP
  747. " autocommmands (it's designed to be used async only completion). The result
  748. " (somewhat oddly) is that the completion menu is shown, but ctrl-n doesn't
  749. " actually select anything.
  750. " When the request is satisfied synchronously (e.g. the omnicompleter), we
  751. " must return to the main loop before triggering completion, so we use a 0ms
  752. " timer for that.
  753. let s:pollers.completion.id = timer_start( 0,
  754. \ function( 's:PollCompletion' ) )
  755. else
  756. " Otherwise, use our usual poll timeout
  757. call s:PollCompletion()
  758. endif
  759. endfunction
  760. function! s:RequestSemanticCompletion()
  761. if !s:AllowedToCompleteInCurrentBuffer()
  762. return ''
  763. endif
  764. if get( b:, 'ycm_completing' )
  765. let s:force_semantic = 1
  766. if s:completion_api == s:COMPLETION_TEXTCHANGEDP
  767. call s:StopPoller( s:pollers.completion )
  768. endif
  769. py3 ycm_state.SendCompletionRequest( True )
  770. if s:completion_api == s:COMPLETION_TEXTCHANGEDP &&
  771. \ py3eval( 'ycm_state.CompletionRequestReady()' )
  772. " We can't call complete() syncrhounsouly in the TextChangedI/TextChangedP
  773. " autocommmands (it's designed to be used async only completion). The
  774. " result (somewhat oddly) is that the completion menu is shown, but ctrl-n
  775. " doesn't actually select anything. When the request is satisfied
  776. " synchronously (e.g. the omnicompleter), we must return to the main loop
  777. " before triggering completion, so we use a 0ms timer for that.
  778. let s:pollers.completion.id = timer_start(
  779. \ 0,
  780. \ function( 's:PollCompletion' ) )
  781. else
  782. " Otherwise, use our usual poll timeout
  783. call s:PollCompletion()
  784. endif
  785. endif
  786. " Since this function is called in a mapping through the expression register
  787. " <C-R>=, its return value is inserted (see :h c_CTRL-R_=). We don't want to
  788. " insert anything so we return an empty string.
  789. return ''
  790. endfunction
  791. function! s:PollCompletion( ... )
  792. if !py3eval( 'ycm_state.CompletionRequestReady()' )
  793. let s:pollers.completion.id = timer_start(
  794. \ s:pollers.completion.wait_milliseconds,
  795. \ function( 's:PollCompletion' ) )
  796. return
  797. endif
  798. let s:completion = py3eval( 'ycm_state.GetCompletionResponse()' )
  799. call s:Complete()
  800. endfunction
  801. function! s:ShouldUseSignatureHelp()
  802. return py3eval( 'vimsupport.VimSupportsPopupWindows()' )
  803. endfunction
  804. function! s:RequestSignatureHelp()
  805. if !s:ShouldUseSignatureHelp()
  806. return
  807. endif
  808. call s:StopPoller( s:pollers.signature_help )
  809. if py3eval( 'ycm_state.SendSignatureHelpRequest()' )
  810. call s:PollSignatureHelp()
  811. endif
  812. endfunction
  813. function! s:PollSignatureHelp( ... )
  814. if !s:ShouldUseSignatureHelp()
  815. return
  816. endif
  817. if a:0 == 0 && s:pollers.signature_help.id >= 0
  818. " OK this is a bug. We have tried to poll for a response while the timer is
  819. " already running. Just return and wait for the timer to fire.
  820. return
  821. endif
  822. if !py3eval( 'ycm_state.SignatureHelpRequestReady()' )
  823. let s:pollers.signature_help.id = timer_start(
  824. \ s:pollers.signature_help.wait_milliseconds,
  825. \ function( 's:PollSignatureHelp' ) )
  826. return
  827. endif
  828. let s:signature_help = py3eval( 'ycm_state.GetSignatureHelpResponse()' )
  829. call s:UpdateSignatureHelp()
  830. endfunction
  831. if s:completion_api == s:COMPLETION_TEXTCHANGEDP
  832. function! s:Complete()
  833. " It's possible for us to be called (by our timer) when we're not _strictly_
  834. " in insert mode. This can happen when mode is temporarily switched, e.g.
  835. " due to Ctrl-r or Ctrl-o or a timer or something. If we're not in insert
  836. " mode _now_ do nothing (FIXME: or should we queue a timer ?)
  837. if count( [ 'i', 'R' ], mode() ) == 0
  838. return
  839. endif
  840. if s:completion.line != line( '.' )
  841. " Given
  842. " scb: column where the completion starts before auto-wrapping
  843. " cb: cursor column before auto-wrapping
  844. " sca: column where the completion starts after auto-wrapping
  845. " ca: cursor column after auto-wrapping
  846. " we have
  847. " ca - sca = cb - scb
  848. " sca = scb + ca - cb
  849. let s:completion.completion_start_column +=
  850. \ col( '.' ) - s:completion.column
  851. endif
  852. if len( s:completion.completions )
  853. let old_completeopt = &completeopt
  854. set completeopt+=noselect
  855. call complete( s:completion.completion_start_column,
  856. \ s:completion.completions )
  857. let &completeopt = old_completeopt
  858. elseif pumvisible()
  859. call s:CloseCompletionMenu()
  860. endif
  861. endfunction
  862. else
  863. function! s:Complete()
  864. " Do not call user's completion function if the start column is after the
  865. " current column or if there are no candidates. Close the completion menu
  866. " instead. This avoids keeping the user in completion mode.
  867. if s:completion.completion_start_column > s:completion.column ||
  868. \ empty( s:completion.completions )
  869. call s:CloseCompletionMenu()
  870. else
  871. " <c-x><c-u> invokes the user's completion function (which we have set to
  872. " youcompleteme#CompleteFunc), and <c-p> tells Vim to select the previous
  873. " completion candidate. This is necessary because by default, Vim selects
  874. " the first candidate when completion is invoked, and selecting a
  875. " candidate automatically replaces the current text with it. Calling <c-p>
  876. " forces Vim to deselect the first candidate and in turn preserve the
  877. " user's current text until he explicitly chooses to replace it with a
  878. " completion.
  879. call s:SendKeys( "\<C-X>\<C-U>\<C-P>" )
  880. endif
  881. " Displaying or hiding the PUM might mean we need to hide the sig help
  882. call s:UpdateSignatureHelp()
  883. endfunction
  884. function! youcompleteme#CompleteFunc( findstart, base )
  885. if a:findstart
  886. " When auto-wrapping is enabled, Vim wraps the current line after the
  887. " completion request is sent but before calling this function. The
  888. " starting column returned by the server is invalid in that case and must
  889. " be recomputed.
  890. if s:completion.line != line( '.' )
  891. " Given
  892. " scb: column where the completion starts before auto-wrapping
  893. " cb: cursor column before auto-wrapping
  894. " sca: column where the completion starts after auto-wrapping
  895. " ca: cursor column after auto-wrapping
  896. " we have
  897. " ca - sca = cb - scb
  898. " sca = scb + ca - cb
  899. let s:completion.completion_start_column +=
  900. \ col( '.' ) - s:completion.column
  901. endif
  902. return s:completion.completion_start_column - 1
  903. endif
  904. return s:completion.completions
  905. endfunction
  906. endif
  907. function! s:UpdateSignatureHelp()
  908. if !s:ShouldUseSignatureHelp()
  909. return
  910. endif
  911. call py3eval(
  912. \ 'ycm_state.UpdateSignatureHelp( vim.eval( "s:signature_help" ) )' )
  913. endfunction
  914. function! s:ClearSignatureHelp()
  915. if !s:ShouldUseSignatureHelp()
  916. return
  917. endif
  918. call s:StopPoller( s:pollers.signature_help )
  919. let s:signature_help = s:default_signature_help
  920. call py3eval( 'ycm_state.ClearSignatureHelp()' )
  921. endfunction
  922. function! youcompleteme#ServerPid()
  923. return py3eval( 'ycm_state.ServerPid()' )
  924. endfunction
  925. function! s:SetUpCommands()
  926. command! YcmRestartServer call s:RestartServer()
  927. command! YcmDebugInfo call s:DebugInfo()
  928. command! -nargs=* -complete=custom,youcompleteme#LogsComplete -count=0
  929. \ YcmToggleLogs call s:ToggleLogs( <f-count>,
  930. \ <f-mods>,
  931. \ <f-args>)
  932. if py3eval( 'vimsupport.VimVersionAtLeast( "7.4.1898" )' )
  933. command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete -range
  934. \ YcmCompleter call s:CompleterCommand(<q-mods>,
  935. \ <count>,
  936. \ <line1>,
  937. \ <line2>,
  938. \ <f-args>)
  939. else
  940. command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete -range
  941. \ YcmCompleter call s:CompleterCommand('',
  942. \ <count>,
  943. \ <line1>,
  944. \ <line2>,
  945. \ <f-args>)
  946. endif
  947. command! YcmDiags call s:ShowDiagnostics()
  948. command! YcmShowDetailedDiagnostic call s:ShowDetailedDiagnostic()
  949. command! YcmForceCompileAndDiagnostics call s:ForceCompileAndDiagnostics()
  950. endfunction
  951. function! s:RestartServer()
  952. call s:SetUpOptions()
  953. py3 ycm_state.RestartServer()
  954. call s:StopPoller( s:pollers.receive_messages )
  955. call s:StopPoller( s:pollers.command )
  956. call s:ClearSignatureHelp()
  957. call s:StopPoller( s:pollers.server_ready )
  958. let s:pollers.server_ready.id = timer_start(
  959. \ s:pollers.server_ready.wait_milliseconds,
  960. \ function( 's:PollServerReady' ) )
  961. endfunction
  962. function! s:DebugInfo()
  963. echom "Printing YouCompleteMe debug information..."
  964. let debug_info = py3eval( 'ycm_state.DebugInfo()' )
  965. echom '-- Completion API: ' . string( s:completion_api )
  966. for line in split( debug_info, "\n" )
  967. echom '-- ' . line
  968. endfor
  969. endfunction
  970. function! s:ToggleLogs( count, ... )
  971. py3 ycm_state.ToggleLogs( vimsupport.GetIntValue( 'a:count' ),
  972. \ *vim.eval( 'a:000' ) )
  973. endfunction
  974. function! youcompleteme#LogsComplete( arglead, cmdline, cursorpos )
  975. return join( py3eval( 'list( ycm_state.GetLogfiles() )' ), "\n" )
  976. endfunction
  977. function! youcompleteme#GetCommandResponse( ... )
  978. if !s:AllowedToCompleteInCurrentBuffer()
  979. return ''
  980. endif
  981. if !get( b:, 'ycm_completing' )
  982. return ''
  983. endif
  984. return py3eval( 'ycm_state.GetCommandResponse( vim.eval( "a:000" ) )' )
  985. endfunction
  986. function! youcompleteme#GetCommandResponseAsync( callback, ... )
  987. if !s:AllowedToCompleteInCurrentBuffer()
  988. eval a:callback( '' )
  989. return
  990. endif
  991. if !get( b:, 'ycm_completing' )
  992. eval a:callback( '' )
  993. return
  994. endif
  995. if s:pollers.command.id != -1
  996. eval a:callback( '' )
  997. return
  998. endif
  999. py3 ycm_state.SendCommandRequestAsync( vim.eval( "a:000" ) )
  1000. let s:pollers.command.id = timer_start(
  1001. \ s:pollers.command.wait_milliseconds,
  1002. \ function( 's:PollCommand', [ a:callback ] ) )
  1003. endfunction
  1004. function! s:PollCommand( callback, id )
  1005. if py3eval( 'ycm_state.GetCommandRequest() is None' )
  1006. " Possible in case of race conditions and things like RestartServer
  1007. " But particualrly in the tests
  1008. return
  1009. endif
  1010. if !py3eval( 'ycm_state.GetCommandRequest().Done()' )
  1011. let s:pollers.command.id = timer_start(
  1012. \ s:pollers.command.wait_milliseconds,
  1013. \ function( 's:PollCommand', [ a:callback ] ) )
  1014. return
  1015. endif
  1016. call s:StopPoller( s:pollers.command )
  1017. let result = py3eval( 'ycm_state.GetCommandRequest().StringResponse()' )
  1018. eval a:callback( result )
  1019. endfunction
  1020. function! s:CompleterCommand( mods, count, line1, line2, ... )
  1021. py3 ycm_state.SendCommandRequest(
  1022. \ vim.eval( 'a:000' ),
  1023. \ vim.eval( 'a:mods' ),
  1024. \ vimsupport.GetBoolValue( 'a:count != -1' ),
  1025. \ vimsupport.GetIntValue( 'a:line1' ),
  1026. \ vimsupport.GetIntValue( 'a:line2' ) )
  1027. endfunction
  1028. function! youcompleteme#SubCommandsComplete( arglead, cmdline, cursorpos )
  1029. return join( py3eval( 'ycm_state.GetDefinedSubcommands()' ), "\n" )
  1030. endfunction
  1031. function! youcompleteme#GetDefinedSubcommands()
  1032. if !s:AllowedToCompleteInCurrentBuffer()
  1033. return []
  1034. endif
  1035. if !exists( 'b:ycm_completing' )
  1036. return []
  1037. endif
  1038. return py3eval( 'ycm_state.GetDefinedSubcommands()' )
  1039. endfunction
  1040. function! youcompleteme#OpenGoToList()
  1041. py3 vimsupport.PostVimMessage(
  1042. \ "'WARNING: youcompleteme#OpenGoToList function is deprecated. " .
  1043. \ "Do NOT use it.'" )
  1044. py3 vimsupport.OpenQuickFixList( True, True )
  1045. endfunction
  1046. function! s:ShowDiagnostics()
  1047. py3 ycm_state.ShowDiagnostics()
  1048. endfunction
  1049. function! s:ShowDetailedDiagnostic()
  1050. py3 ycm_state.ShowDetailedDiagnostic()
  1051. endfunction
  1052. function! s:ForceCompileAndDiagnostics()
  1053. py3 ycm_state.ForceCompileAndDiagnostics()
  1054. endfunction
  1055. if exists( '*popup_atcursor' )
  1056. function s:Hover()
  1057. if !py3eval( 'ycm_state.NativeFiletypeCompletionUsable()' )
  1058. " Cancel the autocommand if it happens to have been set
  1059. call s:DisableAutoHover()
  1060. return
  1061. endif
  1062. if !has_key( b:, 'ycm_hover' )
  1063. let cmds = youcompleteme#GetDefinedSubcommands()
  1064. if index( cmds, 'GetHover' ) >= 0
  1065. let b:ycm_hover = {
  1066. \ 'command': 'GetHover',
  1067. \ 'syntax': 'markdown',
  1068. \ }
  1069. elseif index( cmds, 'GetDoc' ) >= 0
  1070. let b:ycm_hover = {
  1071. \ 'command': 'GetDoc',
  1072. \ 'syntax': '',
  1073. \ }
  1074. elseif index( cmds, 'GetType' ) >= 0
  1075. let b:ycm_hover = {
  1076. \ 'command': 'GetType',
  1077. \ 'syntax': &syntax,
  1078. \ }
  1079. else
  1080. let b:ycm_hover = {}
  1081. endif
  1082. endif
  1083. if empty( b:ycm_hover )
  1084. return
  1085. endif
  1086. call youcompleteme#GetCommandResponseAsync(
  1087. \ function( 's:ShowHoverResult' ),
  1088. \ b:ycm_hover.command )
  1089. endfunction
  1090. function! s:ShowHoverResult( response )
  1091. call popup_hide( s:cursorhold_popup )
  1092. if empty( a:response )
  1093. return
  1094. endif
  1095. " Try to position the popup at the cursor, but avoid wrapping. If the
  1096. " longest line is > screen width (&columns), then we just have to wrap, and
  1097. " place the popup at the leftmost column.
  1098. "
  1099. " Find the longest line (FIXME: probably doesn't work well for multi-byte)
  1100. let lines = split( a:response, "\n" )
  1101. let len = max( map( copy( lines ), "len( v:val )" ) )
  1102. let wrap = 0
  1103. let col = 'cursor'
  1104. " max width is screen columns minus x padding (2)
  1105. if len >= (&columns - 2)
  1106. " There's at least one line > our max - enable word wrap and draw the
  1107. " popup at the leftmost column
  1108. let col = 1
  1109. let wrap = 1
  1110. endif
  1111. let s:cursorhold_popup = popup_atcursor(
  1112. \ lines,
  1113. \ {
  1114. \ 'col': col,
  1115. \ 'wrap': wrap,
  1116. \ 'padding': [ 0, 1, 0, 1 ],
  1117. \ 'moved': 'word',
  1118. \ 'maxwidth': &columns,
  1119. \ 'close': 'click',
  1120. \ 'fixed': 0,
  1121. \ }
  1122. \ )
  1123. call setbufvar( winbufnr( s:cursorhold_popup ),
  1124. \ '&syntax',
  1125. \ b:ycm_hover.syntax )
  1126. endfunction
  1127. function! s:ToggleHover()
  1128. let pos = popup_getpos( s:cursorhold_popup )
  1129. if !empty( pos ) && pos.visible
  1130. call popup_hide( s:cursorhold_popup )
  1131. let s:cursorhold_popup = -1
  1132. " Diable the auto-trigger until the next cursor movement.
  1133. call s:DisableAutoHover()
  1134. augroup YCMHover
  1135. autocmd! CursorMoved <buffer>
  1136. autocmd CursorMoved <buffer> call s:EnableAutoHover()
  1137. augroup END
  1138. else
  1139. call s:Hover()
  1140. endif
  1141. endfunction
  1142. let s:enable_hover = 1
  1143. nnoremap <silent> <plug>(YCMHover) :<C-u>call <SID>ToggleHover()<CR>
  1144. else
  1145. " Don't break people's mappings if this feature is disabled, just do nothing.
  1146. nnoremap <silent> <plug>(YCMHover) <Nop>
  1147. endif
  1148. function! youcompleteme#Test_GetPollers()
  1149. return s:pollers
  1150. endfunction
  1151. " This is basic vim plugin boilerplate
  1152. let &cpo = s:save_cpo
  1153. unlet s:save_cpo