Skip to content

Commit

Permalink
Merge pull request #403 from hrsh7th/improve-hover-popup
Browse files Browse the repository at this point in the history
Improve hover popup behavior
  • Loading branch information
lambdalisue authored Mar 28, 2022
2 parents 45950d3 + c28c4ab commit 085b74e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 36 deletions.
1 change: 1 addition & 0 deletions autoload/fern.vim
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ call s:Config.config(expand('<sfile>:p'), {
\ 'comparators': {},
\ 'drawer_width': 30,
\ 'drawer_keep': v:false,
\ 'drawer_hover_popup_delay': 0,
\ 'mark_symbol': '*',
\})

Expand Down
106 changes: 71 additions & 35 deletions autoload/fern/internal/drawer/hover_popup.vim
Original file line number Diff line number Diff line change
@@ -1,63 +1,99 @@
let s:win = v:null
let s:show_timer = 0

function! fern#internal#drawer#hover_popup#init() abort
if g:fern#disable_drawer_hover_popup
return
endif

if !exists('*popup_create')
call fern#logger#warn('hover popup is not supported, popup_create()
if !s:available()
call fern#logger#warn('hover popup is not supported, popup_create() or nvim environment
\ does not exist. Disable this message
\ with g:fern#disable_drawer_hover_popup.')
return
endif

augroup fern_internal_drawer_hover_popup_init
autocmd! * <buffer>
autocmd CursorMoved <buffer> call s:cursor_moved_event()
autocmd CursorMoved <buffer> call s:debounced_show()
autocmd BufLeave <buffer> call s:hide()
augroup END
endfunction

function! fern#internal#drawer#hover_popup#calculate_node_char_offset(node) abort
" find line offset where label text begins
let line = getline('.')
let labelbegin = charidx(line, strridx(line, a:node.label))
let labelbegin = labelbegin < 0 ? 0 : labelbegin

let windowid = win_getid()

" get cursor position in drawer window (char- and byte-indexed)
let charpos = getcursorcharpos(windowid)
let pos = getcurpos(windowid)

" get cursor position relative to screen
let cursorpos = screenpos(windowid, pos[1], pos[2])

" calculate screen column where label text begins
return cursorpos['col'] - charpos[2] + labelbegin
function! s:available() abort
let has_win = has('nvim') || exists('*popup_create')
return has_win && exists('*win_execute')
endfunction

function! fern#internal#drawer#hover_popup#should_display_popup() abort
return len(getline('.')) >= winwidth(0)
function! s:debounced_show() abort
call s:hide()
let s:show_timer = timer_start(g:fern#drawer_hover_popup_delay, { -> s:show() })
endfunction

function! s:cursor_moved_event() abort
let helper = fern#helper#new()
function! s:show() abort
if &filetype !=# 'fern'
return
endif
call s:hide()

if fern#internal#drawer#hover_popup#should_display_popup()
call s:show_popup(helper)
if strdisplaywidth(getline('.')) <= winwidth(0)
return
endif
endfunction

function! s:show_popup(helper) abort
let node = a:helper.sync.get_cursor_node()
let helper = fern#helper#new()
let node = helper.sync.get_cursor_node()
if node is# v:null
return
endif

let label_offset = fern#internal#drawer#hover_popup#calculate_node_char_offset(node)
call popup_create(l:node.label, {
\ 'line': 'cursor',
\ 'col': label_offset + 1,
\ 'moved': 'any',
\})
let line = getline('.')
let width = strdisplaywidth(substitute(line, '[^[:print:]]*$', '', 'g'))
if has('nvim')
let s:win = nvim_open_win(nvim_create_buf(v:false, v:true), v:false, {
\ 'relative': 'win',
\ 'bufpos': [line('.') - 2, 0],
\ 'width': width,
\ 'height': 1,
\ 'noautocmd': v:true,
\ 'style': 'minimal',
\ })
else
let ui_width = screenpos(0, line('.'), 1).col - win_screenpos(0)[1]
let s:win = popup_create(line, {
\ 'line': 'cursor',
\ 'col': ui_width + 1,
\ 'maxwidth': width,
\ })
endif

function! s:apply() abort closure
call setbufline('%', 1, line)
call helper.fern.renderer.syntax()
call helper.fern.renderer.highlight()
syntax clear FernRoot
syntax clear FernRootText

setlocal nowrap cursorline noswapfile nobuflisted buftype=nofile bufhidden=hide
if has('nvim')
setlocal winhighlight=NormalFloat:Normal
endif
endfunction
call win_execute(s:win, 'call s:apply()', v:true)
endfunction

function! s:hide() abort
call timer_stop(s:show_timer)

if s:win is# v:null
return
endif
if has('nvim')
if nvim_win_is_valid(s:win)
call nvim_win_close(s:win, v:true)
endif
else
call popup_close(s:win)
endif
let s:win = v:null
endfunction

8 changes: 7 additions & 1 deletion doc/fern.txt
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ VARIABLE *fern-variable*
Set 1 to disable popups shown when the name of a node extends beyond
the width of the drawer.

Note that this feature is not supported in Neovim.
Note that this feature is required the |win_execute| and
popup/floatwin features.

Default: 0

Expand Down Expand Up @@ -530,6 +531,11 @@ VARIABLE *fern-variable*
open or close.
Default: |v:false|

*g:fern#drawer_hover_popup_delay*
A |Number| value to specify the delay time to show the hover popup.
See |g:fern#disable_drawer_hover_popup|
Default: |0|

*g:fern#mark_symbol*
A |String| which is used as a mark symbol text.
Note that users must restart Vim to apply changes.
Expand Down

0 comments on commit 085b74e

Please sign in to comment.