* extract DirectoryLinkNode and FileLinkNode, move Node methods to children * temporarily move DirectoryNode methods into BaseNode for easier reviewing * move mostly unchanged DirectoryNode methods back to BaseNode * tidy * git.git_status_file takes an array * update git status of links * luacheck hack
This commit is contained in:
@@ -283,33 +283,46 @@ function M.load_project_status(path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Git file and directory status for an absolute path with optional file fallback
|
||||||
---@param parent_ignored boolean
|
---@param parent_ignored boolean
|
||||||
---@param status table|nil
|
---@param status table|nil
|
||||||
---@param absolute_path string
|
---@param path string
|
||||||
|
---@param path_file string? alternative file path when no other file status
|
||||||
---@return GitStatus|nil
|
---@return GitStatus|nil
|
||||||
function M.git_status_dir(parent_ignored, status, absolute_path)
|
function M.git_status_dir(parent_ignored, status, path, path_file)
|
||||||
if parent_ignored then
|
if parent_ignored then
|
||||||
return { file = "!!" }
|
return { file = "!!" }
|
||||||
end
|
end
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
return {
|
return {
|
||||||
file = status.files and status.files[absolute_path],
|
file = status.files and status.files[path] or path_file and status.files[path_file],
|
||||||
dir = status.dirs and {
|
dir = status.dirs and {
|
||||||
direct = status.dirs.direct[absolute_path],
|
direct = status.dirs.direct[path],
|
||||||
indirect = status.dirs.indirect[absolute_path],
|
indirect = status.dirs.indirect[path],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Git file status for an absolute path with optional fallback
|
||||||
---@param parent_ignored boolean
|
---@param parent_ignored boolean
|
||||||
---@param status table|nil
|
---@param status table|nil
|
||||||
---@param absolute_path string
|
---@param path string
|
||||||
|
---@param path_fallback string?
|
||||||
---@return GitStatus
|
---@return GitStatus
|
||||||
function M.git_status_file(parent_ignored, status, absolute_path)
|
function M.git_status_file(parent_ignored, status, path, path_fallback)
|
||||||
local file_status = parent_ignored and "!!" or (status and status.files and status.files[absolute_path])
|
if parent_ignored then
|
||||||
return { file = file_status }
|
return { file = "!!" }
|
||||||
|
end
|
||||||
|
|
||||||
|
if not status or not status.files then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
file = status.files[path] or status.files[path_fallback]
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.purge_state()
|
function M.purge_state()
|
||||||
|
|||||||
@@ -21,6 +21,25 @@ function M.raw(typ, fmt, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Write to a new file
|
||||||
|
---@param typ string as per log.types config
|
||||||
|
---@param path string absolute path
|
||||||
|
---@param fmt string for string.format
|
||||||
|
---@param ... any arguments for string.format
|
||||||
|
function M.file(typ, path, fmt, ...)
|
||||||
|
if not M.enabled(typ) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local line = string.format(fmt, ...)
|
||||||
|
local file = io.open(path, "w")
|
||||||
|
if file then
|
||||||
|
io.output(file)
|
||||||
|
io.write(line)
|
||||||
|
io.close(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---@class Profile
|
---@class Profile
|
||||||
---@field start number nanos
|
---@field start number nanos
|
||||||
---@field tag string
|
---@field tag string
|
||||||
|
|||||||
54
lua/nvim-tree/node/directory-link.lua
Normal file
54
lua/nvim-tree/node/directory-link.lua
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
local git = require("nvim-tree.git")
|
||||||
|
|
||||||
|
local DirectoryNode = require("nvim-tree.node.directory")
|
||||||
|
|
||||||
|
---@class (exact) DirectoryLinkNode: DirectoryNode
|
||||||
|
---@field link_to string absolute path
|
||||||
|
---@field fs_stat_target uv.fs_stat.result
|
||||||
|
local DirectoryLinkNode = DirectoryNode:new()
|
||||||
|
|
||||||
|
---Static factory method
|
||||||
|
---@param explorer Explorer
|
||||||
|
---@param parent Node
|
||||||
|
---@param absolute_path string
|
||||||
|
---@param link_to string
|
||||||
|
---@param name string
|
||||||
|
---@param fs_stat uv.fs_stat.result?
|
||||||
|
---@param fs_stat_target uv.fs_stat.result
|
||||||
|
---@return DirectoryLinkNode? nil on vim.loop.fs_realpath failure
|
||||||
|
function DirectoryLinkNode:create(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target)
|
||||||
|
-- create DirectoryNode with the target path for the watcher
|
||||||
|
local o = DirectoryNode:create(explorer, parent, link_to, name, fs_stat)
|
||||||
|
|
||||||
|
o = self:new(o) --[[@as DirectoryLinkNode]]
|
||||||
|
|
||||||
|
-- reset absolute path to the link itself
|
||||||
|
o.absolute_path = absolute_path
|
||||||
|
|
||||||
|
o.type = "link"
|
||||||
|
o.link_to = link_to
|
||||||
|
o.fs_stat_target = fs_stat_target
|
||||||
|
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
-----Update the directory GitStatus of link target and the file status of the link itself
|
||||||
|
-----@param parent_ignored boolean
|
||||||
|
-----@param status table|nil
|
||||||
|
function DirectoryLinkNode:update_git_status(parent_ignored, status)
|
||||||
|
self.git_status = git.git_status_dir(parent_ignored, status, self.link_to, self.absolute_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Create a sanitized partial copy of a node, populating children recursively.
|
||||||
|
---@return DirectoryLinkNode cloned
|
||||||
|
function DirectoryLinkNode:clone()
|
||||||
|
local clone = DirectoryNode.clone(self) --[[@as DirectoryLinkNode]]
|
||||||
|
|
||||||
|
clone.type = self.type
|
||||||
|
clone.link_to = self.link_to
|
||||||
|
clone.fs_stat_target = self.fs_stat_target
|
||||||
|
|
||||||
|
return clone
|
||||||
|
end
|
||||||
|
|
||||||
|
return DirectoryLinkNode
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
local git = require("nvim-tree.git")
|
||||||
local watch = require("nvim-tree.explorer.watch")
|
local watch = require("nvim-tree.explorer.watch")
|
||||||
|
|
||||||
local BaseNode = require("nvim-tree.node")
|
local BaseNode = require("nvim-tree.node")
|
||||||
@@ -58,6 +59,63 @@ function DirectoryNode:destroy()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Update the GitStatus of the directory
|
||||||
|
---@param parent_ignored boolean
|
||||||
|
---@param status table|nil
|
||||||
|
function DirectoryNode:update_git_status(parent_ignored, status)
|
||||||
|
self.git_status = git.git_status_dir(parent_ignored, status, self.absolute_path, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return GitStatus|nil
|
||||||
|
function DirectoryNode:get_git_status()
|
||||||
|
if not self.git_status or not self.explorer.opts.git.show_on_dirs then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local status = {}
|
||||||
|
if not self:last_group_node().open or self.explorer.opts.git.show_on_open_dirs then
|
||||||
|
-- dir is closed or we should show on open_dirs
|
||||||
|
if self.git_status.file ~= nil then
|
||||||
|
table.insert(status, self.git_status.file)
|
||||||
|
end
|
||||||
|
if self.git_status.dir ~= nil then
|
||||||
|
if self.git_status.dir.direct ~= nil then
|
||||||
|
for _, s in pairs(self.git_status.dir.direct) do
|
||||||
|
table.insert(status, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self.git_status.dir.indirect ~= nil then
|
||||||
|
for _, s in pairs(self.git_status.dir.indirect) do
|
||||||
|
table.insert(status, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- dir is open and we shouldn't show on open_dirs
|
||||||
|
if self.git_status.file ~= nil then
|
||||||
|
table.insert(status, self.git_status.file)
|
||||||
|
end
|
||||||
|
if self.git_status.dir ~= nil and self.git_status.dir.direct ~= nil then
|
||||||
|
local deleted = {
|
||||||
|
[" D"] = true,
|
||||||
|
["D "] = true,
|
||||||
|
["RD"] = true,
|
||||||
|
["DD"] = true,
|
||||||
|
}
|
||||||
|
for _, s in pairs(self.git_status.dir.direct) do
|
||||||
|
if deleted[s] then
|
||||||
|
table.insert(status, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #status == 0 then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---Create a sanitized partial copy of a node, populating children recursively.
|
---Create a sanitized partial copy of a node, populating children recursively.
|
||||||
---@return DirectoryNode cloned
|
---@return DirectoryNode cloned
|
||||||
function DirectoryNode:clone()
|
function DirectoryNode:clone()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
local DirectoryLinkNode = require("nvim-tree.node.directory-link")
|
||||||
local DirectoryNode = require("nvim-tree.node.directory")
|
local DirectoryNode = require("nvim-tree.node.directory")
|
||||||
local LinkNode = require("nvim-tree.node.link")
|
local FileLinkNode = require("nvim-tree.node.file-link")
|
||||||
local FileNode = require("nvim-tree.node.file")
|
local FileNode = require("nvim-tree.node.file")
|
||||||
local Watcher = require("nvim-tree.watcher")
|
local Watcher = require("nvim-tree.watcher")
|
||||||
|
|
||||||
@@ -8,21 +9,37 @@ local M = {}
|
|||||||
---Factory function to create the appropriate Node
|
---Factory function to create the appropriate Node
|
||||||
---@param explorer Explorer
|
---@param explorer Explorer
|
||||||
---@param parent Node
|
---@param parent Node
|
||||||
---@param abs string
|
---@param absolute_path string
|
||||||
---@param stat uv.fs_stat.result? -- on nil stat return nil Node
|
---@param stat uv.fs_stat.result? -- on nil stat return nil Node
|
||||||
---@param name string
|
---@param name string
|
||||||
---@return Node?
|
---@return Node?
|
||||||
function M.create_node(explorer, parent, abs, stat, name)
|
function M.create_node(explorer, parent, absolute_path, stat, name)
|
||||||
if not stat then
|
if not stat then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if stat.type == "directory" and vim.loop.fs_access(abs, "R") and Watcher.is_fs_event_capable(abs) then
|
if stat.type == "directory" then
|
||||||
return DirectoryNode:create(explorer, parent, abs, name, stat)
|
-- directory must be readable and enumerable
|
||||||
|
if vim.loop.fs_access(absolute_path, "R") and Watcher.is_fs_event_capable(absolute_path) then
|
||||||
|
return DirectoryNode:create(explorer, parent, absolute_path, name, stat)
|
||||||
|
end
|
||||||
elseif stat.type == "file" then
|
elseif stat.type == "file" then
|
||||||
return FileNode:create(explorer, parent, abs, name, stat)
|
-- any file
|
||||||
|
return FileNode:create(explorer, parent, absolute_path, name, stat)
|
||||||
elseif stat.type == "link" then
|
elseif stat.type == "link" then
|
||||||
return LinkNode:create(explorer, parent, abs, name, stat)
|
-- link target path and stat must resolve
|
||||||
|
local link_to = vim.loop.fs_realpath(absolute_path)
|
||||||
|
local link_to_stat = link_to and vim.loop.fs_stat(link_to)
|
||||||
|
if not link_to or not link_to_stat then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- choose directory or file
|
||||||
|
if link_to_stat.type == "directory" then
|
||||||
|
return DirectoryLinkNode:create(explorer, parent, absolute_path, link_to, name, stat, link_to_stat)
|
||||||
|
else
|
||||||
|
return FileLinkNode:create(explorer, parent, absolute_path, link_to, name, stat, link_to_stat)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
50
lua/nvim-tree/node/file-link.lua
Normal file
50
lua/nvim-tree/node/file-link.lua
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
local git = require("nvim-tree.git")
|
||||||
|
|
||||||
|
local FileNode = require("nvim-tree.node.file")
|
||||||
|
|
||||||
|
---@class (exact) FileLinkNode: FileNode
|
||||||
|
---@field link_to string absolute path
|
||||||
|
---@field fs_stat_target uv.fs_stat.result
|
||||||
|
local FileLinkNode = FileNode:new()
|
||||||
|
|
||||||
|
---Static factory method
|
||||||
|
---@param explorer Explorer
|
||||||
|
---@param parent Node
|
||||||
|
---@param absolute_path string
|
||||||
|
---@param link_to string
|
||||||
|
---@param name string
|
||||||
|
---@param fs_stat uv.fs_stat.result?
|
||||||
|
---@param fs_stat_target uv.fs_stat.result
|
||||||
|
---@return FileLinkNode? nil on vim.loop.fs_realpath failure
|
||||||
|
function FileLinkNode:create(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target)
|
||||||
|
local o = FileNode:create(explorer, parent, absolute_path, name, fs_stat)
|
||||||
|
|
||||||
|
o = self:new(o) --[[@as FileLinkNode]]
|
||||||
|
|
||||||
|
o.type = "link"
|
||||||
|
o.link_to = link_to
|
||||||
|
o.fs_stat_target = fs_stat_target
|
||||||
|
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
-----Update the GitStatus of the target otherwise the link itself
|
||||||
|
-----@param parent_ignored boolean
|
||||||
|
-----@param status table|nil
|
||||||
|
function FileLinkNode:update_git_status(parent_ignored, status)
|
||||||
|
self.git_status = git.git_status_file(parent_ignored, status, self.link_to, self.absolute_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Create a sanitized partial copy of a node
|
||||||
|
---@return FileLinkNode cloned
|
||||||
|
function FileLinkNode:clone()
|
||||||
|
local clone = FileNode.clone(self) --[[@as FileLinkNode]]
|
||||||
|
|
||||||
|
clone.type = self.type
|
||||||
|
clone.link_to = self.link_to
|
||||||
|
clone.fs_stat_target = self.fs_stat_target
|
||||||
|
|
||||||
|
return clone
|
||||||
|
end
|
||||||
|
|
||||||
|
return FileLinkNode
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
local git = require("nvim-tree.git")
|
||||||
local utils = require("nvim-tree.utils")
|
local utils = require("nvim-tree.utils")
|
||||||
|
|
||||||
local BaseNode = require("nvim-tree.node")
|
local BaseNode = require("nvim-tree.node")
|
||||||
@@ -36,7 +37,23 @@ function FileNode:create(explorer, parent, absolute_path, name, fs_stat)
|
|||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
---Create a sanitized partial copy of a node, populating children recursively.
|
---Update the GitStatus of the file
|
||||||
|
---@param parent_ignored boolean
|
||||||
|
---@param status table|nil
|
||||||
|
function FileNode:update_git_status(parent_ignored, status)
|
||||||
|
self.git_status = git.git_status_file(parent_ignored, status, self.absolute_path, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return GitStatus|nil
|
||||||
|
function FileNode:get_git_status()
|
||||||
|
if not self.git_status then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.git_status.file and { self.git_status.file }
|
||||||
|
end
|
||||||
|
|
||||||
|
---Create a sanitized partial copy of a node
|
||||||
---@return FileNode cloned
|
---@return FileNode cloned
|
||||||
function FileNode:clone()
|
function FileNode:clone()
|
||||||
local clone = BaseNode.clone(self) --[[@as FileNode]]
|
local clone = BaseNode.clone(self) --[[@as FileNode]]
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ local git = require("nvim-tree.git")
|
|||||||
---@field diag_status DiagStatus?
|
---@field diag_status DiagStatus?
|
||||||
local BaseNode = {}
|
local BaseNode = {}
|
||||||
|
|
||||||
---@alias Node RootNode|BaseNode|DirectoryNode|FileNode|LinkNode
|
---@alias Node RootNode|BaseNode|DirectoryNode|FileNode|DirectoryLinkNode|FileLinkNode
|
||||||
|
|
||||||
---@param o BaseNode?
|
---@param o BaseNode?
|
||||||
---@return BaseNode
|
---@return BaseNode
|
||||||
@@ -63,84 +63,16 @@ function BaseNode:has_one_child_folder()
|
|||||||
return #self.nodes == 1 and self.nodes[1].nodes and vim.loop.fs_access(self.nodes[1].absolute_path, "R") or false
|
return #self.nodes == 1 and self.nodes[1].nodes and vim.loop.fs_access(self.nodes[1].absolute_path, "R") or false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--luacheck: push ignore 212
|
||||||
|
---Update the GitStatus of the node
|
||||||
---@param parent_ignored boolean
|
---@param parent_ignored boolean
|
||||||
---@param status table|nil
|
---@param status table?
|
||||||
function BaseNode:update_git_status(parent_ignored, status)
|
function BaseNode:update_git_status(parent_ignored, status) ---@diagnostic disable-line: unused-local
|
||||||
local get_status
|
|
||||||
if self.nodes then
|
|
||||||
get_status = git.git_status_dir
|
|
||||||
else
|
|
||||||
get_status = git.git_status_file
|
|
||||||
end
|
end
|
||||||
|
--luacheck: pop
|
||||||
|
|
||||||
-- status of the node's absolute path
|
---@return GitStatus?
|
||||||
self.git_status = get_status(parent_ignored, status, self.absolute_path)
|
|
||||||
|
|
||||||
-- status of the link target, if the link itself is not dirty
|
|
||||||
if self.link_to and not self.git_status then
|
|
||||||
self.git_status = get_status(parent_ignored, status, self.link_to)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@return GitStatus|nil
|
|
||||||
function BaseNode:get_git_status()
|
function BaseNode:get_git_status()
|
||||||
if not self.git_status then
|
|
||||||
-- status doesn't exist
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if not self.nodes then
|
|
||||||
-- file
|
|
||||||
return self.git_status.file and { self.git_status.file }
|
|
||||||
end
|
|
||||||
|
|
||||||
-- dir
|
|
||||||
if not self.explorer.opts.git.show_on_dirs then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local status = {}
|
|
||||||
if not self:last_group_node().open or self.explorer.opts.git.show_on_open_dirs then
|
|
||||||
-- dir is closed or we should show on open_dirs
|
|
||||||
if self.git_status.file ~= nil then
|
|
||||||
table.insert(status, self.git_status.file)
|
|
||||||
end
|
|
||||||
if self.git_status.dir ~= nil then
|
|
||||||
if self.git_status.dir.direct ~= nil then
|
|
||||||
for _, s in pairs(self.git_status.dir.direct) do
|
|
||||||
table.insert(status, s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if self.git_status.dir.indirect ~= nil then
|
|
||||||
for _, s in pairs(self.git_status.dir.indirect) do
|
|
||||||
table.insert(status, s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- dir is open and we shouldn't show on open_dirs
|
|
||||||
if self.git_status.file ~= nil then
|
|
||||||
table.insert(status, self.git_status.file)
|
|
||||||
end
|
|
||||||
if self.git_status.dir ~= nil and self.git_status.dir.direct ~= nil then
|
|
||||||
local deleted = {
|
|
||||||
[" D"] = true,
|
|
||||||
["D "] = true,
|
|
||||||
["RD"] = true,
|
|
||||||
["DD"] = true,
|
|
||||||
}
|
|
||||||
for _, s in pairs(self.git_status.dir.direct) do
|
|
||||||
if deleted[s] then
|
|
||||||
table.insert(status, s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #status == 0 then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
return status
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param projects table
|
---@param projects table
|
||||||
@@ -176,7 +108,8 @@ end
|
|||||||
-- If node is grouped, return the last node in the group. Otherwise, return the given node.
|
-- If node is grouped, return the last node in the group. Otherwise, return the given node.
|
||||||
---@return Node
|
---@return Node
|
||||||
function BaseNode:last_group_node()
|
function BaseNode:last_group_node()
|
||||||
local node = self --[[@as BaseNode]]
|
local node = self
|
||||||
|
--- @cast node BaseNode
|
||||||
|
|
||||||
while node.group_next do
|
while node.group_next do
|
||||||
node = node.group_next
|
node = node.group_next
|
||||||
@@ -185,8 +118,8 @@ function BaseNode:last_group_node()
|
|||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param project table|nil
|
---@param project table?
|
||||||
---@param root string|nil
|
---@param root string?
|
||||||
function BaseNode:update_parent_statuses(project, root)
|
function BaseNode:update_parent_statuses(project, root)
|
||||||
local node = self
|
local node = self
|
||||||
while project and node do
|
while project and node do
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
local watch = require("nvim-tree.explorer.watch")
|
|
||||||
|
|
||||||
local BaseNode = require("nvim-tree.node")
|
|
||||||
|
|
||||||
---@class (exact) LinkNode: BaseNode
|
|
||||||
---@field has_children boolean
|
|
||||||
---@field group_next Node? -- If node is grouped, this points to the next child dir/link node
|
|
||||||
---@field link_to string absolute path
|
|
||||||
---@field nodes Node[]
|
|
||||||
---@field open boolean
|
|
||||||
local LinkNode = BaseNode:new()
|
|
||||||
|
|
||||||
---Static factory method
|
|
||||||
---@param explorer Explorer
|
|
||||||
---@param parent Node
|
|
||||||
---@param absolute_path string
|
|
||||||
---@param name string
|
|
||||||
---@param fs_stat uv.fs_stat.result?
|
|
||||||
---@return LinkNode? nil on vim.loop.fs_realpath failure
|
|
||||||
function LinkNode:create(explorer, parent, absolute_path, name, fs_stat)
|
|
||||||
-- INFO: sometimes fs_realpath returns nil
|
|
||||||
-- I expect this be a bug in glibc, because it fails to retrieve the path for some
|
|
||||||
-- links (for instance libr2.so in /usr/lib) and thus even with a C program realpath fails
|
|
||||||
-- when it has no real reason to. Maybe there is a reason, but errno is definitely wrong.
|
|
||||||
local link_to = vim.loop.fs_realpath(absolute_path)
|
|
||||||
if not link_to then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local open, nodes, has_children
|
|
||||||
local is_dir_link = (link_to ~= nil) and vim.loop.fs_stat(link_to).type == "directory"
|
|
||||||
|
|
||||||
if is_dir_link and link_to then
|
|
||||||
local handle = vim.loop.fs_scandir(link_to)
|
|
||||||
has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil or false
|
|
||||||
open = false
|
|
||||||
nodes = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
---@type LinkNode
|
|
||||||
local o = {
|
|
||||||
type = "link",
|
|
||||||
explorer = explorer,
|
|
||||||
absolute_path = absolute_path,
|
|
||||||
executable = false,
|
|
||||||
fs_stat = fs_stat,
|
|
||||||
hidden = false,
|
|
||||||
is_dot = false,
|
|
||||||
name = name,
|
|
||||||
parent = parent,
|
|
||||||
watcher = nil,
|
|
||||||
diag_status = nil,
|
|
||||||
|
|
||||||
has_children = has_children,
|
|
||||||
group_next = nil,
|
|
||||||
link_to = link_to,
|
|
||||||
nodes = nodes,
|
|
||||||
open = open,
|
|
||||||
}
|
|
||||||
o = self:new(o) --[[@as LinkNode]]
|
|
||||||
|
|
||||||
if is_dir_link then
|
|
||||||
o.watcher = watch.create_watcher(o)
|
|
||||||
end
|
|
||||||
|
|
||||||
return o
|
|
||||||
end
|
|
||||||
|
|
||||||
---Create a sanitized partial copy of a node, populating children recursively.
|
|
||||||
---@return LinkNode cloned
|
|
||||||
function LinkNode:clone()
|
|
||||||
local clone = BaseNode.clone(self) --[[@as LinkNode]]
|
|
||||||
|
|
||||||
clone.has_children = self.has_children
|
|
||||||
clone.group_next = nil
|
|
||||||
clone.link_to = self.link_to
|
|
||||||
clone.nodes = {}
|
|
||||||
clone.open = self.open
|
|
||||||
|
|
||||||
if self.nodes then
|
|
||||||
for _, child in ipairs(self.nodes) do
|
|
||||||
table.insert(clone.nodes, child:clone())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return clone
|
|
||||||
end
|
|
||||||
|
|
||||||
return LinkNode
|
|
||||||
Reference in New Issue
Block a user