Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scrolling in vim8 popup window #975

Closed
yongrenjie opened this issue Dec 26, 2020 · 6 comments
Closed

Scrolling in vim8 popup window #975

yongrenjie opened this issue Dec 26, 2020 · 6 comments

Comments

@yongrenjie
Copy link

Hello, firstly thank you for your work on this plugin and related ones.

I installed vim-lsp on vim8 a few days ago, and found that scrolling in popup windows was not possible. I understand that a big part of the issue is that vim8's popup window interface is not very complete, which has also been mentioned in #395 and #403. (Please correct me if I am wrong about either of these!)

So I wrote a tiny function which helps to carry out the scrolling https://github.com/yongrenjie/dotfiles/blob/master/.vimrc#L57-L80., which is partly adapted from https://fortime.ws/blog/2020/03/14/20200312-01/ although I added some touches. It seems like it would be easier to integrate this into vim-lsp since you keep track of the popup window ID already. Would you be interested in a PR (might take a couple of days though as I'm not very good at vimscript)? Although I hardcoded it to 3 lines here, the user could conceivably choose how fast to scroll using a setting like g:vim_lsp_scroll_speed.

hover_example.mov
@polyzen
Copy link

polyzen commented Dec 26, 2020

Scrolling in popups generated by :LspHover works fine with mouse support, however scrolling in popups from completions via asyncomplete does not. It lets you scroll down about a page, then pops back up to the top.

@prabirshrestha
Copy link
Owner

Unfortunately vim8 doesn't support focusable popup so we cannot scroll by focusing on popup. We need to instead intercept keys and send commands to it.

It will be good if we can implement lsp#popup#scroll(val) command similar to what you have. This will get a bit tricky when we have multiple popups but I think it is a good start with what you have now and I can help you in the PR. My thought was to add some sort of window variable w:lsp_popup_type so when we are looping through the list of popups we can get that value and only change if if that is the case. I have plans to implement more popups for other features so we need to make sure we don't have conflict in the future.

Might be ping here for focusable popup support too while you send a PR for vim-lsp.

@prabirshrestha
Copy link
Owner

I just sent a PR in vim to allow focusing inside popup. Let us also see how that goes. If that gets accepted we can implement double tap feature for vim8 and you can use all the features of window inside popup same as how you work on any buffer.

@yongrenjie
Copy link
Author

@prabirshrestha Great! Ok, I will have a go at it. Is there any current scenario (in vim8) with multiple popups that I could test against? As far as I can tell, opening a new popup window (with :LspHover) will close any previously opened ones.

@bfrg
Copy link

bfrg commented Dec 28, 2020

Unfortunately vim8 doesn't support focusable popup so we cannot scroll by focusing on popup. We need to instead intercept keys and send commands to it.

You don't need to intercept keys. That's what popup-filters are for. Vim does this automatically for you. Here's a minimal example:

function s:popup_filter(winid, key) abort
    if a:key ==# "\<c-j>"
        call win_execute(a:winid, "normal! \<c-e>")
    elseif a:key ==# "\<c-k>"
        call win_execute(a:winid, "normal! \<c-y>")
    elseif a:key ==# "\<c-g>"
        call win_execute(a:winid, "normal! G")
    elseif a:key ==# "\<c-t>"
        call win_execute(a:winid, "normal! gg")
    elseif a:key ==# 'q'
        call popup_close(a:winid)
    else
        return v:false
    endif
    return v:true
endfunction

call range(100)
        \ ->map('string(v:val)')
        \ ->popup_create({
        \   'border': [],
        \   'moved': 'any',
        \   'minwidth': 60,
        \   'maxwidth': 60,
        \   'minheight': 10,
        \   'maxheight': 10,
        \   'filter': funcref('s:popup_filter'),
        \   'filtermode': 'n',
        \   'mapping': v:false
        \ })

With the above popup-filter you can scroll up and down with CTRL-K and CTRL-J, respectively, and to top and bottom with CTRL-T and CTRL-G. These mappings will be available only while the popup window is visible. The mapping entry is set to v:false to disable any user mappings. See :h popup-usage for the other entries. In the above example q, or moving the cursor in any direction will close the popup window. When a popup filter is specified, CTRL-C always closes the popup window, starting with the one with the highest zindex.

You could make the keys for scrolling customizable, for example:

function s:popup_filter(winid, key) abort
    if a:key ==# get(g:, 'lsp_popup_scroll_down', "\<c-j>")
        call win_execute(a:winid, "normal! \<c-e>")
    elseif a:key ==# get(g:, 'lsp_popup_scroll_up', "\<c-k>")
        call win_execute(a:winid, "normal! \<c-y>")
    else
        return v:false
    endif
    return v:true
endfunction

@prabirshrestha
Copy link
Owner

Scrolling is now supported by #1058.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants