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.