Skip to content

Commit 7ce94f2

Browse files
committed
node classes and constructors
1 parent 6f67837 commit 7ce94f2

File tree

9 files changed

+216
-59
lines changed

9 files changed

+216
-59
lines changed

lua/nvim-tree/actions/fs/create-file.lua

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,16 @@ local function get_num_nodes(iter)
3030
return i
3131
end
3232

33-
---@param node Node
33+
---@param has_children boolean
34+
---@param absolute_path string
35+
---@param name string
3436
---@return string
35-
local function get_containing_folder(node)
36-
if node.nodes ~= nil then
37-
return utils.path_add_trailing(node.absolute_path)
37+
local function get_containing_folder(has_children, absolute_path, name)
38+
if has_children then
39+
return utils.path_add_trailing(absolute_path)
3840
end
39-
local node_name_size = #(node.name or "")
40-
return node.absolute_path:sub(0, -node_name_size - 1)
41+
local node_name_size = #(name or "")
42+
return absolute_path:sub(0, -node_name_size - 1)
4143
end
4244

4345
---@param node Node|nil
@@ -48,17 +50,14 @@ function M.fn(node)
4850
end
4951

5052
node = node and lib.get_last_group_node(node)
53+
54+
local containing_folder
5155
if not node or node.name == ".." then
52-
node = {
53-
absolute_path = cwd,
54-
name = "",
55-
nodes = core.get_explorer().nodes,
56-
open = true,
57-
}
56+
containing_folder = get_containing_folder(core.get_explorer().nodes ~= nil, cwd, "")
57+
else
58+
containing_folder = get_containing_folder(node.nodes ~= nil, node.absolute_path, node.name)
5859
end
5960

60-
local containing_folder = get_containing_folder(node)
61-
6261
local input_opts = {
6362
prompt = "Create file ",
6463
default = containing_folder,

lua/nvim-tree/enum.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
local M = {}
22

3+
---Roughly synced with uv.fs_stat.result
4+
---@enum (key) NODE_TYPE
5+
M.NODE_TYPE = {
6+
directory = 1,
7+
file = 2,
8+
link = 4,
9+
}
10+
311
---Setup options for "highlight_*"
412
---@enum HL_POSITION
513
M.HL_POSITION = {

lua/nvim-tree/explorer/init.lua

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
local builders = require("nvim-tree.explorer.node-builders")
21
local git = require("nvim-tree.git")
32
local log = require("nvim-tree.log")
43
local notify = require("nvim-tree.notify")
@@ -7,9 +6,13 @@ local view = require("nvim-tree.view")
76
local watch = require("nvim-tree.explorer.watch")
87
local explorer_node = require("nvim-tree.explorer.node")
98

9+
local DirectoryNode = require("nvim-tree.node.directory")
10+
local FileNode = require("nvim-tree.node.file")
11+
local LinkNode = require("nvim-tree.node.link")
12+
local Watcher = require("nvim-tree.watcher")
13+
1014
local Iterator = require("nvim-tree.iterators.node-iterator")
1115
local NodeIterator = require("nvim-tree.iterators.node-iterator")
12-
local Watcher = require("nvim-tree.watcher")
1316

1417
local Filters = require("nvim-tree.explorer.filters")
1518
local Marks = require("nvim-tree.marks")
@@ -155,11 +158,11 @@ function Explorer:reload(node, git_status)
155158
if not nodes_by_path[abs] then
156159
local new_child = nil
157160
if t == "directory" and vim.loop.fs_access(abs, "R") and Watcher.is_fs_event_capable(abs) then
158-
new_child = builders.folder(node, abs, name, stat)
161+
new_child = DirectoryNode:new(self, node, abs, name, stat)
159162
elseif t == "file" then
160-
new_child = builders.file(node, abs, name, stat)
163+
new_child = FileNode:new(self, node, abs, name, stat)
161164
elseif t == "link" then
162-
local link = builders.link(node, abs, name, stat)
165+
local link = LinkNode:new(self, node, abs, name, stat)
163166
if link.link_to ~= nil then
164167
new_child = link
165168
end
@@ -171,7 +174,7 @@ function Explorer:reload(node, git_status)
171174
else
172175
local n = nodes_by_path[abs]
173176
if n then
174-
n.executable = builders.is_executable(abs) or false
177+
n.executable = utils.is_executable(abs) or false
175178
n.fs_stat = stat
176179
end
177180
end
@@ -372,11 +375,11 @@ function Explorer:populate_children(handle, cwd, node, git_status, parent)
372375
local t = stat and stat.type or nil
373376
local child = nil
374377
if t == "directory" and vim.loop.fs_access(abs, "R") then
375-
child = builders.folder(node, abs, name, stat)
378+
child = DirectoryNode:new(self, node, abs, name, stat)
376379
elseif t == "file" then
377-
child = builders.file(node, abs, name, stat)
380+
child = FileNode:new(self, node, abs, name, stat)
378381
elseif t == "link" then
379-
local link = builders.link(node, abs, name, stat)
382+
local link = LinkNode:new(self, node, abs, name, stat)
380383
if link.link_to ~= nil then
381384
child = link
382385
end

lua/nvim-tree/node.lua

Lines changed: 0 additions & 36 deletions
This file was deleted.

lua/nvim-tree/node/directory.lua

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
local watch = require("nvim-tree.explorer.watch")
2+
3+
local BaseNode = require("nvim-tree.node.init")
4+
5+
---@class (exact) DirectoryNode: BaseNode
6+
---@field has_children boolean
7+
---@field group_next Node|nil
8+
---@field nodes Node[]
9+
---@field open boolean
10+
---@field hidden_stats table -- Each field of this table is a key for source and value for count
11+
local DirectoryNode = BaseNode:new()
12+
13+
---@param explorer Explorer
14+
-----@param parent DirectoryNode -- TODO
15+
---@param absolute_path string
16+
---@param name string
17+
---@param fs_stat uv.fs_stat.result|nil
18+
---@return DirectoryNode
19+
function DirectoryNode:new(explorer, parent, absolute_path, name, fs_stat)
20+
local handle = vim.loop.fs_scandir(absolute_path)
21+
local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil
22+
23+
local o = BaseNode.new(self, {
24+
type = "directory",
25+
explorer = explorer,
26+
absolute_path = absolute_path,
27+
executable = false,
28+
fs_stat = fs_stat,
29+
hidden = false,
30+
is_dot = false,
31+
name = name,
32+
parent = parent,
33+
34+
has_children = has_children,
35+
group_next = nil, -- If node is grouped, this points to the next child dir/link node
36+
nodes = {},
37+
open = false,
38+
})
39+
---@cast o DirectoryNode
40+
41+
o.watcher = watch.create_watcher(o)
42+
43+
return o
44+
end
45+
46+
return DirectoryNode

lua/nvim-tree/node/file.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
local utils = require("nvim-tree.utils")
2+
3+
local BaseNode = require("nvim-tree.node.init")
4+
5+
---@class (exact) FileNode: BaseNode
6+
---@field extension string
7+
local FileNode = BaseNode:new()
8+
9+
---@param explorer Explorer
10+
-----@param parent DirectoryNode -- TODO
11+
---@param absolute_path string
12+
---@param name string
13+
---@param fs_stat uv.fs_stat.result|nil
14+
---@return FileNode
15+
function FileNode:new(explorer, parent, absolute_path, name, fs_stat)
16+
local o = BaseNode.new(self, {
17+
type = "file",
18+
explorer = explorer,
19+
absolute_path = absolute_path,
20+
executable = utils.is_executable(absolute_path),
21+
fs_stat = fs_stat,
22+
name = name,
23+
parent = parent,
24+
hidden = false,
25+
is_dot = false,
26+
27+
extension = string.match(name, ".?[^.]+%.(.*)") or "",
28+
})
29+
---@cast o FileNode
30+
31+
return o
32+
end
33+
34+
return FileNode

lua/nvim-tree/node/init.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---@class ParentNode
2+
---@field name string
3+
4+
---@class (exact) BaseNode
5+
---@field type NODE_TYPE
6+
---@field explorer Explorer
7+
---@field absolute_path string
8+
---@field executable boolean
9+
---@field fs_stat uv.fs_stat.result|nil
10+
---@field git_status GitStatus|nil
11+
---@field hidden boolean
12+
---@field is_dot boolean
13+
---@field name string
14+
---@field parent DirectoryNode
15+
---@field watcher Watcher|nil
16+
---@field diag_status DiagStatus|nil
17+
local BaseNode = {}
18+
19+
---@alias Node DirectoryNode|FileNode|LinkNode|Explorer
20+
21+
---@param o BaseNode|nil
22+
---@return BaseNode
23+
function BaseNode:new(o)
24+
o = o or {}
25+
26+
setmetatable(o, { __index = self })
27+
28+
return o
29+
end
30+
31+
return BaseNode

lua/nvim-tree/node/link.lua

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
local watch = require("nvim-tree.explorer.watch")
2+
3+
local BaseNode = require("nvim-tree.node.init")
4+
5+
---@class (exact) LinkNode: BaseNode
6+
---@field link_to string absolute path
7+
local LinkNode = BaseNode:new()
8+
9+
---@param explorer Explorer
10+
-----@param parent DirectoryNode -- TODO
11+
---@param absolute_path string
12+
---@param name string
13+
---@param fs_stat uv.fs_stat.result|nil
14+
---@return LinkNode
15+
function LinkNode:new(explorer, parent, absolute_path, name, fs_stat)
16+
local link_to = vim.loop.fs_realpath(absolute_path)
17+
local open, nodes, has_children
18+
19+
-- TODO-INFO: sometimes fs_realpath returns nil
20+
-- I expect this be a bug in glibc, because it fails to retrieve the path for some
21+
-- links (for instance libr2.so in /usr/lib) and thus even with a C program realpath fails
22+
-- when it has no real reason to. Maybe there is a reason, but errno is definitely wrong.
23+
-- So we need to check for link_to ~= nil when adding new links to the main tree
24+
local is_dir_link = (link_to ~= nil) and vim.loop.fs_stat(link_to).type == "directory"
25+
26+
if is_dir_link and link_to then
27+
local handle = vim.loop.fs_scandir(link_to)
28+
has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil
29+
open = false
30+
nodes = {}
31+
end
32+
33+
local o = BaseNode.new(self, {
34+
type = "link",
35+
explorer = explorer,
36+
absolute_path = absolute_path,
37+
executable = false,
38+
fs_stat = fs_stat,
39+
hidden = false,
40+
is_dot = false,
41+
name = name,
42+
parent = parent,
43+
44+
link_to = link_to,
45+
46+
has_children = has_children,
47+
group_next = nil, -- If node is grouped, this points to the next child dir/link node
48+
nodes = nodes,
49+
open = open,
50+
})
51+
---@cast o LinkNode
52+
53+
if is_dir_link then
54+
o.watcher = watch.create_watcher(o)
55+
end
56+
57+
return o
58+
end
59+
60+
return LinkNode

lua/nvim-tree/utils.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,4 +578,16 @@ function M.is_nvim_tree_buf(bufnr)
578578
return false
579579
end
580580

581+
--- path is an executable file or directory
582+
---@param absolute_path string
583+
---@return boolean
584+
function M.is_executable(absolute_path)
585+
if M.is_windows or M.is_wsl then
586+
--- executable detection on windows is buggy and not performant hence it is disabled
587+
return false
588+
else
589+
return vim.loop.fs_access(absolute_path, "X") or false
590+
end
591+
end
592+
581593
return M

0 commit comments

Comments
 (0)