Skip to content

Commit 3ab6dca

Browse files
committed
add DecoratorOpened
1 parent 4a7d849 commit 3ab6dca

File tree

10 files changed

+138
-74
lines changed

10 files changed

+138
-74
lines changed

doc/nvim-tree-lua.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2305,6 +2305,9 @@ Modified: >
23052305
NvimTreeModifiedFileHL NvimTreeModifiedIcon
23062306
NvimTreeModifiedFolderHL NvimTreeModifiedIcon
23072307
<
2308+
Opened: >
2309+
NvimTreeOpenedHL Constant
2310+
<
23082311
Picker: >
23092312
NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan
23102313
<
@@ -2388,6 +2391,7 @@ Legacy highlight group are still obeyed when they are defined and the current
23882391
highlight group is not, hard linking as follows: >
23892392
23902393
NvimTreeModifiedIcon NvimTreeModifiedFile
2394+
NvimTreeOpenedHL NvimTreeOpenedFile
23912395
23922396
NvimTreeGitDeletedIcon NvimTreeGitDeleted
23932397
NvimTreeGitDirtyIcon NvimTreeGitDirty

lua/nvim-tree.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ local function setup_autocommands(opts)
210210
-- update opened file buffers
211211
if (filters.config.filter_no_buffer or renderer.config.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then
212212
utils.debounce("Buf:filter_buffer", opts.view.debounce_delay, function()
213-
actions.reloaders.reload_explorer(nil, data.buf)
213+
actions.reloaders.reload_explorer()
214214
end)
215215
end
216216
end,
@@ -797,7 +797,7 @@ function M.setup(conf)
797797
require("nvim-tree.renderer").setup(opts)
798798
require("nvim-tree.live-filter").setup(opts)
799799
require("nvim-tree.marks").setup(opts)
800-
require("nvim-tree.modified").setup(opts)
800+
require("nvim-tree.buffers").setup(opts)
801801
require("nvim-tree.help").setup(opts)
802802
require("nvim-tree.watcher").setup(opts)
803803
if M.config.renderer.icons.show.file and pcall(require, "nvim-web-devicons") then

lua/nvim-tree/actions/reloaders.lua

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ local M = {}
1010

1111
---@param node Explorer|nil
1212
---@param projects table
13-
---@param unloaded_bufnr number|nil
14-
local function refresh_nodes(node, projects, unloaded_bufnr)
13+
local function refresh_nodes(node, projects)
1514
Iterator.builder({ node })
1615
:applier(function(n)
1716
if n.nodes then
1817
local toplevel = git.get_toplevel(n.cwd or n.link_to or n.absolute_path)
19-
explorer_module.reload(n, projects[toplevel] or {}, unloaded_bufnr)
18+
explorer_module.reload(n, projects[toplevel] or {})
2019
end
2120
end)
2221
:recursor(function(n)
@@ -43,18 +42,16 @@ function M.reload_node_status(parent_node, projects)
4342
end
4443

4544
local event_running = false
46-
---@param _ table|nil unused node passed by action
47-
---@param unloaded_bufnr number|nil optional bufnr recently unloaded via BufUnload event
48-
function M.reload_explorer(_, unloaded_bufnr)
45+
function M.reload_explorer()
4946
if event_running or not core.get_explorer() or vim.v.exiting ~= vim.NIL then
5047
return
5148
end
5249
event_running = true
5350

5451
local projects = git.reload()
55-
refresh_nodes(core.get_explorer(), projects, unloaded_bufnr)
52+
refresh_nodes(core.get_explorer(), projects)
5653
if view.is_visible() then
57-
renderer.draw(unloaded_bufnr)
54+
renderer.draw()
5855
end
5956
event_running = false
6057
end

lua/nvim-tree/buffers.lua

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
local M = {}
2+
3+
---@type table<string, boolean> record of which file is modified
4+
M._modified = {}
5+
6+
---@type number unloaded_bufnr for the duration of BufUnload
7+
M._unloaded_bufnr = nil
8+
9+
---refresh M._modified
10+
function M.reload_modified()
11+
M._modified = {}
12+
local bufs = vim.fn.getbufinfo { bufmodified = true, buflisted = true }
13+
for _, buf in pairs(bufs) do
14+
local path = buf.name
15+
if path ~= "" then -- not a [No Name] buffer
16+
-- mark all the parent as modified as well
17+
while
18+
M._modified[path] ~= true
19+
-- no need to keep going if already recorded
20+
-- This also prevents an infinite loop
21+
do
22+
M._modified[path] = true
23+
path = vim.fn.fnamemodify(path, ":h")
24+
end
25+
end
26+
end
27+
end
28+
29+
---@param node table
30+
---@return boolean
31+
function M.is_modified(node)
32+
return node
33+
and M.config.modified.enable
34+
and M._modified[node.absolute_path]
35+
and (not node.nodes or M.config.modified.show_on_dirs)
36+
and (not node.open or M.config.modified.show_on_open_dirs)
37+
end
38+
39+
---A buffer exists for the node's absolute path and it's not in the middle of a BufUnload handler.
40+
---@param node table
41+
---@return boolean
42+
function M.is_opened(node)
43+
return node and vim.fn.bufloaded(node.absolute_path) > 0 and vim.fn.bufnr(node.absolute_path) ~= M._unloaded_bufnr
44+
end
45+
46+
---Set the unloaded bufnr - at the start of the BufUnload handler.
47+
---@param bufnr number
48+
function M.set_unloaded_bufnr(bufnr)
49+
M._unloaded_bufnr = bufnr
50+
end
51+
52+
---Reset the unloaded bufnr - at the end of the BufUnload handler.
53+
function M.reset_unloaded_bufnr()
54+
M._unloaded_bufnr = nil
55+
end
56+
57+
---@param opts table
58+
function M.setup(opts)
59+
M.config = {
60+
modified = opts.modified,
61+
}
62+
end
63+
64+
return M

lua/nvim-tree/colors.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ local DEFAULT_LINKS = {
6969
NvimTreeModifiedFileHL = "NvimTreeModifiedIcon",
7070
NvimTreeModifiedFolderHL = "NvimTreeModifiedFileHL",
7171

72+
-- Opened
73+
NvimTreeOpenedHL = "Constant",
74+
7275
-- LiveFilter
7376
NvimTreeLiveFilterPrefix = "PreProc",
7477
NvimTreeLiveFilterValue = "ModeMsg",
@@ -123,6 +126,8 @@ local DEFAULT_LINKS = {
123126
local LEGACY_LINKS = {
124127
NvimTreeModifiedIcon = "NvimTreeModifiedFile",
125128

129+
NvimTreeOpenedHL = "NvimTreeOpenedFile",
130+
126131
NvimTreeGitDeletedIcon = "NvimTreeGitDeleted",
127132
NvimTreeGitDirtyIcon = "NvimTreeGitDirty",
128133
NvimTreeGitIgnoredIcon = "NvimTreeGitIgnored",

lua/nvim-tree/renderer/builder.lua

Lines changed: 5 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ function Builder:configure_filter(filter, prefix)
5454
return self
5555
end
5656

57-
function Builder:configure_opened_file_highlighting(highlight_opened_files)
58-
self.highlight_opened_files = highlight_opened_files
59-
return self
60-
end
61-
6257
function Builder:configure_icon_padding(padding)
6358
self.icon_padding = padding or " "
6459
return self
@@ -260,41 +255,6 @@ function Builder:_get_bookmark_icon(node)
260255
return bookmark_icon
261256
end
262257

263-
---@param node table
264-
---@return string|nil icon_hl
265-
---@return string|nil name_hl
266-
function Builder:_get_highlight_override(node, unloaded_bufnr)
267-
local name_hl, icon_hl
268-
269-
-- opened file
270-
if self.highlight_opened_files and vim.fn.bufloaded(node.absolute_path) > 0 and vim.fn.bufnr(node.absolute_path) ~= unloaded_bufnr then
271-
if self.highlight_opened_files == "all" or self.highlight_opened_files == "name" then
272-
name_hl = "NvimTreeOpenedFile"
273-
end
274-
if self.highlight_opened_files == "all" or self.highlight_opened_files == "icon" then
275-
icon_hl = "NvimTreeOpenedFileIcon"
276-
end
277-
end
278-
return icon_hl, name_hl
279-
end
280-
281-
---Append optional highlighting to icon or name.
282-
---@param node table
283-
---@param get_hl fun(node: table): HL_POSITION, string
284-
---@param icon_hl string[] icons to append to
285-
---@param name_hl string[] names to append to
286-
function Builder:_append_highlight(node, get_hl, icon_hl, name_hl)
287-
local pos, hl = get_hl(node)
288-
if pos ~= HL_POSITION.none and hl then
289-
if pos == HL_POSITION.all or pos == HL_POSITION.icon then
290-
table.insert(icon_hl, hl)
291-
end
292-
if pos == HL_POSITION.all or pos == HL_POSITION.name then
293-
table.insert(name_hl, hl)
294-
end
295-
end
296-
end
297-
298258
---Append optional highlighting to icon or name.
299259
---@param node table
300260
---@param decorator Decorator
@@ -372,7 +332,7 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia
372332
return line
373333
end
374334

375-
function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
335+
function Builder:_build_line(node, idx, num_children)
376336
-- various components
377337
local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers)
378338
local arrows = pad.get_arrows(node)
@@ -395,17 +355,9 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
395355
icon, name = self:_build_file(node)
396356
end
397357

398-
-- highlight override
399-
local icon_hl_override, name_hl_override = self:_get_highlight_override(node, unloaded_bufnr)
400-
if icon_hl_override then
401-
icon.hl = { icon_hl_override }
402-
end
403-
if name_hl_override then
404-
name.hl = { name_hl_override }
405-
end
406-
407358
-- extra highighting
408359
self:_append_dec_highlight(node, self.decorators.git, icon.hl, name.hl)
360+
self:_append_dec_highlight(node, self.decorators.opened, icon.hl, name.hl)
409361
self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl)
410362
self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl)
411363
self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl)
@@ -421,7 +373,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr)
421373

422374
if node.open then
423375
self.depth = self.depth + 1
424-
self:build(node, unloaded_bufnr)
376+
self:build(node)
425377
self.depth = self.depth - 1
426378
end
427379
end
@@ -440,12 +392,12 @@ function Builder:_get_nodes_number(nodes)
440392
return i
441393
end
442394

443-
function Builder:build(tree, unloaded_bufnr)
395+
function Builder:build(tree)
444396
local num_children = self:_get_nodes_number(tree.nodes)
445397
local idx = 1
446398
for _, node in ipairs(tree.nodes) do
447399
if not node.hidden then
448-
self:_build_line(node, idx, num_children, unloaded_bufnr)
400+
self:_build_line(node, idx, num_children)
449401
idx = idx + 1
450402
end
451403
end

lua/nvim-tree/renderer/decorator/init.lua

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ end
1616
---@diagnostic disable: unused-local
1717

1818
--- Node icon
19-
--- @param node table
19+
--- @param _ table node
2020
--- @return HighlightedString|nil modified icon
21-
function Decorator:get_icon(node) end
21+
function Decorator:get_icon(_) end
2222

2323
--- Node highlight group
24-
--- @param node table
24+
--- @param _ table node
2525
--- @return string|nil group
26-
function Decorator:get_highlight(node) end
26+
function Decorator:get_highlight(_) end
2727

2828
---@diagnostic enable: unused-local
2929

@@ -32,7 +32,13 @@ function Decorator:get_highlight(node) end
3232
--- @param icon HighlightedString|nil
3333
function Decorator:define_sign(icon)
3434
if icon and #icon.hl > 0 then
35-
vim.fn.sign_define(icon.hl[1], {
35+
local name = icon.hl[1]
36+
37+
if not vim.tbl_isempty(vim.fn.sign_getdefined(name)) then
38+
vim.fn.sign_undefine(name)
39+
end
40+
41+
vim.fn.sign_define(name, {
3642
text = icon.str,
3743
texthl = icon.hl[1],
3844
})

lua/nvim-tree/renderer/decorator/modified.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
local modified = require "nvim-tree.modified"
1+
local buffers = require "nvim-tree.buffers"
22

33
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
44
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
@@ -37,14 +37,14 @@ end
3737

3838
--- Modified icon: modified.enable, renderer.icons.show.modified and node is modified
3939
function DecoratorModified:get_icon(node)
40-
if self.enabled and modified.is_modified(node) then
40+
if self.enabled and buffers.is_modified(node) then
4141
return self.icon
4242
end
4343
end
4444

4545
--- Modified highlight: modified.enable, renderer.highlight_modified and node is modified
4646
function DecoratorModified:get_highlight(node)
47-
if not self.enabled or self.hl_pos == HL_POSITION.none or not modified.is_modified(node) then
47+
if not self.enabled or self.hl_pos == HL_POSITION.none or not buffers.is_modified(node) then
4848
return nil
4949
end
5050

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
local buffers = require "nvim-tree.buffers"
2+
3+
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
4+
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
5+
6+
local Decorator = require "nvim-tree.renderer.decorator"
7+
8+
--- @class DecoratorOpened: Decorator
9+
--- @field enabled boolean
10+
--- @field icon HighlightedString|nil
11+
local DecoratorOpened = Decorator:new()
12+
13+
--- @param opts table
14+
--- @return DecoratorOpened
15+
function DecoratorOpened:new(opts)
16+
local o = Decorator.new(self, {
17+
hl_pos = HL_POSITION[opts.renderer.highlight_opened_files] or HL_POSITION.none,
18+
icon_placement = ICON_PLACEMENT.none,
19+
})
20+
---@cast o DecoratorOpened
21+
22+
return o
23+
end
24+
25+
--- Opened highlight: renderer.highlight_opened_files and node has an open buffer
26+
--- @param node table
27+
function DecoratorOpened:get_highlight(node)
28+
if self.hl_pos ~= HL_POSITION.none and buffers.is_opened(node) then
29+
return "NvimTreeOpenedHL"
30+
end
31+
end
32+
33+
return DecoratorOpened

0 commit comments

Comments
 (0)