Skip to content

Commit

Permalink
feat(#2948): pass api nodes to user decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-courtis committed Nov 25, 2024
1 parent 3ab3980 commit 6148f69
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 29 deletions.
4 changes: 3 additions & 1 deletion lua/nvim-tree/_meta/api_decorator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ local nvim_tree = { api = { decorator = { AbstractDecorator = {} } } }
---Constructor must call:
--- :init
--- :define_sign when using "signcolumn" range
---Decorator must be registered via api.decorator.register

---Highlight group range as per nvim-tree.renderer.highlight_*
---@alias nvim_tree.api.decorator.HighlightRange "none" | "icon" | "name" | "all"
Expand Down Expand Up @@ -125,4 +126,5 @@ function MyDecorator:highlight_group(node)
end
end

return MyDecorator
---Register the decorator, below Cut in priority
require("nvim-tree.api").decorator.register({ decorator = MyDecorator, below = "Cut" })
5 changes: 3 additions & 2 deletions lua/nvim-tree/node/directory-link.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ function DirectoryLinkNode:highlighted_name()
end

---Create a sanitized partial copy of a node, populating children recursively.
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
---@return nvim_tree.api.DirectoryLinkNode cloned
function DirectoryLinkNode:clone()
local clone = DirectoryNode.clone(self) --[[@as nvim_tree.api.DirectoryLinkNode]]
function DirectoryLinkNode:clone(api_nodes)
local clone = DirectoryNode.clone(self, api_nodes) --[[@as nvim_tree.api.DirectoryLinkNode]]

clone.link_to = self.link_to
clone.fs_stat_target = self.fs_stat_target
Expand Down
7 changes: 4 additions & 3 deletions lua/nvim-tree/node/directory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,18 @@ function DirectoryNode:highlighted_name()
end

---Create a sanitized partial copy of a node, populating children recursively.
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
---@return nvim_tree.api.DirectoryNode cloned
function DirectoryNode:clone()
local clone = Node.clone(self) --[[@as nvim_tree.api.DirectoryNode]]
function DirectoryNode:clone(api_nodes)
local clone = Node.clone(self, api_nodes) --[[@as nvim_tree.api.DirectoryNode]]

clone.has_children = self.has_children
clone.nodes = {}
clone.open = self.open

local clone_child
for _, child in ipairs(self.nodes) do
clone_child = child:clone()
clone_child = child:clone(api_nodes)
clone_child.parent = clone
table.insert(clone.nodes, clone_child)
end
Expand Down
5 changes: 3 additions & 2 deletions lua/nvim-tree/node/file-link.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ function FileLinkNode:highlighted_name()
end

---Create a sanitized partial copy of a node
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
---@return nvim_tree.api.FileLinkNode cloned
function FileLinkNode:clone()
local clone = FileNode.clone(self) --[[@as nvim_tree.api.FileLinkNode]]
function FileLinkNode:clone(api_nodes)
local clone = FileNode.clone(self, api_nodes) --[[@as nvim_tree.api.FileLinkNode]]

clone.link_to = self.link_to
clone.fs_stat_target = self.fs_stat_target
Expand Down
5 changes: 3 additions & 2 deletions lua/nvim-tree/node/file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,10 @@ function FileNode:highlighted_name()
end

---Create a sanitized partial copy of a node
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
---@return nvim_tree.api.FileNode cloned
function FileNode:clone()
local clone = Node.clone(self) --[[@as nvim_tree.api.FileNode]]
function FileNode:clone(api_nodes)
local clone = Node.clone(self, api_nodes) --[[@as nvim_tree.api.FileNode]]

clone.extension = self.extension

Expand Down
7 changes: 6 additions & 1 deletion lua/nvim-tree/node/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ function Node:highlighted_name()
end

---Create a sanitized partial copy of a node, populating children recursively.
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
---@return nvim_tree.api.Node cloned
function Node:clone()
function Node:clone(api_nodes)
---@type nvim_tree.api.Node
local clone = {
uid_node = self.uid_node,
Expand All @@ -137,6 +138,10 @@ function Node:clone()
diag_severity = self.diag_status and self.diag_status.value or nil,
}

if api_nodes then
api_nodes[self.uid_node] = clone
end

return clone
end

Expand Down
5 changes: 3 additions & 2 deletions lua/nvim-tree/node/root.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ function RootNode:destroy()
end

---Create a sanitized partial copy of a node, populating children recursively.
---@param api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node to populate
---@return nvim_tree.api.RootNode cloned
function RootNode:clone()
local clone = DirectoryNode.clone(self) --[[@as nvim_tree.api.RootNode]]
function RootNode:clone(api_nodes)
local clone = DirectoryNode.clone(self, api_nodes) --[[@as nvim_tree.api.RootNode]]

return clone
end
Expand Down
51 changes: 35 additions & 16 deletions lua/nvim-tree/renderer/builder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ local pad = require("nvim-tree.renderer.components.padding")
---@field private markers boolean[] indent markers
---@field private decorators Decorator[]
---@field private hidden_display fun(node: Node): string|nil
---@field private api_nodes table<number, nvim_tree.api.Node>? optional map of uids to api node for user decorators
local Builder = Class:extend()

---@class Builder
Expand All @@ -51,20 +52,33 @@ function Builder:new(args)
self.virtual_lines = {}
self.decorators = {}
self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts)
self.api_nodes = nil

---@type DecoratorArgs
local decorator_args = { explorer = self.explorer }

-- lowest priority is registered first
-- instantiate all the decorators
for _, d in ipairs(decorator_registry.registered) do
if d:is(DecoratorUser) then
table.insert(self.decorators, 1, d())
self:build_api_nodes()
table.insert(self.decorators, d())
else
table.insert(self.decorators, 1, d(decorator_args))
table.insert(self.decorators, d(decorator_args))
end
end
end

---Create and populate api_nodes if not present
---@private
function Builder:build_api_nodes()
if self.api_nodes then
return
end

self.api_nodes = {}
self.explorer:clone(self.api_nodes)
end

---Insert ranged highlight groups into self.highlights
---@private
---@param groups string[]
Expand Down Expand Up @@ -122,22 +136,25 @@ function Builder:format_line(indent_markers, arrows, icon, name, node)
end
end

-- use the api node for user decorators
local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]]

local line = { indent_markers, arrows }
add_to_end(line, { icon })

for i = #self.decorators, 1, -1 do
add_to_end(line, self.decorators[i]:icons_before(node))
for _, d in ipairs(self.decorators) do
add_to_end(line, d:icons_before(d:is(DecoratorUser) and api_node or node))
end

add_to_end(line, { name })

for i = #self.decorators, 1, -1 do
add_to_end(line, self.decorators[i]:icons_after(node))
for _, d in ipairs(self.decorators) do
add_to_end(line, d:icons_after(d:is(DecoratorUser) and api_node or node))
end

local rights = {}
for i = #self.decorators, 1, -1 do
add_to_end(rights, self.decorators[i]:icons_right_align(node))
for _, d in ipairs(self.decorators) do
add_to_end(rights, d:icons_right_align(d:is(DecoratorUser) and api_node or node))
end
if #rights > 0 then
self.extmarks[self.index] = rights
Expand All @@ -149,10 +166,14 @@ end
---@private
---@param node Node
function Builder:build_signs(node)
-- use the api node for user decorators
local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]]

-- first in priority order
local sign_name
for _, d in ipairs(self.decorators) do
sign_name = d:sign_name(node)
local d, sign_name
for i = #self.decorators, 1, -1 do
d = self.decorators[i]
sign_name = d:sign_name(d:is(DecoratorUser) and api_node or node)
if sign_name then
self.signs[self.index] = sign_name
break
Expand Down Expand Up @@ -203,10 +224,8 @@ function Builder:icon_name_decorated(node)
-- calculate node icon and all decorated highlight groups
local icon_groups = {}
local name_groups = {}
local decorator, hl_icon, hl_name
for i = #self.decorators, 1, -1 do
decorator = self.decorators[i]

local hl_icon, hl_name
for _, decorator in ipairs(self.decorators) do
-- maybe overridde icon
icon = decorator:icon_node(node) or icon

Expand Down

0 comments on commit 6148f69

Please sign in to comment.