feat(#2948): add decorator registry and order

This commit is contained in:
Alexander Courtis 2024-11-24 15:19:05 +11:00
parent 919a0a3333
commit 129c349eee
15 changed files with 152 additions and 94 deletions

View File

@ -417,7 +417,6 @@ Following is the default configuration. See |nvim-tree-opts| for details. >lua
},
},
renderer = {
user_decorators = {},
add_trailing = false,
group_empty = false,
full_name = false,

View File

@ -276,7 +276,6 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
},
},
renderer = {
user_decorators = {},
add_trailing = false,
group_empty = false,
full_name = false,

View File

@ -7,6 +7,7 @@ local events = require("nvim-tree.events")
local help = require("nvim-tree.help")
local keymap = require("nvim-tree.keymap")
local notify = require("nvim-tree.notify")
local decorator_registry = require("nvim-tree.renderer.decorator.registry")
local DirectoryNode = require("nvim-tree.node.directory")
local FileLinkNode = require("nvim-tree.node.file-link")
@ -312,6 +313,10 @@ Api.commands.get = wrap(function()
return require("nvim-tree.commands").get()
end)
-- TODO provide a registration convenience to hide classic
-- TODO add doc
Api.decorator.BaseDecorator = require("nvim-tree.renderer.decorator.user") --[[@as nvim_tree.api.decorator.BaseDecorator ]]
Api.decorator.register = decorator_registry.register
Api.decorator.unregister = decorator_registry.unregister
return Api

View File

@ -1,18 +1,11 @@
local decorator_registry = require("nvim-tree.renderer.decorator.registry")
local notify = require("nvim-tree.notify")
local utils = require("nvim-tree.utils")
local view = require("nvim-tree.view")
local Class = require("nvim-tree.classic")
local DirectoryNode = require("nvim-tree.node.directory")
local DecoratorBookmarks = require("nvim-tree.renderer.decorator.bookmarks")
local DecoratorCopied = require("nvim-tree.renderer.decorator.copied")
local DecoratorCut = require("nvim-tree.renderer.decorator.cut")
local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics")
local DecoratorGit = require("nvim-tree.renderer.decorator.git")
local DecoratorModified = require("nvim-tree.renderer.decorator.modified")
local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden")
local DecoratorOpened = require("nvim-tree.renderer.decorator.opened")
local DecoratorUser = require("nvim-tree.renderer.decorator.user")
local pad = require("nvim-tree.renderer.components.padding")
@ -56,21 +49,17 @@ function Builder:new(args)
self.signs = {}
self.extmarks = {}
self.virtual_lines = {}
self.decorators = {
-- priority order
DecoratorCut(self.explorer),
DecoratorCopied(self.explorer),
DecoratorDiagnostics(self.explorer),
DecoratorBookmarks(self.explorer),
DecoratorModified(self.explorer),
DecoratorHidden(self.explorer),
DecoratorOpened(self.explorer),
DecoratorGit(self.explorer),
}
self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts)
for _, user_decorator in ipairs(args.explorer.opts.renderer.user_decorators) do
table.insert(self.decorators, user_decorator.class())
-- lowest priority is registered first
self.decorators = {}
local decorator_args = { explorer = self.explorer }
for _, d in ipairs(decorator_registry.registered) do
if d:is(DecoratorUser) then
table.insert(self.decorators, 1, d())
else
table.insert(self.decorators, 1, d(decorator_args))
end
end
end

View File

@ -4,23 +4,24 @@ local Decorator = require("nvim-tree.renderer.decorator")
---@field private explorer Explorer
---@field private icon HighlightedString?
local DecoratorBookmarks = Decorator:extend()
DecoratorBookmarks.name = "Bookmarks"
---@class DecoratorBookmarks
---@overload fun(explorer: Explorer): DecoratorBookmarks
---@protected
---@param explorer Explorer
function DecoratorBookmarks:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorBookmarks:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_bookmarks or "none",
icon_placement = self.explorer.opts.renderer.icons.bookmarks_placement or "none",
}
DecoratorBookmarks.super.new(self, args)
DecoratorBookmarks.super.new(self, a)
if self.explorer.opts.renderer.icons.show.bookmarks then
self.icon = {

View File

@ -3,23 +3,24 @@ local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) DecoratorCopied: Decorator
---@field private explorer Explorer
local DecoratorCopied = Decorator:extend()
DecoratorCopied.name = "Copied"
---@class DecoratorCopied
---@overload fun(explorer: Explorer): DecoratorCopied
---@protected
---@param explorer Explorer
function DecoratorCopied:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorCopied:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_clipboard or "none",
icon_placement = "none",
}
DecoratorCopied.super.new(self, args)
DecoratorCopied.super.new(self, a)
end
---Copied highlight: renderer.highlight_clipboard and node is copied

View File

@ -3,23 +3,24 @@ local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) DecoratorCut: Decorator
---@field private explorer Explorer
local DecoratorCut = Decorator:extend()
DecoratorCut.name = "Cut"
---@class DecoratorCut
---@overload fun(explorer: Explorer): DecoratorCut
---@protected
---@param explorer Explorer
function DecoratorCut:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorCut:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_clipboard or "none",
icon_placement = "none",
}
DecoratorCut.super.new(self, args)
DecoratorCut.super.new(self, a)
end
---Cut highlight: renderer.highlight_clipboard and node is cut

View File

@ -34,23 +34,24 @@ local ICON_KEYS = {
---@field private explorer Explorer
---@field private diag_icons HighlightedString[]?
local DecoratorDiagnostics = Decorator:extend()
DecoratorDiagnostics.name = "Diagnostics"
---@class DecoratorDiagnostics
---@overload fun(explorer: Explorer): DecoratorDiagnostics
---@protected
---@param explorer Explorer
function DecoratorDiagnostics:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorDiagnostics:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_diagnostics or "none",
icon_placement = self.explorer.opts.renderer.icons.diagnostics_placement or "none",
}
DecoratorDiagnostics.super.new(self, args)
DecoratorDiagnostics.super.new(self, a)
if not self.enabled then
return

View File

@ -19,23 +19,24 @@ local DirectoryNode = require("nvim-tree.node.directory")
---@field private icons_by_status GitIconsByStatus?
---@field private icons_by_xy GitIconsByXY?
local DecoratorGit = Decorator:extend()
DecoratorGit.name = "Git"
---@class DecoratorGit
---@overload fun(explorer: Explorer): DecoratorGit
---@protected
---@param explorer Explorer
function DecoratorGit:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorGit:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = self.explorer.opts.git.enable,
highlight_range = self.explorer.opts.renderer.highlight_git or "none",
icon_placement = self.explorer.opts.renderer.icons.git_placement or "none",
}
DecoratorGit.super.new(self, args)
DecoratorGit.super.new(self, a)
if not self.enabled then
return

View File

@ -5,23 +5,24 @@ local DirectoryNode = require("nvim-tree.node.directory")
---@field private explorer Explorer
---@field private icon HighlightedString?
local DecoratorHidden = Decorator:extend()
DecoratorHidden.name = "Hidden"
---@class DecoratorHidden
---@overload fun(explorer: Explorer): DecoratorHidden
---@protected
---@param explorer Explorer
function DecoratorHidden:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorHidden:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_hidden or "none",
icon_placement = self.explorer.opts.renderer.icons.hidden_placement or "none",
}
DecoratorHidden.super.new(self, args)
DecoratorHidden.super.new(self, a)
if self.explorer.opts.renderer.icons.show.hidden then
self.icon = {

View File

@ -2,18 +2,22 @@ local Class = require("nvim-tree.classic")
---Abstract Decorator
---@class (exact) Decorator: Class
---@field name string for registry
---@field protected enabled boolean
---@field protected highlight_range DecoratorHighlightRange
---@field protected icon_placement DecoratorIconPlacement
local Decorator = Class:extend()
---@class (exact) DecoratorArgs
---@field explorer Explorer
---
---@class (exact) AbstractDecoratorArgs
---@field enabled boolean
---@field highlight_range DecoratorHighlightRange
---@field icon_placement DecoratorIconPlacement
---@protected
---@param args DecoratorArgs
---@param args AbstractDecoratorArgs
function Decorator:new(args)
if args then
self.enabled = args.enabled

View File

@ -7,23 +7,24 @@ local DirectoryNode = require("nvim-tree.node.directory")
---@field private explorer Explorer
---@field private icon HighlightedString?
local DecoratorModified = Decorator:extend()
DecoratorModified.name = "Modified"
---@class DecoratorModified
---@overload fun(explorer: Explorer): DecoratorModified
---@protected
---@param explorer Explorer
function DecoratorModified:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorModified:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_modified or "none",
icon_placement = self.explorer.opts.renderer.icons.modified_placement or "none",
}
DecoratorModified.super.new(self, args)
DecoratorModified.super.new(self, a)
if not self.enabled then
return

View File

@ -6,23 +6,24 @@ local Decorator = require("nvim-tree.renderer.decorator")
---@field private explorer Explorer
---@field private icon HighlightedString|nil
local DecoratorOpened = Decorator:extend()
DecoratorOpened.name = "Opened"
---@class DecoratorOpened
---@overload fun(explorer: Explorer): DecoratorOpened
---@protected
---@param explorer Explorer
function DecoratorOpened:new(explorer)
self.explorer = explorer
---@param args DecoratorArgs
function DecoratorOpened:new(args)
self.explorer = args.explorer
---@type DecoratorArgs
local args = {
---@type AbstractDecoratorArgs
local a = {
enabled = true,
highlight_range = self.explorer.opts.renderer.highlight_opened_files or "none",
icon_placement = "none",
}
DecoratorOpened.super.new(self, args)
DecoratorOpened.super.new(self, a)
end
---Opened highlight: renderer.highlight_opened_files and node has an open buffer

View File

@ -0,0 +1,71 @@
local notify = require("nvim-tree.notify")
local utils = require("nvim-tree.utils")
local DecoratorBookmarks = require("nvim-tree.renderer.decorator.bookmarks")
local DecoratorCopied = require("nvim-tree.renderer.decorator.copied")
local DecoratorCut = require("nvim-tree.renderer.decorator.cut")
local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics")
local DecoratorGit = require("nvim-tree.renderer.decorator.git")
local DecoratorModified = require("nvim-tree.renderer.decorator.modified")
local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden")
local DecoratorOpened = require("nvim-tree.renderer.decorator.opened")
local DecoratorUser = require("nvim-tree.renderer.decorator.user")
-- Globally registered decorators including user
-- Lowest priority first
---@alias DecoratorName nvim_tree.api.decorator.BaseDecorator | "Cut" | "Copied" | "Diagnostics" | "Bookmarks" | "Modified" | "Hidden" | "Opened" | "Git"
local M = {
---@type Decorator[]
registered = {
DecoratorGit,
DecoratorOpened,
DecoratorHidden,
DecoratorModified,
DecoratorBookmarks,
DecoratorDiagnostics,
DecoratorCopied,
DecoratorCut,
}
}
---@class RegisterOpts
---@field decorator nvim_tree.api.decorator.BaseDecorator
---@field below DecoratorName?
---@param opts RegisterOpts
function M.register(opts)
if not opts or not opts.decorator then
return
end
if vim.tbl_contains(M.registered, opts.decorator) then
notify.error("decorator already registered")
return
end
for i, d in ipairs(M.registered) do
if d:is(DecoratorUser) and d == opts.below or d.name == opts.below then
table.insert(M.registered, i, opts.decorator)
return
end
end
-- default to highest at the top
table.insert(M.registered, opts.decorator)
end
---@class UnRegisterOpts
---@field decorator nvim_tree.api.decorator.BaseDecorator
---@param opts UnRegisterOpts
function M.unregister(opts)
if not opts or not opts.decorator then
return
end
utils.array_remove(M.registered, opts.decorator)
end
return M

View File

@ -1,24 +1,7 @@
local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) UserDecorator: Decorator
local UserDecorator = Decorator:extend()
---Exposed as nvim_tree.api.decorator.BaseDecorator
---@class (exact) DecoratorUser: Decorator
local DecoratorUser = Decorator:extend()
---@param node nvim_tree.api.Node
---@return HighlightedString? icon_node
function UserDecorator:icon_node(node)
return self:nop(node)
end
---@param node nvim_tree.api.Node
---@return HighlightedString[]? icons
function UserDecorator:icons(node)
self:nop(node)
end
---@param node nvim_tree.api.Node
---@return string? highlight_group
function UserDecorator:highlight_group(node)
self:nop(node)
end
return UserDecorator
return DecoratorUser