Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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