diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index d350f2b506..50825962f9 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -169,7 +169,7 @@ function! youcompleteme#Enable() " supported, enable it. let s:resolve_completions = s:RESOLVE_ON_DEMAND elseif require_resolve - " The preview window or info popup is enalbed - request the server + " The preview window or info popup is enabled - request the server " pre-resolves completion items let s:resolve_completions = s:RESOLVE_UP_FRONT else @@ -709,19 +709,28 @@ endfunction function! s:EnableAutoHover() - if g:ycm_auto_hover ==# 'CursorHold' && s:enable_hover - augroup YcmBufHover - autocmd! * - autocmd CursorHold call s:Hover() - augroup END + if s:enable_hover + if has( 'balloon_eval' ) + set ballooneval + endif + if has( 'balloon_eval_term' ) + set balloonevalterm + endif + if exists( '+balloonexpr' ) && empty( &balloonexpr ) + set balloonexpr=youcompleteme#hover() + endif endif endfunction function! s:DisableAutoHover() - augroup YcmBufHover - autocmd! * - augroup END + call popup_clear() + if has( 'balloon_eval' ) + set noballooneval + endif + if has( 'balloon_eval_term' ) + set noballoonevalterm + endif endfunction @@ -1245,7 +1254,7 @@ function! s:PollResolve( item, ... ) " Note we re-use the 'completion' request for resolves. This prevents us " sending a completion request and a resolve request at the same time, as - " resolve requests re-use the requset data from the last completion request + " resolve requests re-use the request data from the last completion request " and it must not change. " We also re-use the poller, so that any new completion request effectively " cancels this poller. @@ -1258,9 +1267,12 @@ function! s:PollResolve( item, ... ) call s:ShowInfoPopup( completion_item ) endfunction +set completepopup+=align:menu + function! s:ShowInfoPopup( completion_item ) let id = popup_findinfo() - if id + if id && !empty( a:completion_item.info ) + call popup_setoptions( id, { 'highlight': 'Pmenu' } ) call popup_settext( id, split( a:completion_item.info, '\n' ) ) call popup_show( id ) endif @@ -1584,11 +1596,10 @@ function! s:ForceCompileAndDiagnostics() endfunction -if exists( '*popup_atcursor' ) - function s:Hover() +if exists( '*popup_atcursor' ) && exists( '*popup_beval' ) + function s:Hover( hover_type ) if !py3eval( 'ycm_state.NativeFiletypeCompletionUsable()' ) " Cancel the autocommand if it happens to have been set - call s:DisableAutoHover() return endif @@ -1618,14 +1629,28 @@ if exists( '*popup_atcursor' ) return endif - call youcompleteme#GetCommandResponseAsync( - \ function( 's:ShowHoverResult' ), - \ b:ycm_hover.command ) + let s:hover_syntax = b:ycm_hover.syntax + if a:hover_type == 'cursorhold' + let s:hover_pos = screenpos( win_getid(), line( '.' ), col( '.' ) ) + let s:HoverPopupFunc = function( 'popup_atcursor' ) + call youcompleteme#GetCommandResponseAsync( + \ function( 's:ShowHoverResult' ), + \ b:ycm_hover.command ) + elseif a:hover_type == 'balloon' + let s:hover_pos = screenpos( v:beval_winid, v:beval_lnum, v:beval_col ) + let s:HoverPopupFunc = function( 'popup_beval' ) + call youcompleteme#GetCommandResponseAsync( + \ function( 's:ShowHoverResult' ), + \ b:ycm_hover.command, + \ '--bufnr=' . v:beval_bufnr, + \ '--line_num=' . v:beval_lnum, + \ '--column_num=' . v:beval_col ) + endif endfunction function! s:ShowHoverResult( response ) - call popup_hide( s:cursorhold_popup ) + call popup_close( s:cursorhold_popup ) if empty( a:response ) return @@ -1637,56 +1662,72 @@ if exists( '*popup_atcursor' ) " " Find the longest line (FIXME: probably doesn't work well for multi-byte) let lines = split( a:response, "\n" ) - let len = max( map( copy( lines ), "len( v:val )" ) ) + let len = max( map( copy( lines ), "strdisplaywidth( v:val )" ) ) + let col = s:hover_pos.col let wrap = 0 - let col = 'cursor' - - " max width is screen columns minus x padding (2) - if len >= (&columns - 2) - " There's at least one line > our max - enable word wrap and draw the + let border = { 'above': 1, 'right': 1, 'below': 1, 'left': 1 } + let padding = { 'above': 0, 'right': 1, 'below': 0, 'left': 1 } + let left_right_reserve = border.left + border.right + padding.left + padding.right + let above_below_reserve = border.above + border.below + padding.above + padding.below + let maxheight = max( [ s:hover_pos.row - 1, &lines - s:hover_pos.row ] ) - above_below_reserve + + " max width is screen columns minus border and padding + let maxwidth = &columns - left_right_reserve + let minwidth = min( [ len, maxwidth ] ) + if len >= maxwidth + " There's at least one line >= our max - enable word wrap and draw the " popup at the leftmost column let col = 1 let wrap = 1 endif - let s:cursorhold_popup = popup_atcursor( + let s:cursorhold_popup = s:HoverPopupFunc( \ lines, \ { - \ 'col': col, - \ 'wrap': wrap, - \ 'padding': [ 0, 1, 0, 1 ], - \ 'moved': 'word', - \ 'maxwidth': &columns, - \ 'close': 'click', - \ 'fixed': 0, + \ 'col' : col, + \ 'wrap' : wrap, + \ 'border' : [ border.above, border.right, border.below, border.left ], + \ 'padding' : [ padding.above, padding.right, padding.below, padding.left ], + \ 'maxheight': maxheight, + \ 'maxwidth' : maxwidth, + \ 'minwidth' : minwidth, + \ 'close' : 'click', + \ 'fixed' : 0, + \ 'resize' : 1, + \ 'drag' : 1 \ } \ ) + if popup_getpos( s:cursorhold_popup ).scrollbar + call popup_setoptions( s:cursorhold_popup, + \ { 'maxwidth': maxwidth - 1 } ) + endif call setbufvar( winbufnr( s:cursorhold_popup ), \ '&syntax', - \ b:ycm_hover.syntax ) + \ s:hover_syntax ) endfunction function! s:ToggleHover() let pos = popup_getpos( s:cursorhold_popup ) if !empty( pos ) && pos.visible - call popup_hide( s:cursorhold_popup ) + call popup_close( s:cursorhold_popup ) let s:cursorhold_popup = -1 - - " Diable the auto-trigger until the next cursor movement. - call s:DisableAutoHover() - augroup YCMHover - autocmd! CursorMoved - autocmd CursorMoved call s:EnableAutoHover() - augroup END else - call s:Hover() + call s:Hover( 'cursorhold' ) endif endfunction let s:enable_hover = 1 nnoremap (YCMHover) :call ToggleHover() + nnoremap (YCMHoverON) :call EnableAutoHover() + nnoremap (YCMHoverOFF) :call DisableAutoHover() + + function! youcompleteme#hover() + call win_execute( v:beval_winid, 'call s:Hover( "balloon" )' ) + return '' + endfunction + else " Don't break people's mappings if this feature is disabled, just do nothing. nnoremap (YCMHover) diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index 5d9ac6cd15..77760e66b7 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -393,6 +393,12 @@ def _GetCommandRequestArguments( self, elif argument.startswith( '--bufnr=' ): extra_data[ 'bufnr' ] = int( argument[ len( '--bufnr=' ): ] ) continue + elif argument.startswith( '--line_num=' ): + extra_data[ 'line_num' ] = int( argument[ len( '--line_num=' ): ] ) + continue + elif argument.startswith( '--column_num=' ): + extra_data[ 'column_num' ] = int( argument[ len( '--column_num=' ): ] ) + continue final_arguments.append( argument )