mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 18:58:12 +00:00
feat(dim): added dim plugin
This commit is contained in:
parent
2c4021c466
commit
4dda5516e8
1 changed files with 141 additions and 0 deletions
141
lua/snacks/dim.lua
Normal file
141
lua/snacks/dim.lua
Normal file
|
@ -0,0 +1,141 @@
|
|||
---@class snacks.dim
|
||||
---@overload fun(opts: snacks.dim.Config)
|
||||
local M = setmetatable({}, {
|
||||
__call = function(M, ...)
|
||||
return M.enable(...)
|
||||
end,
|
||||
})
|
||||
|
||||
---@class snacks.dim.Config
|
||||
local defaults = {
|
||||
---@type snacks.scope.Config
|
||||
scope = {
|
||||
min_size = 5,
|
||||
max_size = 20,
|
||||
siblings = true,
|
||||
},
|
||||
-- animate scopes. Enabled by default for Neovim >= 0.10
|
||||
-- Works on older versions but has to trigger redraws during animation.
|
||||
---@type snacks.animate.Config|{enabled?: boolean}
|
||||
animate = {
|
||||
enabled = vim.fn.has("nvim-0.10") == 1,
|
||||
easing = "outQuad",
|
||||
duration = {
|
||||
step = 20, -- ms per step
|
||||
total = 300, -- maximum duration
|
||||
},
|
||||
},
|
||||
enabled = function(buf)
|
||||
return vim.g.snacks_dim ~= false and vim.b[buf].snacks_dim ~= false and vim.bo[buf].buftype == ""
|
||||
end,
|
||||
}
|
||||
|
||||
M.enabled = false
|
||||
local ns = vim.api.nvim_create_namespace("snacks_dim")
|
||||
local scopes ---@type snacks.scope.Listener?
|
||||
local scopes_anim = {} ---@type table<number, {from:number, to:number, buf:number}>
|
||||
|
||||
Snacks.util.set_hl({
|
||||
[""] = "DiagnosticUnnecessary",
|
||||
}, { prefix = "SnacksDim", default = true })
|
||||
|
||||
--- Called during every redraw cycle, so it should be fast.
|
||||
--- Everything that can be cached should be cached.
|
||||
---@param win number
|
||||
---@param buf number
|
||||
---@param top number -- 1-indexed
|
||||
---@param bottom number -- 1-indexed
|
||||
function M.on_win(win, buf, top, bottom)
|
||||
local scope = scopes and scopes:get(win)
|
||||
if not scope then
|
||||
return
|
||||
end
|
||||
local function add(l)
|
||||
vim.api.nvim_buf_set_extmark(buf, ns, l - 1, 0, {
|
||||
end_row = l,
|
||||
end_col = 0,
|
||||
hl_group = "SnacksDim",
|
||||
ephemeral = true,
|
||||
})
|
||||
end
|
||||
local from = M.animating and scopes_anim[win] and scopes_anim[win].from or scope.from
|
||||
local to = M.animating and scopes_anim[win] and scopes_anim[win].to or scope.to
|
||||
for l = top, math.min(from - 1, bottom) do
|
||||
add(l)
|
||||
end
|
||||
for l = math.max(to + 1, top), bottom do
|
||||
add(l)
|
||||
end
|
||||
end
|
||||
|
||||
---@param opts? snacks.dim.Config
|
||||
function M.enable(opts)
|
||||
if M.enabled then
|
||||
return
|
||||
end
|
||||
opts = Snacks.config.get("dim", defaults, opts)
|
||||
|
||||
M.enabled = true
|
||||
|
||||
if opts.animate then
|
||||
M.animating = true
|
||||
end
|
||||
|
||||
-- setup decoration provider
|
||||
vim.api.nvim_set_decoration_provider(ns, {
|
||||
on_win = function(_, win, buf, top, bottom)
|
||||
if M.enabled and opts.enabled(buf) then
|
||||
M.on_win(win, buf, top + 1, bottom + 1)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
scopes = scopes
|
||||
or Snacks.scope.attach(function(win, buf, scope, prev)
|
||||
if not M.animating then
|
||||
Snacks.util.redraw(win)
|
||||
else
|
||||
if not (scopes_anim[win] and scopes_anim[win].buf == buf) then
|
||||
local info = vim.fn.getwininfo(win)[1]
|
||||
scopes_anim[win] = {
|
||||
from = info.topline,
|
||||
to = info.botline,
|
||||
buf = buf,
|
||||
}
|
||||
end
|
||||
|
||||
Snacks.animate.animate(scopes_anim[win].from, scope.from, function(v)
|
||||
scopes_anim[win].from = v
|
||||
Snacks.util.redraw(win)
|
||||
end, vim.tbl_extend("keep", { int = true, id = "snacks_dim_from_" .. win }, opts.animate))
|
||||
|
||||
Snacks.animate.animate(scopes_anim[win].to, scope.to, function(v)
|
||||
scopes_anim[win].to = v
|
||||
Snacks.util.redraw(win)
|
||||
end, vim.tbl_extend("keep", { int = true, id = "snacks_dim_to_" .. win }, opts.animate))
|
||||
end
|
||||
end, opts.scope)
|
||||
if not scopes.enabled then
|
||||
scopes:enable()
|
||||
end
|
||||
end
|
||||
|
||||
-- Disable dimming
|
||||
function M.disable()
|
||||
if not M.enabled then
|
||||
return
|
||||
end
|
||||
M.enabled = false
|
||||
if scopes and scopes.enabled then
|
||||
scopes:disable()
|
||||
end
|
||||
scopes_anim = {}
|
||||
vim.cmd([[redraw!]])
|
||||
end
|
||||
|
||||
-- Animate scope changes
|
||||
function M.animate()
|
||||
M.animating = not M.animating
|
||||
end
|
||||
|
||||
return M
|
Loading…
Add table
Add a link
Reference in a new issue