Files
dotfiles/dot_config/nvim/lua/plugins/scrollbar.lua
T
2026-10-27 10:02:27 -04:00

107 lines
3.5 KiB
Lua

-- Pinned to the v2 rewrite branch until it replaces v1 on main (2026-11-16,
-- see https://github.com/petertriho/nvim-scrollbar/issues/121). After that,
-- switch to `version = vim.version.range("^2")`.
vim.pack.add({
{ src = "https://github.com/petertriho/nvim-scrollbar", version = "refactor/v2" },
})
require("scrollbar").setup({
exclude = {
filetypes = { ["neo-tree"] = true },
},
-- Search marks are native in v2 (no hlslens dependency like v1).
providers = {
search = true,
gitsigns = true,
},
marks = {
Illuminate = { text = "≡", priority = 8, highlight = "Special" },
Search = { highlight = "DiagnosticVirtualTextInfo" },
Error = { highlight = "DiagnosticFloatingError" },
Warn = { highlight = "DiagnosticFloatingWarn" },
Info = { highlight = "DiagnosticFloatingInfo" },
Hint = { highlight = "DiagnosticFloatingHint" },
GitAdd = { highlight = "GitSignsAdd" },
GitChange = { highlight = "GitSignsChange" },
GitDelete = { highlight = "GitSignsDelete" },
},
scrollbar = {
-- Non-focusable so Ctrl+W w never lands on the float; also disables
-- click/drag navigation on the scrollbar.
mouse = false,
-- v1 had no track; the explicit PmenuSbar handle highlight carried over
-- would make the thumb indistinguishable from the v2 track, which also
-- defaults to PmenuSbar. The v2 defaults (PmenuThumb thumb on a
-- PmenuSbar track) give the same subtle-on-subtle look the v1 override
-- was after.
},
})
-- Show illuminated word matches as scrollbar marks. The illuminate plugin
-- refreshes its references after CursorMoved, so hook the events directly and
-- publish through the provider API. `buffer = "provider"` ownership means the
-- manager dispatches no automatic buffer refreshes; our autocmds own that.
-- illuminate also refreshes its own refs ~100ms after CursorMoved, so re-run
-- the refresh on a small debounce for snappy bars.
local function get_illuminate_marks(bufnr)
local ok, reference = pcall(require, "illuminate.reference")
if not ok then
return {}
end
-- illuminate stores refs as { {0-indexed line, col}, {0-indexed line, col} },
-- sorted. Several refs can share a line, so keep one mark per line.
local illuminate_marks = {}
local last_line = -1
for _, ref in ipairs(reference.buf_get_references(bufnr)) do
local line = ref[1][1]
if line ~= last_line then
last_line = line
illuminate_marks[#illuminate_marks + 1] = {
line = line,
text = "≡",
type = "Illuminate",
}
end
end
return illuminate_marks
end
require("scrollbar.providers").register({
name = "illuminate",
refresh_owner = { buffer = "provider" },
refresh = function(bufnr)
return get_illuminate_marks(bufnr)
end,
setup = function(context)
local function publish(bufnr)
bufnr = (bufnr == nil or bufnr == 0) and vim.api.nvim_get_current_buf() or bufnr
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
if context.is_buffer_eligible(bufnr) then
context.set_marks(bufnr, get_illuminate_marks(bufnr))
else
context.clear_marks(bufnr)
end
end
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorHold", "TextChanged", "BufEnter", "WinEnter" }, {
group = context.create_augroup("illuminate"),
callback = function(args)
publish(args.buf)
if args.event == "CursorMoved" or args.event == "TextChanged" then
vim.defer_fn(function()
publish(args.buf)
end, 250)
end
end,
})
end,
})