From b467e2e599ca69022bd838f496eda211fe642a18 Mon Sep 17 00:00:00 2001 From: Shuangcheng-Ni <110970449+Shuangcheng-Ni@users.noreply.github.com> Date: Sun, 25 Dec 2022 21:40:22 +0800 Subject: [PATCH 1/3] Show balloon hovers instead of cursorhold hovers --- autoload/youcompleteme.vim | 94 +++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index bd4a94d92c..a6976f602c 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,18 @@ 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 + set ballooneval + set balloonevalterm + set balloonexpr=youcompleteme#hover() endif endfunction function! s:DisableAutoHover() - augroup YcmBufHover - autocmd! * - augroup END + call popup_clear() + set noballooneval + set noballoonevalterm endfunction @@ -1259,7 +1258,9 @@ endfunction function! s:ShowInfoPopup( completion_item ) let id = popup_findinfo() - if id + if id && !empty( a:completion_item.info ) + call setwinvar( id, '&number', 0 ) + call setwinvar( id, '&wincolor', 'Pmenu' ) call popup_settext( id, split( a:completion_item.info, '\n' ) ) call popup_show( id ) endif @@ -1583,11 +1584,10 @@ function! s:ForceCompileAndDiagnostics() endfunction -if exists( '*popup_atcursor' ) +if exists( '*popup_beval' ) function s:Hover() if !py3eval( 'ycm_state.NativeFiletypeCompletionUsable()' ) " Cancel the autocommand if it happens to have been set - call s:DisableAutoHover() return endif @@ -1619,7 +1619,10 @@ if exists( '*popup_atcursor' ) call youcompleteme#GetCommandResponseAsync( \ function( 's:ShowHoverResult' ), - \ b:ycm_hover.command ) + \ b:ycm_hover.command, + \ '--bufnr=' . v:beval_bufnr, + \ '--line_num=' . v:beval_lnum, + \ '--column_num=' . v:beval_col ) endfunction @@ -1636,56 +1639,85 @@ 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 mousepos = screenpos( v:beval_winid, v:beval_lnum, v:beval_col ) + let col = mousepos.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( [ mousepos.row - 1, &lines - mousepos.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 = popup_beval( \ 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 ) + \ getbufvar( v:beval_bufnr, 'ycm_hover' ).syntax ) endfunction function! s:ToggleHover() + if !s:enable_hover + return + endif + let pos = popup_getpos( s:cursorhold_popup ) if !empty( pos ) && pos.visible call popup_hide( s:cursorhold_popup ) let s:cursorhold_popup = -1 - " Diable the auto-trigger until the next cursor movement. + " Disable the auto-trigger until the next cursor movement. call s:DisableAutoHover() augroup YCMHover autocmd! CursorMoved - autocmd CursorMoved call s:EnableAutoHover() + autocmd CursorMoved ++once call s:EnableAutoHover() augroup END else - call s:Hover() + call s:EnableAutoHover() endif endfunction let s:enable_hover = 1 nnoremap (YCMHover) :call ToggleHover() + nnoremap (YCMHoverON) :call EnableAutoHover() + nnoremap (YCMHoverOFF) :call DisableAutoHover() + autocmd InsertEnter silent call s:DisableAutoHover() + autocmd InsertLeave silent call s:EnableAutoHover() + + function! youcompleteme#hover() + call win_execute( v:beval_winid, 'call s:Hover()' ) + return '' + endfunction else " Don't break people's mappings if this feature is disabled, just do nothing. nnoremap (YCMHover) From 2b52613307dc70add19bbd984db99860efbbb05b Mon Sep 17 00:00:00 2001 From: Shuangcheng-Ni <110970449+Shuangcheng-Ni@users.noreply.github.com> Date: Sun, 15 Jan 2023 11:44:59 +0800 Subject: [PATCH 2/3] Update youcompleteme.py --- python/ycm/youcompleteme.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index 7bd88d72a6..49ca0eedbb 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 ) From 728fb7e2c842f619d7c30e7f8f995c1aab01683e Mon Sep 17 00:00:00 2001 From: Shuangcheng-Ni <110970449+Shuangcheng-Ni@users.noreply.github.com> Date: Fri, 3 Mar 2023 16:02:51 +0800 Subject: [PATCH 3/3] ycm's balloonexpr will not override vimspector's --- autoload/youcompleteme.vim | 93 +++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index 85d81dddb5..50825962f9 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -710,17 +710,27 @@ endfunction function! s:EnableAutoHover() if s:enable_hover - set ballooneval - set balloonevalterm - set balloonexpr=youcompleteme#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() call popup_clear() - set noballooneval - set noballoonevalterm + if has( 'balloon_eval' ) + set noballooneval + endif + if has( 'balloon_eval_term' ) + set noballoonevalterm + endif endfunction @@ -1244,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. @@ -1257,11 +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 && !empty( a:completion_item.info ) - call setwinvar( id, '&number', 0 ) - call setwinvar( id, '&wincolor', 'Pmenu' ) + call popup_setoptions( id, { 'highlight': 'Pmenu' } ) call popup_settext( id, split( a:completion_item.info, '\n' ) ) call popup_show( id ) endif @@ -1585,8 +1596,8 @@ function! s:ForceCompileAndDiagnostics() endfunction -if exists( '*popup_beval' ) - 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 return @@ -1618,17 +1629,28 @@ if exists( '*popup_beval' ) return endif - call youcompleteme#GetCommandResponseAsync( - \ function( 's:ShowHoverResult' ), - \ b:ycm_hover.command, - \ '--bufnr=' . v:beval_bufnr, - \ '--line_num=' . v:beval_lnum, - \ '--column_num=' . v:beval_col ) + 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 @@ -1642,14 +1664,13 @@ if exists( '*popup_beval' ) let lines = split( a:response, "\n" ) let len = max( map( copy( lines ), "strdisplaywidth( v:val )" ) ) - let mousepos = screenpos( v:beval_winid, v:beval_lnum, v:beval_col ) - let col = mousepos.col + let col = s:hover_pos.col let wrap = 0 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( [ mousepos.row - 1, &lines - mousepos.row ] ) - above_below_reserve + 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 @@ -1661,13 +1682,13 @@ if exists( '*popup_beval' ) let wrap = 1 endif - let s:cursorhold_popup = popup_beval( + let s:cursorhold_popup = s:HoverPopupFunc( \ lines, \ { \ 'col' : col, \ 'wrap' : wrap, - \ 'border' : [ border['above'], border['right'], border['below'], border['left'] ], - \ 'padding' : [ padding['above'], padding['right'], padding['below'], padding['left'] ], + \ 'border' : [ border.above, border.right, border.below, border.left ], + \ 'padding' : [ padding.above, padding.right, padding.below, padding.left ], \ 'maxheight': maxheight, \ 'maxwidth' : maxwidth, \ 'minwidth' : minwidth, @@ -1683,28 +1704,17 @@ if exists( '*popup_beval' ) endif call setbufvar( winbufnr( s:cursorhold_popup ), \ '&syntax', - \ getbufvar( v:beval_bufnr, 'ycm_hover' ).syntax ) + \ s:hover_syntax ) endfunction function! s:ToggleHover() - if !s:enable_hover - return - endif - 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 - - " Disable the auto-trigger until the next cursor movement. - call s:DisableAutoHover() - augroup YCMHover - autocmd! CursorMoved - autocmd CursorMoved ++once call s:EnableAutoHover() - augroup END else - call s:EnableAutoHover() + call s:Hover( 'cursorhold' ) endif endfunction @@ -1712,13 +1722,12 @@ if exists( '*popup_beval' ) nnoremap (YCMHover) :call ToggleHover() nnoremap (YCMHoverON) :call EnableAutoHover() nnoremap (YCMHoverOFF) :call DisableAutoHover() - autocmd InsertEnter silent call s:DisableAutoHover() - autocmd InsertLeave silent call s:EnableAutoHover() function! youcompleteme#hover() - call win_execute( v:beval_winid, 'call s: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)