chore: migrate to classic (#2991)

* add classic, migrating nodes classes

* add mixins to classic

* typechecked optargs constructors for nodes

* typechecked optargs constructors for watcher and event

* luacheck

* typechecked optargs constructors for GitRunner

* typechecked optargs constructors for Sorter

* typechecked optargs constructors for decorators, WIP

* typechecked optargs constructors for decorators, WIP

* typechecked optargs constructors for decorators

* remove class

* replace enums with named maps

* Renderer and Builder use classic, tidy opts

* LiveFilter uses classic, tidy opts

* Filter uses classic, tidy opts

* add FilterTypes named map

* move toggles into filters

* Marks uses classic, tidy opts

* Sorter uses classic, tidy opts

* Clipboard uses classic, tidy opts

* use supers for node methods

* HighlightDisplay uses classic

* protected :new

* Watcher tidy

* Revert "use supers for node methods"

This reverts commit 9fc7a866ec.

* Watcher tidy

* format

* format

* Filters private methods

* format

* Sorter type safety

* Sorter type safety

* Sorter type safety

* Sorter type safety

* Sorter type safety

* Sorter type safety

* tidy Runner

* tidy hi-test name
This commit is contained in:
Alexander Courtis
2024-11-09 14:14:04 +11:00
committed by GitHub
parent 610a1c189b
commit 3fc8de198c
42 changed files with 995 additions and 1115 deletions

View File

@@ -2,6 +2,7 @@ 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")
@@ -26,57 +27,51 @@ local pad = require("nvim-tree.renderer.components.padding")
---@field col_end number
---@class (exact) Builder
---@field private __index? table
---@field lines string[] includes icons etc.
---@field hl_args AddHighlightArgs[] line highlights
---@field signs string[] line signs
---@field extmarks table[] extra marks for right icon placement
---@field virtual_lines table[] virtual lines for hidden count display
---@field private explorer Explorer
---@field private opts table
---@field private index number
---@field private depth number
---@field private combined_groups table<string, boolean> combined group names
---@field private markers boolean[] indent markers
---@field private decorators Decorator[]
---@field private hidden_display fun(node: Node): string|nil
local Builder = {}
local Builder = Class:extend()
---@param opts table user options
---@param explorer Explorer
---@return Builder
function Builder:new(opts, explorer)
---@type Builder
local o = {
opts = opts,
explorer = explorer,
index = 0,
depth = 0,
hl_args = {},
combined_groups = {},
lines = {},
markers = {},
signs = {},
extmarks = {},
virtual_lines = {},
decorators = {
-- priority order
DecoratorCut:create(opts, explorer),
DecoratorCopied:create(opts, explorer),
DecoratorDiagnostics:create(opts, explorer),
DecoratorBookmarks:create(opts, explorer),
DecoratorModified:create(opts, explorer),
DecoratorHidden:create(opts, explorer),
DecoratorOpened:create(opts, explorer),
DecoratorGit:create(opts, explorer),
},
hidden_display = Builder:setup_hidden_display_function(opts),
---@class Builder
---@overload fun(args: BuilderArgs): Builder
---@class (exact) BuilderArgs
---@field explorer Explorer
---@protected
---@param args BuilderArgs
function Builder:new(args)
self.explorer = args.explorer
self.index = 0
self.depth = 0
self.hl_args = {}
self.combined_groups = {}
self.lines = {}
self.markers = {}
self.signs = {}
self.extmarks = {}
self.virtual_lines = {}
self.decorators = {
-- priority order
DecoratorCut({ explorer = args.explorer }),
DecoratorCopied({ explorer = args.explorer }),
DecoratorDiagnostics({ explorer = args.explorer }),
DecoratorBookmarks({ explorer = args.explorer }),
DecoratorModified({ explorer = args.explorer }),
DecoratorHidden({ explorer = args.explorer }),
DecoratorOpened({ explorer = args.explorer }),
DecoratorGit({ explorer = args.explorer })
}
setmetatable(o, self)
self.__index = self
return o
self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts)
end
---Insert ranged highlight groups into self.highlights
@@ -123,7 +118,7 @@ function Builder:format_line(indent_markers, arrows, icon, name, node)
end
for _, v in ipairs(t2) do
if added_len > 0 then
table.insert(t1, { str = self.opts.renderer.icons.padding })
table.insert(t1, { str = self.explorer.opts.renderer.icons.padding })
end
table.insert(t1, v)
end
@@ -284,7 +279,7 @@ function Builder:add_hidden_count_string(node, idx, num_children)
local hidden_count_string = self.hidden_display(node.hidden_stats)
if hidden_count_string and hidden_count_string ~= "" then
local indent_markers = pad.get_indent_markers(self.depth, idx or 0, num_children or 0, node, self.markers, 1)
local indent_width = self.opts.renderer.indent_width
local indent_width = self.explorer.opts.renderer.indent_width
local indent_padding = string.rep(" ", indent_width)
local indent_string = indent_padding .. indent_markers.str
@@ -354,16 +349,16 @@ end
---@private
function Builder:build_header()
if view.is_root_folder_visible(self.explorer.absolute_path) then
local root_name = self:format_root_name(self.opts.renderer.root_folder_label)
local root_name = self:format_root_name(self.explorer.opts.renderer.root_folder_label)
table.insert(self.lines, root_name)
self:insert_highlight({ "NvimTreeRootFolder" }, 0, string.len(root_name))
self.index = 1
end
if self.explorer.live_filter.filter then
local filter_line = string.format("%s/%s/", self.opts.live_filter.prefix, self.explorer.live_filter.filter)
local filter_line = string.format("%s/%s/", self.explorer.opts.live_filter.prefix, self.explorer.live_filter.filter)
table.insert(self.lines, filter_line)
local prefix_length = string.len(self.opts.live_filter.prefix)
local prefix_length = string.len(self.explorer.opts.live_filter.prefix)
self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length)
self:insert_highlight({ "NvimTreeLiveFilterValue" }, prefix_length, string.len(filter_line))
self.index = self.index + 1
@@ -413,11 +408,11 @@ function Builder:setup_hidden_display_function(opts)
-- In case of missing field such as live_filter we zero it, otherwise keep field as is
hidden_stats = vim.tbl_deep_extend("force", {
live_filter = 0,
git = 0,
buf = 0,
dotfile = 0,
custom = 0,
bookmark = 0,
git = 0,
buf = 0,
dotfile = 0,
custom = 0,
bookmark = 0,
}, hidden_stats or {})
local ok, result = pcall(hidden_display, hidden_stats)

View File

@@ -1,95 +0,0 @@
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local diagnostics = require("nvim-tree.diagnostics")
local DirectoryNode = require("nvim-tree.node.directory")
local M = {
-- highlight strings for the icons
HS_ICON = {},
-- highlight groups for HL
HG_FILE = {},
HG_FOLDER = {},
-- position for HL
HL_POS = HL_POSITION.none,
}
---Diagnostics highlight group and position when highlight_diagnostics.
---@param node Node
---@return HL_POSITION position none when no status
---@return string|nil group only when status
function M.get_highlight(node)
if not node or M.HL_POS == HL_POSITION.none then
return HL_POSITION.none, nil
end
local group
local diag_status = diagnostics.get_diag_status(node)
if node:is(DirectoryNode) then
group = M.HS_FOLDER[diag_status and diag_status.value]
else
group = M.HS_FILE[diag_status and diag_status.value]
end
if group then
return M.HL_POS, group
else
return HL_POSITION.none, nil
end
end
---diagnostics icon if there is a status
---@param node Node
---@return HighlightedString|nil modified icon
function M.get_icon(node)
if node and M.config.diagnostics.enable and M.config.renderer.icons.show.diagnostics then
local diag_status = diagnostics.get_diag_status(node)
return M.ICON[diag_status and diag_status.value]
end
end
function M.setup(opts)
M.config = {
diagnostics = opts.diagnostics,
renderer = opts.renderer,
}
if opts.diagnostics.enable and opts.renderer.highlight_diagnostics then
M.HL_POS = HL_POSITION[opts.renderer.highlight_diagnostics]
end
M.HG_FILE[vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFileHL"
M.HG_FILE[vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFileHL"
M.HG_FILE[vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFileHL"
M.HG_FILE[vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFileHL"
M.HG_FOLDER[vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFolderHL"
M.HG_FOLDER[vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFolderHL"
M.HG_FOLDER[vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFolderHL"
M.HG_FOLDER[vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFolderHL"
M.HS_ICON[vim.diagnostic.severity.ERROR] = {
str = M.config.diagnostics.icons.error,
hl = { "NvimTreeDiagnosticErrorIcon" },
}
M.HS_ICON[vim.diagnostic.severity.WARN] = {
str = M.config.diagnostics.icons.warning,
hl = { "NvimTreeDiagnosticWarningIcon" },
}
M.HS_ICON[vim.diagnostic.severity.INFO] = {
str = M.config.diagnostics.icons.info,
hl = { "NvimTreeDiagnosticInfoIcon" },
}
M.HS_ICON[vim.diagnostic.severity.HINT] = {
str = M.config.diagnostics.icons.hint,
hl = { "NvimTreeDiagnosticHintIcon" },
}
for _, i in ipairs(M.HS_ICON) do
vim.fn.sign_define(i.hl[1], { text = i.str, texthl = i.hl[1] })
end
end
return M

View File

@@ -57,13 +57,13 @@ local function show()
end
M.popup_win = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, false), false, {
relative = "win",
row = 0,
bufpos = { vim.api.nvim_win_get_cursor(0)[1] - 1, 0 },
width = math.min(text_width, vim.o.columns - 2),
height = 1,
relative = "win",
row = 0,
bufpos = { vim.api.nvim_win_get_cursor(0)[1] - 1, 0 },
width = math.min(text_width, vim.o.columns - 2),
height = 1,
noautocmd = true,
style = "minimal",
style = "minimal",
})
local ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"]

View File

@@ -1,12 +1,10 @@
local M = {}
M.diagnostics = require("nvim-tree.renderer.components.diagnostics")
M.full_name = require("nvim-tree.renderer.components.full-name")
M.devicons = require("nvim-tree.renderer.components.devicons")
M.padding = require("nvim-tree.renderer.components.padding")
function M.setup(opts)
M.diagnostics.setup(opts)
M.full_name.setup(opts)
M.devicons.setup(opts)
M.padding.setup(opts)

View File

@@ -1,35 +1,29 @@
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) DecoratorBookmarks: Decorator
---@field icon HighlightedString?
local DecoratorBookmarks = Decorator:new()
local DecoratorBookmarks = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorBookmarks
function DecoratorBookmarks:create(opts, explorer)
---@type DecoratorBookmarks
local o = {
explorer = explorer,
enabled = true,
hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT[opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorBookmarks
---@overload fun(explorer: DecoratorArgs): DecoratorBookmarks
if opts.renderer.icons.show.bookmarks then
o.icon = {
str = opts.renderer.icons.glyphs.bookmark,
---@protected
---@param args DecoratorArgs
function DecoratorBookmarks:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_bookmarks or "none",
icon_placement = args.explorer.opts.renderer.icons.bookmarks_placement or "none",
})
if self.explorer.opts.renderer.icons.show.bookmarks then
self.icon = {
str = self.explorer.opts.renderer.icons.glyphs.bookmark,
hl = { "NvimTreeBookmarkIcon" },
}
o:define_sign(o.icon)
self:define_sign(self.icon)
end
return o
end
---Bookmark icon: renderer.icons.show.bookmarks and node is marked
@@ -45,7 +39,7 @@ end
---@param node Node
---@return string|nil group
function DecoratorBookmarks:calculate_highlight(node)
if self.hl_pos ~= HL_POSITION.none and self.explorer.marks:get(node) then
if self.range ~= "none" and self.explorer.marks:get(node) then
return "NvimTreeBookmarkHL"
end
end

View File

@@ -1,34 +1,27 @@
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) DecoratorCopied: Decorator
---@field icon HighlightedString?
local DecoratorCopied = Decorator:new()
local DecoratorCopied = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorCopied
function DecoratorCopied:create(opts, explorer)
---@type DecoratorCopied
local o = {
explorer = explorer,
enabled = true,
hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorCopied
---@overload fun(explorer: DecoratorArgs): DecoratorCopied
return o
---@protected
---@param args DecoratorArgs
function DecoratorCopied:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_clipboard or "none",
icon_placement = "none",
})
end
---Copied highlight: renderer.highlight_clipboard and node is copied
---@param node Node
---@return string|nil group
function DecoratorCopied:calculate_highlight(node)
if self.hl_pos ~= HL_POSITION.none and self.explorer.clipboard:is_copied(node) then
if self.range ~= "none" and self.explorer.clipboard:is_copied(node) then
return "NvimTreeCopiedHL"
end
end

View File

@@ -1,33 +1,27 @@
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) DecoratorCut: Decorator
local DecoratorCut = Decorator:new()
local DecoratorCut = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorCut
function DecoratorCut:create(opts, explorer)
---@type DecoratorCut
local o = {
explorer = explorer,
enabled = true,
hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorCut
---@overload fun(explorer: DecoratorArgs): DecoratorCut
return o
---@protected
---@param args DecoratorArgs
function DecoratorCut:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_clipboard or "none",
icon_placement = "none",
})
end
---Cut highlight: renderer.highlight_clipboard and node is cut
---@param node Node
---@return string|nil group
function DecoratorCut:calculate_highlight(node)
if self.hl_pos ~= HL_POSITION.none and self.explorer.clipboard:is_cut(node) then
if self.range ~= "none" and self.explorer.clipboard:is_cut(node) then
return "NvimTreeCutHL"
end
end

View File

@@ -1,8 +1,5 @@
local diagnostics = require("nvim-tree.diagnostics")
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
local DirectoryNode = require("nvim-tree.node.directory")
@@ -35,38 +32,35 @@ local ICON_KEYS = {
---@class (exact) DecoratorDiagnostics: Decorator
---@field icons HighlightedString[]?
local DecoratorDiagnostics = Decorator:new()
local DecoratorDiagnostics = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorDiagnostics
function DecoratorDiagnostics:create(opts, explorer)
---@type DecoratorDiagnostics
local o = {
explorer = explorer,
enabled = opts.diagnostics.enable,
hl_pos = HL_POSITION[opts.renderer.highlight_diagnostics] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT[opts.renderer.icons.diagnostics_placement] or ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorDiagnostics
---@overload fun(explorer: DecoratorArgs): DecoratorDiagnostics
if not o.enabled then
return o
---@protected
---@param args DecoratorArgs
function DecoratorDiagnostics:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_diagnostics or "none",
icon_placement = args.explorer.opts.renderer.icons.diagnostics_placement or "none",
})
if not self.enabled then
return
end
if opts.renderer.icons.show.diagnostics then
o.icons = {}
if self.explorer.opts.renderer.icons.show.diagnostics then
self.icons = {}
for name, sev in pairs(ICON_KEYS) do
o.icons[sev] = {
str = opts.diagnostics.icons[name],
self.icons[sev] = {
str = self.explorer.opts.diagnostics.icons[name],
hl = { HG_ICON[sev] },
}
o:define_sign(o.icons[sev])
self:define_sign(self.icons[sev])
end
end
return o
end
---Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status
@@ -87,7 +81,7 @@ end
---@param node Node
---@return string|nil group
function DecoratorDiagnostics:calculate_highlight(node)
if not node or not self.enabled or self.hl_pos == HL_POSITION.none then
if not node or not self.enabled or self.range == "none" then
return nil
end

View File

@@ -1,8 +1,5 @@
local notify = require("nvim-tree.notify")
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
local DirectoryNode = require("nvim-tree.node.directory")
@@ -20,52 +17,49 @@ local DirectoryNode = require("nvim-tree.node.directory")
---@field folder_hl_by_xy table<GitXY, string>?
---@field icons_by_status GitIconsByStatus?
---@field icons_by_xy GitIconsByXY?
local DecoratorGit = Decorator:new()
local DecoratorGit = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorGit
function DecoratorGit:create(opts, explorer)
---@type DecoratorGit
local o = {
explorer = explorer,
enabled = opts.git.enable,
hl_pos = HL_POSITION[opts.renderer.highlight_git] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT[opts.renderer.icons.git_placement] or ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorGit
---@overload fun(explorer: DecoratorArgs): DecoratorGit
if not o.enabled then
return o
---@protected
---@param args DecoratorArgs
function DecoratorGit:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = args.explorer.opts.git.enable,
hl_pos = args.explorer.opts.renderer.highlight_git or "none",
icon_placement = args.explorer.opts.renderer.icons.git_placement or "none",
})
if not self.enabled then
return
end
if o.hl_pos ~= HL_POSITION.none then
o:build_file_folder_hl_by_xy()
if self.range ~= "none" then
self:build_file_folder_hl_by_xy()
end
if opts.renderer.icons.show.git then
o:build_icons_by_status(opts.renderer.icons.glyphs.git)
o:build_icons_by_xy(o.icons_by_status)
if self.explorer.opts.renderer.icons.show.git then
self:build_icons_by_status(self.explorer.opts.renderer.icons.glyphs.git)
self:build_icons_by_xy(self.icons_by_status)
for _, icon in pairs(o.icons_by_status) do
for _, icon in pairs(self.icons_by_status) do
self:define_sign(icon)
end
end
return o
end
---@param glyphs GitGlyphsByStatus
function DecoratorGit:build_icons_by_status(glyphs)
self.icons_by_status = {}
self.icons_by_status.staged = { str = glyphs.staged, hl = { "NvimTreeGitStagedIcon" }, ord = 1 }
self.icons_by_status.unstaged = { str = glyphs.unstaged, hl = { "NvimTreeGitDirtyIcon" }, ord = 2 }
self.icons_by_status.renamed = { str = glyphs.renamed, hl = { "NvimTreeGitRenamedIcon" }, ord = 3 }
self.icons_by_status.deleted = { str = glyphs.deleted, hl = { "NvimTreeGitDeletedIcon" }, ord = 4 }
self.icons_by_status.unmerged = { str = glyphs.unmerged, hl = { "NvimTreeGitMergeIcon" }, ord = 5 }
self.icons_by_status = {}
self.icons_by_status.staged = { str = glyphs.staged, hl = { "NvimTreeGitStagedIcon" }, ord = 1 }
self.icons_by_status.unstaged = { str = glyphs.unstaged, hl = { "NvimTreeGitDirtyIcon" }, ord = 2 }
self.icons_by_status.renamed = { str = glyphs.renamed, hl = { "NvimTreeGitRenamedIcon" }, ord = 3 }
self.icons_by_status.deleted = { str = glyphs.deleted, hl = { "NvimTreeGitDeletedIcon" }, ord = 4 }
self.icons_by_status.unmerged = { str = glyphs.unmerged, hl = { "NvimTreeGitMergeIcon" }, ord = 5 }
self.icons_by_status.untracked = { str = glyphs.untracked, hl = { "NvimTreeGitNewIcon" }, ord = 6 }
self.icons_by_status.ignored = { str = glyphs.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }
self.icons_by_status.ignored = { str = glyphs.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }
end
---@param icons GitIconsByXY
@@ -102,7 +96,7 @@ function DecoratorGit:build_icons_by_xy(icons)
["DD"] = { icons.deleted },
["DU"] = { icons.deleted, icons.unmerged },
["!!"] = { icons.ignored },
dirty = { icons.unstaged },
dirty = { icons.unstaged },
}
end
@@ -121,7 +115,7 @@ function DecoratorGit:build_file_folder_hl_by_xy()
[" T"] = "NvimTreeGitFileDirtyHL",
["MM"] = "NvimTreeGitFileDirtyHL",
["AM"] = "NvimTreeGitFileDirtyHL",
dirty = "NvimTreeGitFileDirtyHL",
dirty = "NvimTreeGitFileDirtyHL",
["A "] = "NvimTreeGitFileStagedHL",
["??"] = "NvimTreeGitFileNewHL",
["AU"] = "NvimTreeGitFileMergeHL",
@@ -165,7 +159,7 @@ function DecoratorGit:calculate_icons(node)
for _, s in pairs(git_xy) do
local icons = self.icons_by_xy[s]
if not icons then
if self.hl_pos == HL_POSITION.none then
if self.range == "none" then
notify.warn(string.format("Unrecognized git state '%s'", git_xy))
end
return nil
@@ -197,7 +191,7 @@ end
---@param node Node
---@return string|nil name
function DecoratorGit:sign_name(node)
if self.icon_placement ~= ICON_PLACEMENT.signcolumn then
if self.icon_placement ~= "signcolumn" then
return
end
@@ -211,7 +205,7 @@ end
---@param node Node
---@return string|nil group
function DecoratorGit:calculate_highlight(node)
if not node or not self.enabled or self.hl_pos == HL_POSITION.none then
if not node or not self.enabled or self.range == "none" then
return nil
end

View File

@@ -1,36 +1,30 @@
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
local DirectoryNode = require("nvim-tree.node.directory")
---@class (exact) DecoratorHidden: Decorator
---@field icon HighlightedString?
local DecoratorHidden = Decorator:new()
local DecoratorHidden = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorHidden
function DecoratorHidden:create(opts, explorer)
---@type DecoratorHidden
local o = {
explorer = explorer,
enabled = true,
hl_pos = HL_POSITION[opts.renderer.highlight_hidden] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT[opts.renderer.icons.hidden_placement] or ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorHidden
---@overload fun(explorer: DecoratorArgs): DecoratorHidden
if opts.renderer.icons.show.hidden then
o.icon = {
str = opts.renderer.icons.glyphs.hidden,
---@protected
---@param args DecoratorArgs
function DecoratorHidden:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_hidden or "none",
icon_placement = args.explorer.opts.renderer.icons.hidden_placement or "none",
})
if self.explorer.opts.renderer.icons.show.hidden then
self.icon = {
str = self.explorer.opts.renderer.icons.glyphs.hidden,
hl = { "NvimTreeHiddenIcon" },
}
o:define_sign(o.icon)
self:define_sign(self.icon)
end
return o
end
---Hidden icon: renderer.icons.show.hidden and node starts with `.` (dotfile).
@@ -46,7 +40,7 @@ end
---@param node Node
---@return string|nil group
function DecoratorHidden:calculate_highlight(node)
if not self.enabled or self.hl_pos == HL_POSITION.none or not node:is_dotfile() then
if not self.enabled or self.range == "none" or not node:is_dotfile() then
return nil
end

View File

@@ -1,16 +1,33 @@
local Class = require("nvim-tree.class")
local Class = require("nvim-tree.classic")
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
---@alias DecoratorRange "none" | "icon" | "name" | "all"
---@alias DecoratorIconPlacement "none" | "before" | "after" | "signcolumn" | "right_align"
---Abstract Decorator
---Uses the factory pattern to instantiate child instances.
---@class (exact) Decorator: Class
---@field protected explorer Explorer
---@field protected enabled boolean
---@field protected hl_pos HL_POSITION
---@field protected icon_placement ICON_PLACEMENT
local Decorator = Class:new()
---@field protected range DecoratorRange
---@field protected icon_placement DecoratorIconPlacement
local Decorator = Class:extend()
---@class (exact) DecoratorArgs
---@field explorer Explorer
---@class (exact) AbstractDecoratorArgs: DecoratorArgs
---@field enabled boolean
---@field hl_pos DecoratorRange
---@field icon_placement DecoratorIconPlacement
---@protected
---@param args AbstractDecoratorArgs
function Decorator:new(args)
self.explorer = args.explorer
self.enabled = args.enabled
self.range = args.hl_pos
self.icon_placement = args.icon_placement
end
---Maybe highlight groups
---@param node Node
@@ -19,13 +36,13 @@ local Decorator = Class:new()
function Decorator:groups_icon_name(node)
local icon_hl, name_hl
if self.enabled and self.hl_pos ~= HL_POSITION.none then
if self.enabled and self.range ~= "none" then
local hl = self:calculate_highlight(node)
if self.hl_pos == HL_POSITION.all or self.hl_pos == HL_POSITION.icon then
if self.range == "all" or self.range == "icon" then
icon_hl = hl
end
if self.hl_pos == HL_POSITION.all or self.hl_pos == HL_POSITION.name then
if self.range == "all" or self.range == "name" then
name_hl = hl
end
end
@@ -37,7 +54,7 @@ end
---@param node Node
---@return string|nil name
function Decorator:sign_name(node)
if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.signcolumn then
if not self.enabled or self.icon_placement ~= "signcolumn" then
return
end
@@ -47,33 +64,33 @@ function Decorator:sign_name(node)
end
end
---Icons when ICON_PLACEMENT.before
---Icons when "before"
---@param node Node
---@return HighlightedString[]|nil icons
function Decorator:icons_before(node)
if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.before then
if not self.enabled or self.icon_placement ~= "before" then
return
end
return self:calculate_icons(node)
end
---Icons when ICON_PLACEMENT.after
---Icons when "after"
---@param node Node
---@return HighlightedString[]|nil icons
function Decorator:icons_after(node)
if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.after then
if not self.enabled or self.icon_placement ~= "after" then
return
end
return self:calculate_icons(node)
end
---Icons when ICON_PLACEMENT.right_align
---Icons when "right_align"
---@param node Node
---@return HighlightedString[]|nil icons
function Decorator:icons_right_align(node)
if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.right_align then
if not self.enabled or self.icon_placement ~= "right_align" then
return
end
@@ -109,7 +126,7 @@ function Decorator:define_sign(icon)
-- don't use sign if not defined
if #icon.str < 1 then
self.icon_placement = ICON_PLACEMENT.none
self.icon_placement = "none"
return
end

View File

@@ -1,42 +1,36 @@
local buffers = require("nvim-tree.buffers")
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
local DirectoryNode = require("nvim-tree.node.directory")
---@class (exact) DecoratorModified: Decorator
---@field icon HighlightedString|nil
local DecoratorModified = Decorator:new()
---@field icon HighlightedString?
local DecoratorModified = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorModified
function DecoratorModified:create(opts, explorer)
---@type DecoratorModified
local o = {
explorer = explorer,
enabled = opts.modified.enable,
hl_pos = HL_POSITION[opts.renderer.highlight_modified] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT[opts.renderer.icons.modified_placement] or ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorModified
---@overload fun(explorer: DecoratorArgs): DecoratorModified
if not o.enabled then
return o
---@protected
---@param args DecoratorArgs
function DecoratorModified:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_modified or "none",
icon_placement = args.explorer.opts.renderer.icons.modified_placement or "none",
})
if not self.enabled then
return
end
if opts.renderer.icons.show.modified then
o.icon = {
str = opts.renderer.icons.glyphs.modified,
if self.explorer.opts.renderer.icons.show.modified then
self.icon = {
str = self.explorer.opts.renderer.icons.glyphs.modified,
hl = { "NvimTreeModifiedIcon" },
}
o:define_sign(o.icon)
self:define_sign(self.icon)
end
return o
end
---Modified icon: modified.enable, renderer.icons.show.modified and node is modified
@@ -52,7 +46,7 @@ end
---@param node Node
---@return string|nil group
function DecoratorModified:calculate_highlight(node)
if not self.enabled or self.hl_pos == HL_POSITION.none or not buffers.is_modified(node) then
if not self.enabled or self.range == "none" or not buffers.is_modified(node) then
return nil
end

View File

@@ -1,36 +1,30 @@
local buffers = require("nvim-tree.buffers")
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
local Decorator = require("nvim-tree.renderer.decorator")
---@class (exact) DecoratorOpened: Decorator
---@field icon HighlightedString|nil
local DecoratorOpened = Decorator:new()
local DecoratorOpened = Decorator:extend()
---Static factory method
---@param opts table
---@param explorer Explorer
---@return DecoratorOpened
function DecoratorOpened:create(opts, explorer)
---@type DecoratorOpened
local o = {
explorer = explorer,
enabled = true,
hl_pos = HL_POSITION[opts.renderer.highlight_opened_files] or HL_POSITION.none,
icon_placement = ICON_PLACEMENT.none,
}
o = self:new(o)
---@class DecoratorOpened
---@overload fun(explorer: DecoratorArgs): DecoratorOpened
return o
---@protected
---@param args DecoratorArgs
function DecoratorOpened:new(args)
Decorator.new(self, {
explorer = args.explorer,
enabled = true,
hl_pos = args.explorer.opts.renderer.highlight_opened_files or "none",
icon_placement = "none",
})
end
---Opened highlight: renderer.highlight_opened_files and node has an open buffer
---@param node Node
---@return string|nil group
function DecoratorOpened:calculate_highlight(node)
if self.hl_pos ~= HL_POSITION.none and buffers.is_opened(node) then
if self.range ~= "none" and buffers.is_opened(node) then
return "NvimTreeOpenedHL"
end
end

View File

@@ -2,6 +2,7 @@ local log = require("nvim-tree.log")
local view = require("nvim-tree.view")
local events = require("nvim-tree.events")
local Class = require("nvim-tree.classic")
local Builder = require("nvim-tree.renderer.builder")
local SIGN_GROUP = "NvimTreeRendererSigns"
@@ -10,26 +11,20 @@ local namespace_highlights_id = vim.api.nvim_create_namespace("NvimTreeHighlight
local namespace_extmarks_id = vim.api.nvim_create_namespace("NvimTreeExtmarks")
local namespace_virtual_lines_id = vim.api.nvim_create_namespace("NvimTreeVirtualLines")
---@class (exact) Renderer
---@field private __index? table
---@field private opts table user options
---@field private explorer Explorer
local Renderer = {}
---@class (exact) Renderer: Class
---@field explorer Explorer
local Renderer = Class:extend()
---@param opts table user options
---@param explorer Explorer
---@return Renderer
function Renderer:new(opts, explorer)
---@type Renderer
local o = {
opts = opts,
explorer = explorer,
}
---@class Renderer
---@overload fun(args: RendererArgs): Renderer
setmetatable(o, self)
self.__index = self
---@class (exact) RendererArgs
---@field explorer Explorer
return o
---@protected
---@param args RendererArgs
function Renderer:new(args)
self.explorer = args.explorer
end
---@private
@@ -64,9 +59,9 @@ function Renderer:_draw(bufnr, lines, hl_args, signs, extmarks, virtual_lines)
for i, extname in pairs(extmarks) do
for _, mark in ipairs(extname) do
vim.api.nvim_buf_set_extmark(bufnr, namespace_extmarks_id, i, -1, {
virt_text = { { mark.str, mark.hl } },
virt_text = { { mark.str, mark.hl } },
virt_text_pos = "right_align",
hl_mode = "combine",
hl_mode = "combine",
})
end
end
@@ -74,8 +69,8 @@ function Renderer:_draw(bufnr, lines, hl_args, signs, extmarks, virtual_lines)
vim.api.nvim_buf_clear_namespace(bufnr, namespace_virtual_lines_id, 0, -1)
for line_nr, vlines in pairs(virtual_lines) do
vim.api.nvim_buf_set_extmark(bufnr, namespace_virtual_lines_id, line_nr, 0, {
virt_lines = vlines,
virt_lines_above = false,
virt_lines = vlines,
virt_lines_above = false,
virt_lines_leftcol = true,
})
end
@@ -106,7 +101,7 @@ function Renderer:draw()
local cursor = vim.api.nvim_win_get_cursor(view.get_winnr() or 0)
local builder = Builder:new(self.opts, self.explorer):build()
local builder = Builder(self.explorer):build()
self:_draw(bufnr, builder.lines, builder.hl_args, builder.signs, builder.extmarks, builder.virtual_lines)