Use balloon hovers instead of cursorhold hovers to show documents #4106
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
PR Prelude
Thank you for working on YCM! :)
Please complete these steps and check these boxes (by putting an
x
insidethe brackets) before filing your PR:
rationale for why I haven't.
actually perform all of these steps.
Why this change is necessary and useful
The advantages of balloon hovers
updatetime
is too short, cursorhold hovers are quite likely to pop up frequently when a user is moving the vim cursor, which overshadows file contents all the time. Whenupdatetime
is too long, a user has to wait for a long time before the desired cursorhold popup emerges. When the user disables auto hover, he/she has to manually trigger cursorhold hovers over and over again. All these cases are quite annoying. If we use balloon hovers, no popups will come to make trouble when we move the vim cursor as long as the mouse isn't moved. We can also setballoondelay
to a moderate time, so we won't have to wait for too long.My design: balloon hovers for auto hover and cursorhold hovers for manual hover
Considering these advantages, balloon hovers can be used for auto hover. Some users might prefer to use the mouse to point at the text while reading a long document. Balloon hovers are volatile in this case, so I still preserve cursorhold hovers which can be triggered manually.
Bad news
The changes are listed as follows
line 1726:
youcompleteme#hover()
The
youcompleteme#hover()
function generates the content of a balloon hover. I usewin_execute()
here to ensure thes:Hover()
function to be executed in the buffer/window where the mouse pointer is, since the mouse pointer and the vim cursor can be in different buffers/windows.line 711:
s:EnableAutoHover()
&s:DisableAutoHover()
I use
set (no)ballooneval/(no)balloonevalterm
to enable/disable auto hover. In functions:EnableAutoHover()
, the'balloonexpr'
option won't be overridden if&balloonexpr
is not an empty string. Therefore, the'balloonexpr'
option set byvimspector
will be preserved while debugging.line 1599:
exists( '*popup_beval' )
I use
exists( '*popup_beval' )
to judge whether the balloon popup feature is available.line 1600:
s:Hover()
The
s:Hover()
function is modified to take an argument namedhover_type
, which should be either'cursorhold'
or'balloon'
.a:hover_type == 'balloon'
In this case, the
s:Hover()
function should be called bycall win_execute( v:beval_winid, 'call s:Hover()' )
, so theb:ycm_hover
variable is related to the buffer/window where the mouse pointer is andb:ycm_hover.command
is executed at the mouse pointer. To get the location of the mouse pointer, I add some arguments tob:ycm_hover.command
, including--bufnr=v:beval_bufnr
,--line_num=v:beval_lnum
and--column_num=v:beval_col
.--line_num
and--column_num
are not supported by ycm currently. They depend on my previous PR.a:hover_type == 'cursorhold'
No changes.
Since the callback of
youcompleteme#GetCommandResponseAsync()
(i.e.s:ShowHoverResult()
) is always executed in the buffer/window where the vim cursor is, I uses:hover_syntax
to saveb:ycm_hover.syntax
which might be local to the buffer/window where the mouse pointer is.s:hover_pos
saves the position of the identifier at the vim cursor/mouse pointer.s:HoverPopupFunc
saves the Funcref ofpopup_atcursor()/popup_beval()
. These script variables free me from writing twos:ShowHoverResult()
s.line 1652:
s:ShowHoverResult()
strdisplaywidth()
instead oflen()
. This fixes the problem of multi-byte characters the author mentioned here.maxheight
can prevent the popup from exceeding the bottom of the screen. In vim 8.1, it is possible for popups to exceed the bottom of the screen. In vim 9.0, the problem has been fixed. For compatibility,maxheight
should be explicitly set here.maxwidth
is screen columns minus border and padding and sometimes the potential scrollbar.minwidth
can prevent the popup from getting wider or narrower during scrolling. The maximum line width in different pages of a popup might differ, so the width of the popup might change after scrolling down a page.line 1711:
s:ToggleHover()
When there is a visible cursorhold/balloon popup, this function will close it. Otherwise, a cursorhold popup will be generated. There is also the
<plug>(YCMHover)
mapping, which can be used to manually trigger cursorhold hovers or close an existing popup. I also add some mappings to enable/disable auto hover permanently, including<plug>(YCMHoverON)
and<plug>(YCMHoverOFF)
.Balloon hovers might cause the completion menu and the info popup next to it to disappear in insert mode. This is a vim bug (see this issue). The problem has been fixed since vim-patch:9.0.1371. If one's vim doesn't contain this patch, he/she can disable auto hover before entering insert mode and enable auto hover again after leaving insert mode by adding the following code in
<YouCompleteMe repo>/autoload/youcompleteme.vim
.line 1270:
s:ShowInfoPopup()
In insert mode, the info popup next to the completion menu should not be shown if it contains nothing, so we should judge whether
a:completion_item.info
is empty.set completepopup+=align:menu
prevents the info popup from jumping up and down. I also highlight the info popup asPmenu
, which isPmenuSel
by default and that looks too bright.Remaining problems
I'm considering to let users choose the type of hovers by themselves through something like(solved)let g:ycm_hover_type = 'cursorhold/balloon'
.Since(solved)ballooneval/balloonevalterm/balloonexpr
are global options, they might override the settings by user or from other plugins, or be overridden by other settings.This change is