Skip to content

Commit 3afc6aa

Browse files
authored
Merge pull request #439 from skanehira/main
Add `g:fern#window_selector_use_popup` to use popup/float window when select window.
2 parents 23dc077 + b6fade3 commit 3afc6aa

File tree

4 files changed

+125
-16
lines changed

4 files changed

+125
-16
lines changed

autoload/fern.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ call s:Config.config(expand('<sfile>:p'), {
4242
\ 'drawer_keep': v:false,
4343
\ 'drawer_hover_popup_delay': 0,
4444
\ 'mark_symbol': '*',
45+
\ 'window_selector_use_popup': 0,
4546
\})
4647

4748
function! fern#version() abort

autoload/fern/internal/window.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ function! fern#internal#window#select() abort
2929
\ 'statusline_hl': 'FernWindowSelectStatusLine',
3030
\ 'indicator_hl': 'FernWindowSelectIndicator',
3131
\ 'use_winbar': g:fern#internal#window#use_winbar,
32+
\ 'use_popup': g:fern#window_selector_use_popup,
3233
\})
3334
endfunction
3435

autoload/vital/_fern/App/WindowSelector.vim

Lines changed: 118 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ function! s:select(winnrs, ...) abort
1515
\ 'indicator_hl': 'VitalWindowSelectorIndicator',
1616
\ 'winbar_hl': 'VitalWindowSelectorWinBar',
1717
\ 'use_winbar': &laststatus is# 3 && exists('&winbar'),
18+
\ 'use_popup': 0,
19+
\ 'popup_borderchars': ['', '', '', '', '', '', '', ''],
1820
\}, a:0 ? a:1 : {})
1921
if !options.use_winbar && &laststatus is# 3
2022
echohl WarningMsg
@@ -25,26 +27,40 @@ function! s:select(winnrs, ...) abort
2527
call win_gotoid(len(a:winnrs) ? win_getid(a:winnrs[0]) : win_getid())
2628
return 0
2729
endif
28-
let target = options.use_winbar ? '&winbar' : '&statusline'
2930
let length = len(a:winnrs)
30-
let store = {}
31-
for winnr in a:winnrs
32-
let store[winnr] = getwinvar(winnr, target)
33-
endfor
3431
try
3532
let scs = options.select_chars
3633
let chars = map(
3734
\ range(length + 1),
3835
\ { _, v -> get(scs, v, string(v)) },
3936
\)
40-
let l:S = funcref('s:_statusline', [
41-
\ options.use_winbar
42-
\ ? options.winbar_hl
43-
\ : options.statusline_hl,
44-
\ options.indicator_hl,
45-
\])
46-
call map(keys(store), { k, v -> setwinvar(v, target, S(v, chars[k])) })
47-
redrawstatus
37+
38+
if options.use_popup
39+
if len(options.popup_borderchars) != 8
40+
echohl WarningMsg
41+
echomsg 'vital: App.WindowSelector: number of popup_borderchars must be eight'
42+
echohl None
43+
return
44+
endif
45+
46+
let borderchars = s:_normalize_popup_borderchars(options.popup_borderchars)
47+
call s:_popup(a:winnrs, options.select_chars, borderchars)
48+
redraw
49+
else
50+
let target = options.use_winbar ? '&winbar' : '&statusline'
51+
let store = {}
52+
for winnr in a:winnrs
53+
let store[winnr] = getwinvar(winnr, target)
54+
endfor
55+
let l:S = funcref('s:_statusline', [
56+
\ options.use_winbar
57+
\ ? options.winbar_hl
58+
\ : options.statusline_hl,
59+
\ options.indicator_hl,
60+
\])
61+
call map(keys(store), { k, v -> setwinvar(v, target, S(v, chars[k])) })
62+
redrawstatus
63+
endif
4864
call s:_cnoremap_all(chars)
4965
let n = input('choose window: ')
5066
call s:_cunmap_all()
@@ -58,11 +74,98 @@ function! s:select(winnrs, ...) abort
5874
endif
5975
call win_gotoid(win_getid(a:winnrs[n]))
6076
finally
61-
call map(keys(store), { _, v -> setwinvar(v, target, store[v]) })
62-
redrawstatus
77+
if options.use_popup
78+
call s:_clear_popups()
79+
else
80+
call map(keys(store), { _, v -> setwinvar(v, target, store[v]) })
81+
redrawstatus
82+
endif
6383
endtry
6484
endfunction
6585

86+
" Convert popup window border character order to float window border character order
87+
function! s:_normalize_popup_borderchars(chars) abort
88+
if has('nvim')
89+
return a:chars
90+
endif
91+
92+
let borderchars = repeat([''], 8)
93+
" this is index for convert to float window border characters
94+
let idx = [4, 0, 5, 3, 6, 2, 7, 1]
95+
for i in range(len(idx))
96+
let borderchars[idx[i]] = a:chars[i]
97+
endfor
98+
return borderchars
99+
endfunction
100+
101+
let s:_popup_winids = []
102+
103+
if has('nvim')
104+
function! s:_clear_popups() abort
105+
for winid in s:_popup_winids
106+
call nvim_win_close(winid, 1)
107+
endfor
108+
let s:_popup_winids = []
109+
endfunction
110+
111+
function! s:_popup(winnrs, chars, borderchars) abort
112+
for idx in range(len(a:winnrs))
113+
let winnr = a:winnrs[idx]
114+
let char = a:chars[idx]
115+
let text = printf(' %s ', char)
116+
let [col, row] = [(winwidth(winnr) - len(text))/2, (winheight(winnr) - 3)/2]
117+
118+
let bufnr = nvim_create_buf(0, 1)
119+
call nvim_buf_set_lines(bufnr, 0, -1, 1, [text])
120+
121+
let opt = {
122+
\ 'relative': 'win',
123+
\ 'win': win_getid(winnr),
124+
\ 'width': len(text),
125+
\ 'height': 1,
126+
\ 'col': col,
127+
\ 'row': row,
128+
\ 'anchor': 'NE',
129+
\ 'style': 'minimal',
130+
\ 'focusable': 0,
131+
\ 'border': map(copy(a:borderchars), { _, v -> [v, 'NormalFloat'] }),
132+
\ }
133+
let winid = nvim_open_win(bufnr, 1, opt)
134+
call add(s:_popup_winids, winid)
135+
endfor
136+
endfunction
137+
138+
else
139+
function! s:_clear_popups() abort
140+
for winid in s:_popup_winids
141+
call popup_close(winid)
142+
endfor
143+
let s:_popup_winids = []
144+
endfunction
145+
146+
function! s:_popup(winnrs, chars, borderchars) abort
147+
for idx in range(len(a:winnrs))
148+
let winnr = a:winnrs[idx]
149+
let char = a:chars[idx]
150+
let text = printf(' %s ', char)
151+
152+
let [width, height] = [(winwidth(winnr) - len(text))/2, (winheight(winnr) - 3)/2]
153+
let [winrow, wincol] = win_screenpos(winnr)
154+
let row = winrow + height
155+
let col = wincol + width
156+
157+
let winid = popup_create([text], {
158+
\ 'col': col,
159+
\ 'line': row,
160+
\ 'border': [1, 1, 1, 1],
161+
\ 'borderchars': copy(a:borderchars),
162+
\ })
163+
call add(s:_popup_winids, winid)
164+
endfor
165+
endfunction
166+
167+
endif
168+
66169
function! s:_statusline(statusline_hl, indicator_hl, winnr, char) abort
67170
let width = winwidth(a:winnr) - len(a:winnr . '') - 6
68171
let leading = repeat(' ', width / 2)
@@ -93,7 +196,6 @@ function! s:_cunmap_all() abort
93196
endfor
94197
endfunction
95198

96-
97199
function! s:_highlight() abort
98200
highlight default link VitalWindowSelectorStatusLine StatusLineNC
99201
highlight default link VitalWindowSelectorIndicator DiffText

doc/fern.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,11 @@ VARIABLE *fern-variable*
562562
A |Number| value that specifies whether to synchronize file renames to the buffer
563563
Default: 0
564564

565+
*g:fern#window_selector_use_popup*
566+
A |Boolean| which use popup/float window to select window.
567+
See |fern-glossary-window-selector|
568+
Default: 0
569+
565570
-----------------------------------------------------------------------------
566571
COMMAND *fern-command*
567572

0 commit comments

Comments
 (0)