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

add support for floating window and popup #747

Open
prabirshrestha opened this issue Jun 25, 2020 · 6 comments
Open

add support for floating window and popup #747

prabirshrestha opened this issue Jun 25, 2020 · 6 comments

Comments

@prabirshrestha
Copy link

It would be good if vital.vim has a popup api that works in both vim and neovim. There has been some PRs related to this in vim-lsp at prabirshrestha/vim-lsp#510 and prabirshrestha/vim-lsp#567. Another one i found was this https://github.com/ZSaberLv0/ZFVimPopup. Lot of other plugins also has to keep creating wrappers to solve this issue.

Besides just a wrapper around vim and neovim apis there are other high level apis that would be necessary for the popup such as controlling direction and zindex. For example I might want to show LSP hover information above the cursor but diagnostics below the cursor. If autocomplete popup menu is open I might want to show the popup at the right of the complete menu but if it is to the end of the screen i might want to show it to the left instead or if at the bottom of the screen i might want to show at the top. Or might even want to dock it similar as https://github.com/ncm2/float-preview.nvim. Might also want to listen to buffer/window resizes and resize accordingly.

Since some of these are quite complicated specially when dealing with multiple popup at the same time my thought was to have 2 modules.

  1. Popup : This is a simple wrapper that is just bridges vim popup and neovim floating window apis.
  2. PopupManager: This is the bigger one which does the management of multiple popups.
@ujihisa
Copy link
Member

ujihisa commented Jun 25, 2020

Let's definitely have them. And yes let's have both the lower layor one to bridge and the one to orchestrate/coordinate a set of popups.

@prabirshrestha
Copy link
Author

This one seems interesting since it supports border which I believe neovim doesn't support by default. junegunn/fzf.vim#821 (comment) I have found popup without border very difficult to use since some colorschemes blend together and very difficult to know what the issue is.

I haven't played much with popup apis but would be good to hear thoughts from those who have experience around it.

@lambdalisue
Copy link
Member

Just note.

https://github.com/lambdalisue/loupe.vim/blob/master/autoload/loupe/viewer/nvim.vim#L24-L105

To provide borders in Neovim, we need to make the border by ourselves like above.

The feature request has closed in Neovim.
neovim/neovim#9718

@prabirshrestha
Copy link
Author

Here is an api I can think of some would most likely have to be pushed as a higher level api.

let s:Popup = vital#vital#import('UI.Popup')

function! s:demo() abort
    let popup = s:Popup.new({
        \ 'max_width': 'auto',
        \ 'max_height': 'auto',
        \ 'min_height': 'auto',
        \ 'min_width': 'auto',
        \ 'height': 10,
        \ 'width': 10,
        \ 'border': 1,
        \ 'borderchars': '',
        \ 'contents': ['hello', 'world'],
        \ 'screenpos': [0, 0],
        \ 'directionalhint': 'bottomleft|bottomright|topleftedge|topcenter',
        \ 'focusable': 0,
        \ 'zindex': 0,
        \ 'drag': 0,
        \ 'scrollbar': 0,
        \ 'on_event': function('s:on_event'),
        \ })
    let winid = popup.get_winid()

    let [height, width] = popup.get_dimensions(id)
    call popup.set_dimensions(height, width)
    " or
    let height = popup.get_height()
    let width = popup.get_width()
    call popup.set_height(height)
    call popup.set_width(width)

    let isopen = popup.is_open()
    call popup.show(id)  " open popup
    call popup.hide(id)  " popup is hidden
    " or
    call popup.set_visibility(0)
    let isvisible = popup.get_visiblity()

    let contents = popup.get_contents()
    call popup.set_contents(contents)

    call popup.focus() " focus cursor

    call popup.close(id) " disposes and cleans up the popup
endfunction

function! s:on_event(id, event, data) abort
    let l:popup = s:Popup.get(a:id)

    let l:bufnr = a:data['bufnr']
    let l:popuid = a:id

    if a:event == 'open'
        " register autocmd for cursor move so can auto close the popup
    elseif a:event == 'close'
    elseif a:event == 'focus'
    elseif a:event == 'blur'
    elseif a:event == 'hidden'
    elseif a:event == 'scrolldown'
    elseif a:event == 'scrollup'
    endif
endfunction

Another option is for s:Popup.new() to return an id which is a number instead of string so when using different languages such as lua or rpc it is very easy to pass references around. This does mean one would have to use call s:Popup.close(id)
//cc @hrsh7th since he had submitted a similar PR to refactor this for vim-lsp.

@prabirshrestha
Copy link
Author

sent initial PR at #748

@prabirshrestha
Copy link
Author

Seems like the border in neovim uses two floating window most likely to not have impact on syntax highlighting. In order to make it consistent with vim and have z-index the same might have to use the same trick on vim.

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

No branches or pull requests

3 participants