diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index 5c511fdf..76d6f58b 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -29,6 +29,26 @@ let s:cursor_moved = 0 let s:moved_vertically_in_insert_mode = 0 let s:previous_num_chars_on_current_line = strlen( getline('.') ) +function! s:UsingPython2() + " I'm willing to bet quite a bit that sooner or later, somebody will ask us to + " make it configurable which version of Python we use. + if has('python') + return 1 + endif + return 0 +endfunction + +let s:using_python2 = s:UsingPython2() +let s:python_until_eof = s:using_python2 ? "python << EOF" : "python3 << EOF" +let s:python_command = s:using_python2 ? "py " : "py3 " + +function! s:Pyeval( eval_string ) + if s:using_python2 + return pyeval( a:eval_string ) + endif + return py3eval( a:eval_string ) +endfunction + function! youcompleteme#Enable() " When vim is in diff mode, don't run @@ -120,17 +140,22 @@ endfunction function! youcompleteme#GetErrorCount() - return pyeval( 'ycm_state.GetErrorCount()' ) + return s:Pyeval( 'ycm_state.GetErrorCount()' ) endfunction function! youcompleteme#GetWarningCount() - return pyeval( 'ycm_state.GetWarningCount()' ) + return s:Pyeval( 'ycm_state.GetWarningCount()' ) endfunction function! s:SetUpPython() abort -python << EOF + exec s:python_until_eof +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import + import os import sys import traceback @@ -340,7 +365,7 @@ function! s:SetUpCpoptions() " This prevents the display of "Pattern not found" & similar messages during " completion. This is only available since Vim 7.4.314 - if pyeval( 'vimsupport.VimVersionAtLeast("7.4.314")' ) + if s:Pyeval( 'vimsupport.VimVersionAtLeast("7.4.314")' ) set shortmess+=c endif endfunction @@ -383,12 +408,12 @@ endfunction function! s:OnVimLeave() - py ycm_state.OnVimLeave() + exec s:python_command "ycm_state.OnVimLeave()" endfunction function! s:OnCompleteDone() - py ycm_state.OnCompleteDone() + exec s:python_command "ycm_state.OnCompleteDone()" endfunction @@ -421,7 +446,7 @@ function! s:OnBufferVisit() call s:SetOmnicompleteFunc() endif - py ycm_state.OnBufferVisit() + exec s:python_command "ycm_state.OnBufferVisit()" call s:OnFileReadyToParse() endfunction @@ -431,7 +456,8 @@ function! s:OnBufferUnload( deleted_buffer_file ) return endif - py ycm_state.OnBufferUnload( vim.eval( 'a:deleted_buffer_file' ) ) + exec s:python_command "ycm_state.OnBufferUnload(" + \ "vim.eval( 'a:deleted_buffer_file' ) )" endfunction @@ -454,11 +480,11 @@ function! s:OnFileReadyToParse() " reparsing the file again. If we sent the new parse request first, then " the response would always be pending when we called " HandleFileParseRequest. - py ycm_state.HandleFileParseRequest() + exec s:python_command "ycm_state.HandleFileParseRequest()" let buffer_changed = b:changedtick != b:ycm_changedtick.file_ready_to_parse if buffer_changed - py ycm_state.OnFileReadyToParse() + exec s:python_command "ycm_state.OnFileReadyToParse()" endif let b:ycm_changedtick.file_ready_to_parse = b:changedtick endfunction @@ -471,7 +497,7 @@ endfunction function! s:SetOmnicompleteFunc() - if pyeval( 'ycm_state.NativeFiletypeCompletionUsable()' ) + if s:Pyeval( 'ycm_state.NativeFiletypeCompletionUsable()' ) let &omnifunc = 'youcompleteme#OmniComplete' let &l:omnifunc = 'youcompleteme#OmniComplete' @@ -489,7 +515,7 @@ function! s:OnCursorMovedInsertMode() return endif - py ycm_state.OnCursorMoved() + exec s:python_command "ycm_state.OnCursorMoved()" call s:UpdateCursorMoved() " Basically, we need to only trigger the completion menu when the user has @@ -515,7 +541,7 @@ function! s:OnCursorMovedInsertMode() " We have to make sure we correctly leave omnifunc mode even when the user " inserts something like a "operator[]" candidate string which fails " CurrentIdentifierFinished check. - if s:omnifunc_mode && !pyeval( 'base.LastEnteredCharIsIdentifierChar()') + if s:omnifunc_mode && !s:Pyeval( 'base.LastEnteredCharIsIdentifierChar()') let s:omnifunc_mode = 0 endif endfunction @@ -527,7 +553,7 @@ function! s:OnCursorMovedNormalMode() endif call s:OnFileReadyToParse() - py ycm_state.OnCursorMoved() + exec s:python_command "ycm_state.OnCursorMoved()" endfunction @@ -538,7 +564,7 @@ function! s:OnInsertLeave() let s:omnifunc_mode = 0 call s:OnFileReadyToParse() - py ycm_state.OnInsertLeave() + exec s:python_command "ycm_state.OnInsertLeave()" if g:ycm_autoclose_preview_window_after_completion || \ g:ycm_autoclose_preview_window_after_insertion call s:ClosePreviewWindowIfNeeded() @@ -601,10 +627,10 @@ endfunction function! s:IdentifierFinishedOperations() - if !pyeval( 'base.CurrentIdentifierFinished()' ) + if !s:Pyeval( 'base.CurrentIdentifierFinished()' ) return endif - py ycm_state.OnCurrentIdentifierFinished() + exec s:python_command "ycm_state.OnCurrentIdentifierFinished()" let s:omnifunc_mode = 0 endfunction @@ -613,7 +639,8 @@ endfunction function! s:InsideCommentOrString() " Has to be col('.') -1 because col('.') doesn't exist at this point. We are " in insert mode when this func is called. - let syntax_group = synIDattr( synIDtrans( synID( line( '.' ), col( '.' ) - 1, 1 ) ), 'name') + let syntax_group = synIDattr( + \ synIDtrans( synID( line( '.' ), col( '.' ) - 1, 1 ) ), 'name') if stridx(syntax_group, 'Comment') > -1 return 1 @@ -642,7 +669,7 @@ endfunction function! s:OnBlankLine() - return pyeval( 'not vim.current.line or vim.current.line.isspace()' ) + return s:Pyeval( 'not vim.current.line or vim.current.line.isspace()' ) endfunction @@ -678,7 +705,7 @@ function! s:InvokeCompletion() endfunction -python << EOF +exec s:python_until_eof def GetCompletionsInner(): request = ycm_state.GetCurrentCompletionRequest() request.Start() @@ -692,8 +719,8 @@ EOF function! s:GetCompletions() - py results = GetCompletionsInner() - let results = pyeval( 'results' ) + exec s:python_command "results = GetCompletionsInner()" + let results = s:Pyeval( 'results' ) return results endfunction @@ -718,11 +745,11 @@ function! youcompleteme#Complete( findstart, base ) return -2 endif - if !pyeval( 'ycm_state.IsServerAlive()' ) + if !s:Pyeval( 'ycm_state.IsServerAlive()' ) return -2 endif - py ycm_state.CreateCompletionRequest() - return pyeval( 'base.CompletionStartColumn()' ) + exec s:python_command "ycm_state.CreateCompletionRequest()" + return s:Pyeval( 'base.CompletionStartColumn()' ) else return s:GetCompletions() endif @@ -731,12 +758,13 @@ endfunction function! youcompleteme#OmniComplete( findstart, base ) if a:findstart - if !pyeval( 'ycm_state.IsServerAlive()' ) + if !s:Pyeval( 'ycm_state.IsServerAlive()' ) return -2 endif let s:omnifunc_mode = 1 - py ycm_state.CreateCompletionRequest( force_semantic = True ) - return pyeval( 'base.CompletionStartColumn()' ) + exec s:python_command "ycm_state.CreateCompletionRequest(" + \ "force_semantic = True )" + return s:Pyeval( 'base.CompletionStartColumn()' ) else return s:GetCompletions() endif @@ -744,23 +772,23 @@ endfunction function! youcompleteme#ServerPid() - return pyeval( 'ycm_state.ServerPid()' ) + return s:Pyeval( 'ycm_state.ServerPid()' ) endfunction function! s:RestartServer() - py ycm_state.RestartServer() + exec s:python_command "ycm_state.RestartServer()" endfunction function! s:ShowDetailedDiagnostic() - py ycm_state.ShowDetailedDiagnostic() + exec s:python_command "ycm_state.ShowDetailedDiagnostic()" endfunction function! s:DebugInfo() echom "Printing YouCompleteMe debug information..." - let debug_info = pyeval( 'ycm_state.DebugInfo()' ) + let debug_info = s:Pyeval( 'ycm_state.DebugInfo()' ) for line in split( debug_info, "\n" ) echom '-- ' . line endfor @@ -770,8 +798,9 @@ endfunction function! s:ToggleLogs(...) let stderr = a:0 == 0 || a:1 !=? 'stdout' let stdout = a:0 == 0 || a:1 !=? 'stderr' - py ycm_state.ToggleLogs( stdout = vimsupport.GetBoolValue( 'l:stdout' ), - \ stderr = vimsupport.GetBoolValue( 'l:stderr' ) ) + exec s:python_command "ycm_state.ToggleLogs(" + \ "stdout = vimsupport.GetBoolValue( 'l:stdout' )," + \ "stderr = vimsupport.GetBoolValue( 'l:stderr' ) )" endfunction @@ -793,8 +822,8 @@ function! s:CompleterCommand(...) let arguments = arguments[1:] endif - py ycm_state.SendCommandRequest( vim.eval( 'l:arguments' ), - \ vim.eval( 'l:completer' ) ) + exec s:python_command "ycm_state.SendCommandRequest(" + \ "vim.eval( 'l:arguments' ), vim.eval( 'l:completer' ) ) " endfunction @@ -814,21 +843,21 @@ endfunction function! youcompleteme#SubCommandsComplete( arglead, cmdline, cursorpos ) - return join( pyeval( 'ycm_state.GetDefinedSubcommands()' ), + return join( s:Pyeval( 'ycm_state.GetDefinedSubcommands()' ), \ "\n") endfunction function! s:ForceCompile() - if !pyeval( 'ycm_state.NativeFiletypeCompletionUsable()' ) + if !s:Pyeval( 'ycm_state.NativeFiletypeCompletionUsable()' ) echom "Native filetype completion not supported for current file, " \ . "cannot force recompilation." return 0 endif echom "Forcing compilation, this will block Vim until done." - py ycm_state.OnFileReadyToParse() - py ycm_state.HandleFileParseRequest( True ) + exec s:python_command "ycm_state.OnFileReadyToParse()" + exec s:python_command "ycm_state.HandleFileParseRequest( True )" return 1 endfunction @@ -849,7 +878,7 @@ function! s:ShowDiagnostics() return endif - if pyeval( 'ycm_state.PopulateLocationListWithLatestDiagnostics()' ) + if s:Pyeval( 'ycm_state.PopulateLocationListWithLatestDiagnostics()' ) if g:ycm_open_loclist_on_ycm_diags lopen endif diff --git a/plugin/youcompleteme.vim b/plugin/youcompleteme.vim index b30ee632..8e5ebc25 100644 --- a/plugin/youcompleteme.vim +++ b/plugin/youcompleteme.vim @@ -33,10 +33,10 @@ elseif v:version < 703 || (v:version == 703 && !has('patch598')) \ echohl None call s:restore_cpo() finish -elseif !has( 'python' ) +elseif !has( 'python' ) && !has( 'python3' ) echohl WarningMsg | \ echomsg "YouCompleteMe unavailable: requires Vim compiled with " . - \ "Python 2.x support" | + \ "Python (2.6+ or 3.3+) support" | \ echohl None call s:restore_cpo() finish