5

How can I scroll and hide a floating window in Vim using the coc.nvim plugin?

I added these mappings to my vim.rc file but I still cannot manage it. I would expect if I press ctrl+f once I have a floating window in normal mode then it scrolls or if I press my leader key \ + h then it hides it. What do I do wrong? Thank you!

nmap <silent> <leader>h <Plug>(coc-float-hide)

"coc#util#float_scroll({forward})
"Return expr for scrolling a floating window forward or backward. ex: >

nnoremap <expr><C-f> coc#util#has_float() ? coc#util#float_scroll(1) : "\<C-f>"
nnoremap <expr><C-b> coc#util#has_float() ? coc#util#float_scroll(0) : "\<C-b>"

enter image description here

2
  • I use vim 8 on Mac. I read this overlay must be a popup and does not have these commands.
    – Lajos
    Nov 15, 2019 at 12:13
  • 1
    Do note that vim.rc =/= vimrc
    – D. Ben Knoble
    Nov 15, 2019 at 16:09

1 Answer 1

6

This is a general way to scroll popup window above or under around cursor, it first get winid by test :h popup_locate() with screen cursor position, then update firstline of the found window.

I didn't add the close map, AFAIK, it's closed automatically when you move your cursor.

Note that the beginning and ending of scroll is affected by :h 'scrolloff'

code update :

  • Removed hardcoded binding.
  • Use :h popup_getpos() to get firstline, simplify scroll logic.
  • Test entire rect instead of 2 corners in find_cursor_popup().

known issue

  • I use <esc> instead of blank as no operation, as blank doesn't trigger popup window redraw. <esc> will also trigger a bell, you may use set belloff+=esc to deal with it.
nnoremap <expr> <c-d> misc#popup#scroll_cursor_popup(1) ? '<esc>' : '<c-d>'
nnoremap <expr> <c-u> misc#popup#scroll_cursor_popup(0) ? '<esc>' : '<c-u>'

function misc#popup#find_cursor_popup(...)
  let radius = get(a:000, 0, 2)
  let srow = screenrow()
  let scol = screencol()

  " it's necessary to test entire rect, as some popup might be quite small
  for r in range(srow - radius, srow + radius)
    for c in range(scol - radius, scol + radius)
      let winid = popup_locate(r, c)
      if winid != 0
        return winid
      endif
    endfor
  endfor

  return 0
endfunction

function misc#popup#scroll_cursor_popup(down)
  let winid = misc#popup#find_cursor_popup()
  if winid == 0
    return 0
  endif

  let pp = popup_getpos(winid)
  call popup_setoptions( winid,
        \ {'firstline' : pp.firstline + ( a:down ? 1 : -1 ) } )

  return 1
endfunction

There is an open issue about this.

7
  • This works. Only thing I had to update was the fn name s:find_cursor_popupis scroll_popup in the key mappings. Amazing, many thanks!
    – Lajos
    Nov 15, 2019 at 14:49
  • Forgot to change map, Updated.
    – dedowsdi
    Nov 15, 2019 at 14:54
  • Thank you again
    – Lajos
    Nov 15, 2019 at 16:57
  • @Lajos The original script failed to locate popup in certain conditions, it's fixed now.
    – dedowsdi
    Nov 16, 2019 at 3:01
  • 2
    I got 2 errors after adding those lines to .vimrc. E746: Function name does not match script file name: misc#popup#find_cursor_popup and E746: Function name does not match script file name: misc#popup#scroll_cursor_popup
    – sify
    Apr 29, 2020 at 6:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.