@@ -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
6484endfunction
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+
66169function ! 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
94197endfunction
95198
96-
97199function ! s: _highlight () abort
98200 highlight default link VitalWindowSelectorStatusLine StatusLineNC
99201 highlight default link VitalWindowSelectorIndicator DiffText
0 commit comments