mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 17:40:06 +08:00
feat(scrollbar): add scrollbar support for vim
This commit is contained in:
parent
30d8b3dcb1
commit
fcc564ae25
@ -46,6 +46,14 @@ else
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:self.set_var(buf, var, val) abort
|
||||
return setbufvar(a:buf, a:var, a:val)
|
||||
endfunction
|
||||
|
||||
function! s:self.get_var(buf, var) abort
|
||||
return getbufvar(a:buf, a:var)
|
||||
endfunction
|
||||
|
||||
" bufnr needs atleast one argv before patch-8.1.1924 has('patch-8.1.1924')
|
||||
function! s:self.bufnr(...) abort
|
||||
if has('patch-8.1.1924')
|
||||
|
@ -81,6 +81,18 @@ function! s:self.open_win(buffer, focuce, options) abort
|
||||
let highlight = get(a:options, 'highlight', 'Normal')
|
||||
let relative = get(a:options, 'relative', 'editor')
|
||||
if relative ==# 'win'
|
||||
let winid = get(a:options, 'win', 0)
|
||||
let pos = win_screenpos(win_id2win(winid))
|
||||
let opt = {
|
||||
\ 'line' : row + 1 + pos[0],
|
||||
\ 'col' : col + pos[1],
|
||||
\ 'maxheight' : height,
|
||||
\ 'minheight' : height,
|
||||
\ 'maxwidth' : width,
|
||||
\ 'minwidth' : width,
|
||||
\ 'highlight' : highlight,
|
||||
\ 'scrollbar' : 0,
|
||||
\ }
|
||||
elseif relative ==# 'cursor'
|
||||
elseif relative ==# 'editor'
|
||||
let opt = {
|
||||
@ -105,6 +117,18 @@ function! s:self.win_config(winid, options) abort
|
||||
let highlight = get(a:options, 'highlight', '')
|
||||
let relative = get(a:options, 'relative', 'editor')
|
||||
if relative ==# 'win'
|
||||
let winid = get(a:options, 'win', 0)
|
||||
let pos = win_screenpos(win_id2win(winid))
|
||||
let opt = {
|
||||
\ 'line' : row + 1 + pos[0],
|
||||
\ 'col' : col + pos[1],
|
||||
\ 'maxheight' : height,
|
||||
\ 'minheight' : height,
|
||||
\ 'maxwidth' : width,
|
||||
\ 'minwidth' : width,
|
||||
\ 'highlight' : highlight,
|
||||
\ 'scrollbar' : 0,
|
||||
\ }
|
||||
elseif relative ==# 'cursor'
|
||||
elseif relative ==# 'editor'
|
||||
let opt = {
|
||||
|
@ -25,7 +25,7 @@
|
||||
"
|
||||
" Sets the cursor position to {pos} in the window {winid}.
|
||||
"
|
||||
" is_float({winnr})
|
||||
" is_float({winid})
|
||||
"
|
||||
" Check if the window is a floating windows, return `v:true` if the window
|
||||
" is a floating window.
|
||||
@ -73,25 +73,22 @@ else
|
||||
endif
|
||||
|
||||
if has('nvim')
|
||||
function! s:self.is_float(winnr) abort
|
||||
let id = win_getid(a:winnr)
|
||||
if id > 0 && exists('*nvim_win_get_config')
|
||||
return has_key(nvim_win_get_config(id), 'col')
|
||||
function! s:self.is_float(winid) abort
|
||||
if a:winid > 0 && exists('*nvim_win_get_config')
|
||||
try
|
||||
return has_key(nvim_win_get_config(a:winid), 'col')
|
||||
catch
|
||||
return 0
|
||||
endtry
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
else
|
||||
function! s:self.is_float(winnr) abort
|
||||
" vim without win_getid() is old, which do not support floating window.
|
||||
" so if_float always return 0
|
||||
if !exists('*win_getid')
|
||||
return 0
|
||||
endif
|
||||
let id = win_getid(a:winnr)
|
||||
if id > 0 && exists('*popup_getoptions')
|
||||
function! s:self.is_float(winid) abort
|
||||
if a:winid > 0 && exists('*popup_getoptions')
|
||||
try
|
||||
return has_key(popup_getoptions(id), 'col')
|
||||
return has_key(popup_getoptions(a:winid), 'col')
|
||||
catch /^Vim\%((\a\+)\)\=:E993/
|
||||
return 0
|
||||
endtry
|
||||
|
@ -171,7 +171,7 @@ function! SpaceVim#layers#ui#config() abort
|
||||
augroup spacevim_layer_ui
|
||||
autocmd!
|
||||
let events = join(filter( ['BufEnter','WinEnter', 'QuitPre', 'CursorMoved', 'VimResized', 'FocusGained', 'WinScrolled' ], 'exists("##" . v:val)'), ',')
|
||||
if s:enable_scrollbar && has('nvim')
|
||||
if s:enable_scrollbar && SpaceVim#plugins#scrollbar#usable()
|
||||
exe printf('autocmd %s * call SpaceVim#plugins#scrollbar#show()',
|
||||
\ events)
|
||||
autocmd WinLeave,BufLeave,BufWinLeave,FocusLost
|
||||
|
@ -371,7 +371,7 @@ fu! SpaceVim#mapping#SmartClose() abort
|
||||
let num = num - 1
|
||||
elseif getwinvar(i, '&previewwindow') == 1 && winnr() !=# i
|
||||
let num = num - 1
|
||||
elseif s:WIN.is_float(i)
|
||||
elseif s:WIN.is_float(win_getid(i))
|
||||
let num = num - 1
|
||||
endif
|
||||
endfor
|
||||
|
@ -678,7 +678,7 @@ if exists('*nvim_open_win') && exists('*nvim_win_set_buf')
|
||||
let linenr = str2nr(matchstr(line, ':\d\+:')[1:-2])
|
||||
noautocmd let bufnr = s:BUFFER.bufadd(filename)
|
||||
call bufload(bufnr)
|
||||
if s:Window.is_float(win_id2win(s:preview_win_id))
|
||||
if s:Window.is_float(s:preview_win_id)
|
||||
call nvim_win_set_buf(s:preview_win_id, bufnr)
|
||||
else
|
||||
let flygrep_win_height = 16
|
||||
@ -699,7 +699,7 @@ if exists('*nvim_open_win') && exists('*nvim_win_set_buf')
|
||||
call s:MPT._build_prompt()
|
||||
endfunction
|
||||
function! s:close_preview_win() abort
|
||||
if s:Window.is_float(win_id2win(s:preview_win_id))
|
||||
if s:Window.is_float(s:preview_win_id)
|
||||
call s:FLOATING.win_close(s:preview_win_id, 1)
|
||||
endif
|
||||
endfunction
|
||||
@ -943,7 +943,7 @@ function! s:update_statusline() abort
|
||||
return
|
||||
endif
|
||||
|
||||
if s:SL.support_float() && win_id2tabwin(s:flygrep_win_id)[0] ==# tabpagenr() && s:Window.is_float(win_id2win(s:flygrep_win_id))
|
||||
if s:SL.support_float() && win_id2tabwin(s:flygrep_win_id)[0] ==# tabpagenr() && s:Window.is_float(s:flygrep_win_id)
|
||||
noautocmd call s:SL.open_float([
|
||||
\ ['FlyGrep ', 'SpaceVim_statusline_a_bold'],
|
||||
\ [' ', 'SpaceVim_statusline_a_SpaceVim_statusline_b'],
|
||||
|
@ -9,6 +9,13 @@
|
||||
let s:VIM = SpaceVim#api#import('vim')
|
||||
let s:BUF = SpaceVim#api#import('vim#buffer')
|
||||
let s:WIN = SpaceVim#api#import('vim#window')
|
||||
if has('nvim')
|
||||
let s:FLOAT = SpaceVim#api#import('neovim#floating')
|
||||
else
|
||||
let s:FLOAT = SpaceVim#api#import('vim#floating')
|
||||
endif
|
||||
let s:HI = SpaceVim#api#import('vim#highlight')
|
||||
let s:LOG = SpaceVim#logger#derive('scrollbar')
|
||||
|
||||
scriptencoding utf-8
|
||||
|
||||
@ -19,21 +26,29 @@ let s:default = {
|
||||
\ 'right_offset' : 1,
|
||||
\ 'excluded_filetypes' : ['startify', 'leaderf'],
|
||||
\ 'shape' : {
|
||||
\ 'head' : '▲',
|
||||
\ 'body' : '█',
|
||||
\ 'tail' : '▼',
|
||||
\ },
|
||||
\ 'highlight' : {
|
||||
\ 'head' : 'Normal',
|
||||
\ 'body' : 'Normal',
|
||||
\ 'tail' : 'Normal',
|
||||
\ }
|
||||
\ }
|
||||
\ 'head' : '▲',
|
||||
\ 'body' : '█',
|
||||
\ 'tail' : '▼',
|
||||
\ },
|
||||
\ 'highlight' : {
|
||||
\ 'head' : 'Normal',
|
||||
\ 'body' : 'Normal',
|
||||
\ 'tail' : 'Normal',
|
||||
\ }
|
||||
\ }
|
||||
|
||||
augroup spacevim_scrollbar
|
||||
autocmd!
|
||||
augroup END
|
||||
|
||||
let s:scrollbar_bufnr = -1
|
||||
let s:scrollbar_winid = -1
|
||||
|
||||
function! SpaceVim#plugins#scrollbar#usable() abort
|
||||
|
||||
return s:FLOAT.exists()
|
||||
|
||||
endfunction
|
||||
|
||||
" vim script do not support metatable function
|
||||
|
||||
@ -49,8 +64,22 @@ function! s:get(key) abort
|
||||
endfunction
|
||||
|
||||
|
||||
let s:ns_id = nvim_create_namespace('scrollbar')
|
||||
" this is only supported in neovim
|
||||
if exists('*nvim_create_namespace')
|
||||
let s:ns_id = nvim_create_namespace('scrollbar')
|
||||
function! s:add_highlight(bufnr, size) abort
|
||||
let highlight = s:get('highlight')
|
||||
call nvim_buf_add_highlight(a:bufnr, s:ns_id, highlight.head, 0, 0, -1)
|
||||
for i in range(1, a:size - 2)
|
||||
call nvim_buf_add_highlight(a:bufnr, s:ns_id, highlight.body, i, 0, -1)
|
||||
endfor
|
||||
call nvim_buf_add_highlight(a:bufnr, s:ns_id, highlight.tail, a:size - 1, 0, -1)
|
||||
endfunction
|
||||
else
|
||||
|
||||
function! s:add_highlight(bufnr, size) abort
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:gen_bar_lines(size) abort
|
||||
let shape = s:get('shape')
|
||||
@ -67,130 +96,80 @@ function! s:fix_size(size) abort
|
||||
return max([s:get('min_size'), min([s:get('max_size'), a:size])])
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:buf_get_var(bufnr, name) abort
|
||||
try
|
||||
let var = nvim_buf_get_var(a:bufnr, a:name)
|
||||
return var
|
||||
catch
|
||||
|
||||
endtry
|
||||
function! s:create_scrollbar_buffer(size, lines) abort
|
||||
if !bufexists(s:scrollbar_bufnr)
|
||||
let s:scrollbar_bufnr = s:BUF.create_buf(0, 1)
|
||||
endif
|
||||
call s:BUF.buf_set_lines(s:scrollbar_bufnr, 0, -1, 0, a:lines)
|
||||
call s:add_highlight(s:scrollbar_bufnr, a:size)
|
||||
return s:scrollbar_bufnr
|
||||
endfunction
|
||||
|
||||
function! s:add_highlight(bufnr, size) abort
|
||||
let highlight = s:get('highlight')
|
||||
call nvim_buf_add_highlight(a:bufnr, s:ns_id, highlight.head, 0, 0, -1)
|
||||
for i in range(1, a:size - 2)
|
||||
call nvim_buf_add_highlight(a:bufnr, s:ns_id, highlight.body, i, 0, -1)
|
||||
endfor
|
||||
call nvim_buf_add_highlight(a:bufnr, s:ns_id, highlight.tail, a:size - 1, 0, -1)
|
||||
endfunction
|
||||
|
||||
let s:next_index = 0
|
||||
function! s:next_buf_index() abort
|
||||
let s:next_index += 1
|
||||
return s:next_index - 1
|
||||
endfunction
|
||||
|
||||
function! s:create_buf(size, lines) abort
|
||||
noautocmd let bufnr = s:BUF.create_buf(0, 1)
|
||||
noautocmd call nvim_buf_set_option(bufnr, 'filetype', 'scrollbar')
|
||||
" noautocmd call nvim_buf_set_option(bufnr, 'bufhidden', 'wipe')
|
||||
noautocmd call nvim_buf_set_name(bufnr, 'scrollbar_' . s:next_buf_index())
|
||||
noautocmd call nvim_buf_set_lines(bufnr, 0, a:size, 0, a:lines)
|
||||
call s:add_highlight(bufnr, a:size)
|
||||
" exe printf('au spacevim_scrollbar BufDelete <buffer=%s> call SpaceVim#plugins#scrollbar#clear()', bufnr)
|
||||
return bufnr
|
||||
endfunction
|
||||
|
||||
function! SpaceVim#plugins#scrollbar#show(...) abort
|
||||
let winnr = get(a:000, 0, 0)
|
||||
let bufnr = get(a:000, 1, 0)
|
||||
let win_config = nvim_win_get_config(winnr)
|
||||
|
||||
" ignore other floating windows
|
||||
if win_config.relative !=# ''
|
||||
function! SpaceVim#plugins#scrollbar#show() abort
|
||||
let [winnr, bufnr, winid] = [winnr(), bufnr(), win_getid()]
|
||||
if s:WIN.is_float(winid)
|
||||
return
|
||||
endif
|
||||
|
||||
let excluded_filetypes = s:get('excluded_filetypes')
|
||||
let filetype = nvim_buf_get_option(bufnr, 'filetype')
|
||||
|
||||
if filetype == '' || index(excluded_filetypes, filetype) !=# -1
|
||||
if &filetype == '' || index(excluded_filetypes, &filetype) !=# -1
|
||||
return
|
||||
endif
|
||||
|
||||
let total = line('$')
|
||||
let height = nvim_win_get_height(winnr)
|
||||
let height = winheight(winnr)
|
||||
if total <= height
|
||||
call SpaceVim#plugins#scrollbar#clear()
|
||||
return
|
||||
endif
|
||||
|
||||
let cursor = nvim_win_get_cursor(winnr)
|
||||
let curr_line = cursor[0]
|
||||
let pos = getpos('.')
|
||||
let curr_line = pos[1]
|
||||
let bar_size = height * height / total
|
||||
let bar_size = s:fix_size(bar_size)
|
||||
|
||||
let width = nvim_win_get_width(winnr)
|
||||
let width = winwidth(winnr)
|
||||
let col = width - s:get('width') - s:get('right_offset')
|
||||
let row = (height - bar_size) * (curr_line * 1.0 / total)
|
||||
|
||||
let opts = {
|
||||
\ 'style' : 'minimal',
|
||||
\ 'relative' : 'win',
|
||||
\ 'win' : winnr,
|
||||
\ 'win' : winid,
|
||||
\ 'width' : s:get('width'),
|
||||
\ 'height' : bar_size,
|
||||
\ 'row' : row,
|
||||
\ 'col' : col,
|
||||
\ 'height' : float2nr(bar_size),
|
||||
\ 'row' : float2nr(row),
|
||||
\ 'col' : float2nr(col),
|
||||
\ 'focusable' : 0,
|
||||
\ }
|
||||
let [bar_winnr, bar_bufnr] = [0, 0]
|
||||
let state = s:buf_get_var(bufnr, 'scrollbar_state')
|
||||
if !empty(state)
|
||||
let bar_bufnr = state.bufnr
|
||||
if has_key(state, 'winnr') && win_id2win(state.winnr) > 0
|
||||
let bar_winnr = state.winnr
|
||||
else
|
||||
noautocmd let bar_winnr = nvim_open_win(bar_bufnr, 0, opts)
|
||||
endif
|
||||
let state = getbufvar(bufnr, 'scrollbar_state')
|
||||
if !empty(state) && s:WIN.is_float(s:scrollbar_winid)
|
||||
if state.size !=# bar_size
|
||||
noautocmd call nvim_buf_set_lines(bar_bufnr, 0, -1, 0, [])
|
||||
let bar_lines = s:gen_bar_lines(bar_size)
|
||||
noautocmd call nvim_buf_set_lines(bar_bufnr, 0, bar_size, 0, bar_lines)
|
||||
noautocmd call s:add_highlight(bar_bufnr, bar_size)
|
||||
call s:BUF.buf_set_lines(s:scrollbar_bufnr, 0, -1, 0, bar_lines)
|
||||
call s:add_highlight(s:scrollbar_bufnr, bar_size)
|
||||
endif
|
||||
noautocmd call nvim_win_set_config(bar_winnr, opts)
|
||||
noautocmd call s:FLOAT.win_config(s:scrollbar_winid, opts)
|
||||
else
|
||||
let bar_lines = s:gen_bar_lines(bar_size)
|
||||
let bar_bufnr = s:create_buf(bar_size, bar_lines)
|
||||
let bar_winnr = nvim_open_win(bar_bufnr, 0, opts)
|
||||
call nvim_win_set_option(bar_winnr, 'winhl', 'Normal:ScrollbarWinHighlight')
|
||||
let s:scrollbar_bufnr = s:create_scrollbar_buffer(bar_size, bar_lines)
|
||||
let s:scrollbar_winid = s:FLOAT.open_win(s:scrollbar_bufnr, 0, opts)
|
||||
if exists('&winhighlight')
|
||||
call setwinvar(win_id2win(s:scrollbar_winid), '&winhighlight', 'Normal:ScrollbarWinHighlight')
|
||||
endif
|
||||
endif
|
||||
call nvim_buf_set_var(bufnr, 'scrollbar_state', {
|
||||
\ 'winnr' : bar_winnr,
|
||||
\ 'bufnr' : bar_bufnr,
|
||||
call setbufvar(bufnr, 'scrollbar_state', {
|
||||
\ 'wind' : s:scrollbar_winid,
|
||||
\ 'bufnr' : s:scrollbar_bufnr,
|
||||
\ 'size' : bar_size,
|
||||
\ })
|
||||
return [bar_winnr, bar_bufnr]
|
||||
|
||||
endfunction
|
||||
|
||||
" the first argument is buffer number
|
||||
|
||||
function! SpaceVim#plugins#scrollbar#clear(...) abort
|
||||
let bufnr = get(a:000, 0, 0)
|
||||
let state = s:buf_get_var(bufnr, 'scrollbar_state')
|
||||
if !empty(state) && has_key(state, 'winnr')
|
||||
if win_id2win(state.winnr) > 0
|
||||
noautocmd call nvim_win_close(state.winnr, 1)
|
||||
endif
|
||||
noautocmd call nvim_buf_set_var(bufnr, 'scrollbar_state', {
|
||||
\ 'size' : state.size,
|
||||
\ 'bufnr' : state.bufnr,
|
||||
\ })
|
||||
if s:WIN.is_float(s:scrollbar_winid)
|
||||
call s:FLOAT.win_close(s:scrollbar_winid, 1)
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
|
@ -6313,7 +6313,7 @@ set_cursor({winid}, {pos})
|
||||
|
||||
Sets the cursor position to {pos} in the window {winid}.
|
||||
|
||||
is_float({winnr})
|
||||
is_float({winid})
|
||||
|
||||
Check if the window is a floating windows, return `v:true` if the window
|
||||
is a floating window.
|
||||
|
Loading…
Reference in New Issue
Block a user