1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 09:20:06 +08:00
SpaceVim/lua/spacevim/plugin/scrollbar.lua

162 lines
4.0 KiB
Lua

--=============================================================================
-- scrollbar.lua --- scrollbar for SpaceVim
-- Copyright (c) 2016-2022 Wang Shidong & Contributors
-- Author: Wang Shidong < wsdjeg@outlook.com >
-- URL: https://spacevim.org
-- License: GPLv3
--=============================================================================
local M = {}
local win = require('spacevim.api.vim.window')
local default_conf = {
max_size = 10,
min_size = 3,
width = 1,
right_offset = 1,
excluded_filetypes = {
'startify',
'git-commit',
'leaderf',
'NvimTree',
'tagbar',
'defx',
'neo-tree',
'qf',
},
shape = {
head = '',
body = '',
tail = '',
},
highlight = {
head = 'Normal',
body = 'Normal',
tail = 'Normal',
},
}
local function get(opt)
return default_conf[opt]
end
local scrollbar_bufnr = -1
local scrollbar_winid = -1
local scrollbar_size = -1
local ns_id = vim.api.nvim_create_namespace('scrollbar')
local function add_highlight(bufnr, size)
local highlight = get('highlight')
vim.api.nvim_buf_add_highlight(bufnr, ns_id, highlight.head, 0, 0, -1)
for i = 1, size - 2 do
vim.api.nvim_buf_add_highlight(bufnr, ns_id, highlight.body, i, 0, -1)
end
vim.api.nvim_buf_add_highlight(bufnr, ns_id, highlight.tail, size - 1, 0, -1)
end
local function fix_size(size)
return math.max(get('min_size'), math.min(get('max_size'), math.floor(size + 0.5)))
end
local function gen_bar_lines(size)
local shape = get('shape')
local lines = { shape.head }
for _ = 2, size - 1 do
table.insert(lines, shape.body)
end
table.insert(lines, shape.tail)
return lines
end
local function create_scrollbar_buffer(size, lines)
if not vim.api.nvim_buf_is_valid(scrollbar_bufnr) then
scrollbar_bufnr = vim.api.nvim_create_buf(false, true)
end
vim.api.nvim_buf_set_lines(scrollbar_bufnr, 0, -1, false, lines)
add_highlight(scrollbar_bufnr, size)
return scrollbar_bufnr
end
function M.show()
local saved_ei = vim.o.eventignore
vim.o.eventignore = 'all'
local winnr = vim.fn.winnr()
local bufnr = vim.fn.bufnr()
local winid = vim.fn.win_getid()
if win.is_float(winid) then
M.clear()
vim.o.eventignore = saved_ei
return
end
local total = vim.api.nvim_buf_line_count(bufnr)
local height = vim.fn.winheight(winnr)
if total <= height then
M.clear()
vim.o.eventignore = saved_ei
return
end
local curr_line = vim.fn.line('w0')
local bar_size = fix_size(height * height / total)
local width = vim.fn.winwidth(winnr)
local col = width - get('width') - get('right_offset')
local precision = height - bar_size
local each_line = (total - height) * 1.0 / precision
local visble_line = vim.fn.min({ curr_line, total - height + 1 })
local row
if each_line >= 1 then
row = vim.fn.float2nr(visble_line / each_line)
else
row = vim.fn.float2nr(visble_line / each_line - 1 / each_line)
end
local opts = {
style = 'minimal',
relative = 'win',
win = winid,
width = get('width'),
height = bar_size,
row = row,
col = vim.fn.float2nr(col),
focusable = false,
zindex = 10,
}
if win.is_float(scrollbar_winid) then
if bar_size ~= scrollbar_size then
scrollbar_size = bar_size
local bar_lines = gen_bar_lines(bar_size)
vim.api.nvim_buf_set_lines(scrollbar_bufnr, 0, -1, false, bar_lines)
add_highlight(scrollbar_bufnr, bar_size)
end
vim.api.nvim_win_set_config(scrollbar_winid, opts)
else
scrollbar_size = bar_size
local bar_lines = gen_bar_lines(bar_size)
scrollbar_bufnr = create_scrollbar_buffer(bar_size, bar_lines)
scrollbar_winid = vim.api.nvim_open_win(scrollbar_bufnr, false, opts)
vim.fn.setwinvar(
vim.fn.win_id2win(scrollbar_winid),
'&winhighlight',
'Normal:ScrollbarWinHighlight'
)
end
vim.o.eventignore = saved_ei
end
function M.clear()
if vim.api.nvim_win_is_valid(scrollbar_winid) then
vim.api.nvim_win_close(scrollbar_winid, true)
end
end
function M.usable()
return true
end
return M