typechecked optargs constructors for nodes
This commit is contained in:
@@ -19,11 +19,7 @@ Object.__index = Object ---@diagnostic disable-line: inject-field
|
|||||||
function Object:new(...)
|
function Object:new(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Extend a class T
|
---Extend a class, setting .super
|
||||||
---super will be set to T
|
|
||||||
---@generic T
|
|
||||||
---@param self T
|
|
||||||
---@return T
|
|
||||||
function Object:extend()
|
function Object:extend()
|
||||||
local cls = {}
|
local cls = {}
|
||||||
for k, v in pairs(self) do
|
for k, v in pairs(self) do
|
||||||
@@ -38,10 +34,11 @@ function Object:extend()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---Implement the functions of a mixin
|
---Implement the functions of a mixin
|
||||||
---Add the mixin to the implements table
|
---Add the mixin to .implements
|
||||||
---@param class Object
|
---@param class Object
|
||||||
function Object:implement(class)
|
function Object:implement(class)
|
||||||
if not rawget(self, "implements") then
|
if not rawget(self, "implements") then
|
||||||
|
-- set on the class itself instead of parents
|
||||||
rawset(self, "implements", {})
|
rawset(self, "implements", {})
|
||||||
end
|
end
|
||||||
self.implements[class] = true
|
self.implements[class] = true
|
||||||
@@ -78,11 +75,7 @@ function Object:as(class)
|
|||||||
return self:is(class) and self or nil
|
return self:is(class) and self or nil
|
||||||
end
|
end
|
||||||
|
|
||||||
---Constructor that invokes :new on a new instance
|
---Constructor to create instance, call :new and return
|
||||||
---@generic T
|
|
||||||
---@param self T
|
|
||||||
---@param ... any
|
|
||||||
---@return T
|
|
||||||
function Object:__call(...)
|
function Object:__call(...)
|
||||||
local obj = setmetatable({}, self)
|
local obj = setmetatable({}, self)
|
||||||
obj:new(...)
|
obj:new(...)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function M.init(foldername)
|
|||||||
path, err = vim.loop.cwd()
|
path, err = vim.loop.cwd()
|
||||||
end
|
end
|
||||||
if path then
|
if path then
|
||||||
TreeExplorer = require("nvim-tree.explorer")(path)
|
TreeExplorer = require("nvim-tree.explorer")({ path = path })
|
||||||
else
|
else
|
||||||
notify.error(err)
|
notify.error(err)
|
||||||
TreeExplorer = nil
|
TreeExplorer = nil
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---Must be synced with uv.fs_stat.result as it is compared with it
|
|
||||||
---@enum (key) NODE_TYPE
|
|
||||||
M.NODE_TYPE = {
|
|
||||||
directory = 1,
|
|
||||||
file = 2,
|
|
||||||
link = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
---Setup options for "highlight_*"
|
---Setup options for "highlight_*"
|
||||||
---@enum HL_POSITION
|
---@enum HL_POSITION
|
||||||
M.HL_POSITION = {
|
M.HL_POSITION = {
|
||||||
|
|||||||
@@ -37,9 +37,19 @@ local config
|
|||||||
---@field clipboard Clipboard
|
---@field clipboard Clipboard
|
||||||
local Explorer = RootNode:extend()
|
local Explorer = RootNode:extend()
|
||||||
|
|
||||||
---@param path string
|
---@class Explorer
|
||||||
function Explorer:new(path)
|
---@overload fun(opts: ExplorerArgs): Explorer
|
||||||
Explorer.super.new(self, self, path, "..", nil)
|
|
||||||
|
---@class (exact) ExplorerArgs
|
||||||
|
---@field path string
|
||||||
|
|
||||||
|
---@param args ExplorerArgs
|
||||||
|
function Explorer:new(args)
|
||||||
|
Explorer.super.new(self, {
|
||||||
|
explorer = self,
|
||||||
|
absolute_path = args.path,
|
||||||
|
name = "..",
|
||||||
|
})
|
||||||
|
|
||||||
self.uid_explorer = vim.loop.hrtime()
|
self.uid_explorer = vim.loop.hrtime()
|
||||||
self.augroup_id = vim.api.nvim_create_augroup("NvimTree_Explorer_" .. self.uid_explorer, {})
|
self.augroup_id = vim.api.nvim_create_augroup("NvimTree_Explorer_" .. self.uid_explorer, {})
|
||||||
@@ -222,7 +232,13 @@ function Explorer:reload(node, project)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not nodes_by_path[abs] then
|
if not nodes_by_path[abs] then
|
||||||
local new_child = node_factory.create_node(self, node, abs, stat, name)
|
local new_child = node_factory.create({
|
||||||
|
explorer = self,
|
||||||
|
parent = node,
|
||||||
|
absolute_path = abs,
|
||||||
|
name = name,
|
||||||
|
fs_stat = stat
|
||||||
|
})
|
||||||
if new_child then
|
if new_child then
|
||||||
table.insert(node.nodes, new_child)
|
table.insert(node.nodes, new_child)
|
||||||
nodes_by_path[abs] = new_child
|
nodes_by_path[abs] = new_child
|
||||||
@@ -360,7 +376,13 @@ function Explorer:populate_children(handle, cwd, node, project, parent)
|
|||||||
local stat = vim.loop.fs_lstat(abs)
|
local stat = vim.loop.fs_lstat(abs)
|
||||||
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
|
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
|
||||||
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] then
|
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] then
|
||||||
local child = node_factory.create_node(self, node, abs, stat, name)
|
local child = node_factory.create({
|
||||||
|
explorer = self,
|
||||||
|
parent = node,
|
||||||
|
absolute_path = abs,
|
||||||
|
name = name,
|
||||||
|
fs_stat = stat
|
||||||
|
})
|
||||||
if child then
|
if child then
|
||||||
table.insert(node.nodes, child)
|
table.insert(node.nodes, child)
|
||||||
nodes_by_path[child.absolute_path] = true
|
nodes_by_path[child.absolute_path] = true
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ local LinkNode = require("nvim-tree.node.link")
|
|||||||
local DirectoryLinkNode = DirectoryNode:extend()
|
local DirectoryLinkNode = DirectoryNode:extend()
|
||||||
DirectoryLinkNode:implement(LinkNode)
|
DirectoryLinkNode:implement(LinkNode)
|
||||||
|
|
||||||
---@param explorer Explorer
|
---@class DirectoryLinkNode
|
||||||
---@param parent DirectoryNode
|
---@overload fun(opts: LinkNodeArgs): DirectoryLinkNode
|
||||||
---@param absolute_path string
|
|
||||||
---@param link_to string
|
---@protected
|
||||||
---@param name string
|
---@param args LinkNodeArgs
|
||||||
---@param fs_stat uv.fs_stat.result?
|
function DirectoryLinkNode:new(args)
|
||||||
---@param fs_stat_target uv.fs_stat.result
|
LinkNode.new(self, args)
|
||||||
function DirectoryLinkNode:new(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target)
|
|
||||||
-- create DirectoryNode with the target path for the watcher
|
-- create DirectoryNode with watcher on link_to
|
||||||
DirectoryLinkNode.super.new(self, explorer, parent, link_to, name, fs_stat)
|
local absolute_path = args.absolute_path
|
||||||
|
args.absolute_path = args.link_to
|
||||||
|
DirectoryLinkNode.super.new(self, args)
|
||||||
|
|
||||||
|
self.type = "link"
|
||||||
|
|
||||||
-- reset absolute path to the link itself
|
-- reset absolute path to the link itself
|
||||||
self.absolute_path = absolute_path
|
self.absolute_path = absolute_path
|
||||||
|
|
||||||
self.type = "link"
|
|
||||||
self.link_to = link_to
|
|
||||||
self.fs_stat_target = fs_stat_target
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function DirectoryLinkNode:destroy()
|
function DirectoryLinkNode:destroy()
|
||||||
@@ -76,7 +76,6 @@ end
|
|||||||
function DirectoryLinkNode:clone()
|
function DirectoryLinkNode:clone()
|
||||||
local clone = DirectoryNode.clone(self) --[[@as DirectoryLinkNode]]
|
local clone = DirectoryNode.clone(self) --[[@as DirectoryLinkNode]]
|
||||||
|
|
||||||
clone.type = self.type
|
|
||||||
clone.link_to = self.link_to
|
clone.link_to = self.link_to
|
||||||
clone.fs_stat_target = self.fs_stat_target
|
clone.fs_stat_target = self.fs_stat_target
|
||||||
|
|
||||||
|
|||||||
@@ -12,36 +12,26 @@ local Node = require("nvim-tree.node")
|
|||||||
---@field private watcher Watcher?
|
---@field private watcher Watcher?
|
||||||
local DirectoryNode = Node:extend()
|
local DirectoryNode = Node:extend()
|
||||||
|
|
||||||
---@param explorer Explorer
|
---@class DirectoryNode
|
||||||
---@param parent DirectoryNode?
|
---@overload fun(opts: NodeArgs): DirectoryNode
|
||||||
---@param absolute_path string
|
|
||||||
---@param name string
|
|
||||||
---@param fs_stat uv.fs_stat.result|nil
|
|
||||||
function DirectoryNode:new(explorer, parent, absolute_path, name, fs_stat)
|
|
||||||
DirectoryNode.super.new(self)
|
|
||||||
|
|
||||||
local handle = vim.loop.fs_scandir(absolute_path)
|
---@protected
|
||||||
|
---@param args NodeArgs
|
||||||
|
function DirectoryNode:new(args)
|
||||||
|
DirectoryNode.super.new(self, args)
|
||||||
|
|
||||||
|
local handle = vim.loop.fs_scandir(args.absolute_path)
|
||||||
local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil or false
|
local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil or false
|
||||||
|
|
||||||
self.type = "directory"
|
self.type = "directory"
|
||||||
self.explorer = explorer
|
|
||||||
self.absolute_path = absolute_path
|
|
||||||
self.executable = false
|
|
||||||
self.fs_stat = fs_stat
|
|
||||||
self.git_status = nil
|
|
||||||
self.hidden = false
|
|
||||||
self.name = name
|
|
||||||
self.parent = parent
|
|
||||||
self.watcher = nil
|
|
||||||
self.diag_status = nil
|
|
||||||
|
|
||||||
self.has_children = has_children
|
self.has_children = has_children
|
||||||
self.group_next = nil
|
self.group_next = nil
|
||||||
self.nodes = {}
|
self.nodes = {}
|
||||||
self.open = false
|
self.open = false
|
||||||
self.hidden_stats = nil
|
self.hidden_stats = nil
|
||||||
|
|
||||||
self.watcher = require("nvim-tree.explorer.watch").create_watcher(self)
|
self.watcher = require("nvim-tree.explorer.watch").create_watcher(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function DirectoryNode:destroy()
|
function DirectoryNode:destroy()
|
||||||
|
|||||||
@@ -7,38 +7,38 @@ local Watcher = require("nvim-tree.watcher")
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---Factory function to create the appropriate Node
|
---Factory function to create the appropriate Node
|
||||||
---@param explorer Explorer
|
---nil on invalid stat or invalid link target stat
|
||||||
---@param parent DirectoryNode
|
---@param args NodeArgs
|
||||||
---@param absolute_path string
|
|
||||||
---@param stat uv.fs_stat.result? -- on nil stat return nil Node
|
|
||||||
---@param name string
|
|
||||||
---@return Node?
|
---@return Node?
|
||||||
function M.create_node(explorer, parent, absolute_path, stat, name)
|
function M.create(args)
|
||||||
if not stat then
|
if not args.fs_stat then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if stat.type == "directory" then
|
if args.fs_stat.type == "directory" then
|
||||||
-- directory must be readable and enumerable
|
-- directory must be readable and enumerable
|
||||||
if vim.loop.fs_access(absolute_path, "R") and Watcher.is_fs_event_capable(absolute_path) then
|
if vim.loop.fs_access(args.absolute_path, "R") and Watcher.is_fs_event_capable(args.absolute_path) then
|
||||||
return DirectoryNode(explorer, parent, absolute_path, name, stat)
|
return DirectoryNode(args)
|
||||||
end
|
end
|
||||||
elseif stat.type == "file" then
|
elseif args.fs_stat.type == "file" then
|
||||||
-- any file
|
return FileNode(args)
|
||||||
return FileNode(explorer, parent, absolute_path, name, stat)
|
elseif args.fs_stat.type == "link" then
|
||||||
elseif stat.type == "link" then
|
|
||||||
-- link target path and stat must resolve
|
-- link target path and stat must resolve
|
||||||
local link_to = vim.loop.fs_realpath(absolute_path)
|
local link_to = vim.loop.fs_realpath(args.absolute_path)
|
||||||
local link_to_stat = link_to and vim.loop.fs_stat(link_to)
|
local link_to_stat = link_to and vim.loop.fs_stat(link_to)
|
||||||
if not link_to or not link_to_stat then
|
if not link_to or not link_to_stat then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@cast args LinkNodeArgs
|
||||||
|
args.link_to = link_to
|
||||||
|
args.fs_stat_target = link_to_stat
|
||||||
|
|
||||||
-- choose directory or file
|
-- choose directory or file
|
||||||
if link_to_stat.type == "directory" then
|
if link_to_stat.type == "directory" then
|
||||||
return DirectoryLinkNode(explorer, parent, absolute_path, link_to, name, stat, link_to_stat)
|
return DirectoryLinkNode(args)
|
||||||
else
|
else
|
||||||
return FileLinkNode(explorer, parent, absolute_path, link_to, name, stat, link_to_stat)
|
return FileLinkNode(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,19 +8,16 @@ local LinkNode = require("nvim-tree.node.link")
|
|||||||
local FileLinkNode = FileNode:extend()
|
local FileLinkNode = FileNode:extend()
|
||||||
FileLinkNode:implement(LinkNode)
|
FileLinkNode:implement(LinkNode)
|
||||||
|
|
||||||
---@param explorer Explorer
|
---@class FileLinkNode
|
||||||
---@param parent DirectoryNode
|
---@overload fun(opts: LinkNodeArgs): FileLinkNode
|
||||||
---@param absolute_path string
|
|
||||||
---@param link_to string
|
---@protected
|
||||||
---@param name string
|
---@param args LinkNodeArgs
|
||||||
---@param fs_stat uv.fs_stat.result?
|
function FileLinkNode:new(args)
|
||||||
---@param fs_stat_target uv.fs_stat.result
|
LinkNode.new(self, args)
|
||||||
function FileLinkNode:new(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target)
|
FileLinkNode.super.new(self, args)
|
||||||
FileLinkNode.super.new(self, explorer, parent, absolute_path, name, fs_stat)
|
|
||||||
|
|
||||||
self.type = "link"
|
self.type = "link"
|
||||||
self.link_to = link_to
|
|
||||||
self.fs_stat_target = fs_stat_target
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileLinkNode:destroy()
|
function FileLinkNode:destroy()
|
||||||
@@ -65,7 +62,6 @@ end
|
|||||||
function FileLinkNode:clone()
|
function FileLinkNode:clone()
|
||||||
local clone = FileNode.clone(self) --[[@as FileLinkNode]]
|
local clone = FileNode.clone(self) --[[@as FileLinkNode]]
|
||||||
|
|
||||||
clone.type = self.type
|
|
||||||
clone.link_to = self.link_to
|
clone.link_to = self.link_to
|
||||||
clone.fs_stat_target = self.fs_stat_target
|
clone.fs_stat_target = self.fs_stat_target
|
||||||
|
|
||||||
|
|||||||
@@ -17,26 +17,17 @@ local PICTURE_MAP = {
|
|||||||
---@field extension string
|
---@field extension string
|
||||||
local FileNode = Node:extend()
|
local FileNode = Node:extend()
|
||||||
|
|
||||||
---@param explorer Explorer
|
---@class FileNode
|
||||||
---@param parent DirectoryNode
|
---@overload fun(opts: NodeArgs): FileNode
|
||||||
---@param absolute_path string
|
|
||||||
---@param name string
|
|
||||||
---@param fs_stat uv.fs_stat.result?
|
|
||||||
function FileNode:new(explorer, parent, absolute_path, name, fs_stat)
|
|
||||||
FileNode.super.new(self)
|
|
||||||
|
|
||||||
self.type = "file"
|
---@protected
|
||||||
self.explorer = explorer
|
---@param args NodeArgs
|
||||||
self.absolute_path = absolute_path
|
function FileNode:new(args)
|
||||||
self.executable = utils.is_executable(absolute_path)
|
FileNode.super.new(self, args)
|
||||||
self.fs_stat = fs_stat
|
|
||||||
self.git_status = nil
|
|
||||||
self.hidden = false
|
|
||||||
self.name = name
|
|
||||||
self.parent = parent
|
|
||||||
self.diag_status = nil
|
|
||||||
|
|
||||||
self.extension = string.match(name, ".?[^.]+%.(.*)") or ""
|
self.type = "file"
|
||||||
|
self.extension = string.match(args.name, ".?[^.]+%.(.*)") or ""
|
||||||
|
self.executable = utils.is_executable(args.absolute_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileNode:destroy()
|
function FileNode:destroy()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ local Object = require("nvim-tree.classic")
|
|||||||
|
|
||||||
---Abstract Node class.
|
---Abstract Node class.
|
||||||
---@class (exact) Node: Object
|
---@class (exact) Node: Object
|
||||||
---@field type NODE_TYPE
|
---@field type "file" | "directory" | "link" uv.fs_stat.result.type
|
||||||
---@field explorer Explorer
|
---@field explorer Explorer
|
||||||
---@field absolute_path string
|
---@field absolute_path string
|
||||||
---@field executable boolean
|
---@field executable boolean
|
||||||
@@ -15,8 +15,26 @@ local Object = require("nvim-tree.classic")
|
|||||||
---@field private is_dot boolean cached is_dotfile
|
---@field private is_dot boolean cached is_dotfile
|
||||||
local Node = Object:extend()
|
local Node = Object:extend()
|
||||||
|
|
||||||
function Node:new()
|
---@class (exact) NodeArgs
|
||||||
self.is_dot = false
|
---@field explorer Explorer
|
||||||
|
---@field parent DirectoryNode?
|
||||||
|
---@field absolute_path string
|
||||||
|
---@field name string
|
||||||
|
---@field fs_stat uv.fs_stat.result?
|
||||||
|
|
||||||
|
---@protected
|
||||||
|
---@param args NodeArgs
|
||||||
|
function Node:new(args)
|
||||||
|
self.explorer = args.explorer
|
||||||
|
self.absolute_path = args.absolute_path
|
||||||
|
self.executable = false
|
||||||
|
self.fs_stat = args.fs_stat
|
||||||
|
self.git_status = nil
|
||||||
|
self.hidden = false
|
||||||
|
self.name = args.name
|
||||||
|
self.parent = args.parent
|
||||||
|
self.diag_status = nil
|
||||||
|
self.is_dot = false
|
||||||
end
|
end
|
||||||
|
|
||||||
function Node:destroy()
|
function Node:destroy()
|
||||||
|
|||||||
@@ -5,4 +5,17 @@ local Object = require("nvim-tree.classic")
|
|||||||
---@field protected fs_stat_target uv.fs_stat.result
|
---@field protected fs_stat_target uv.fs_stat.result
|
||||||
local LinkNode = Object:extend()
|
local LinkNode = Object:extend()
|
||||||
|
|
||||||
|
---@class (exact) LinkNodeArgs: NodeArgs
|
||||||
|
---@field link_to string
|
||||||
|
---@field fs_stat_target uv.fs_stat.result
|
||||||
|
---
|
||||||
|
---@protected
|
||||||
|
---@param args LinkNodeArgs
|
||||||
|
function LinkNode:new(args)
|
||||||
|
LinkNode.super.new(self, args)
|
||||||
|
|
||||||
|
self.link_to = args.link_to
|
||||||
|
self.fs_stat_target = args.fs_stat_target
|
||||||
|
end
|
||||||
|
|
||||||
return LinkNode
|
return LinkNode
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ local DirectoryNode = require("nvim-tree.node.directory")
|
|||||||
---@class (exact) RootNode: DirectoryNode
|
---@class (exact) RootNode: DirectoryNode
|
||||||
local RootNode = DirectoryNode:extend()
|
local RootNode = DirectoryNode:extend()
|
||||||
|
|
||||||
---@param explorer Explorer
|
---@class RootNode
|
||||||
---@param absolute_path string
|
---@overload fun(opts: NodeArgs): RootNode
|
||||||
---@param name string
|
|
||||||
---@param fs_stat uv.fs_stat.result|nil
|
---@protected
|
||||||
function RootNode:new(explorer, absolute_path, name, fs_stat)
|
---@param args NodeArgs
|
||||||
RootNode.super.new(self, explorer, nil, absolute_path, name, fs_stat)
|
function RootNode:new(args)
|
||||||
|
RootNode.super.new(self, args)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Root is never a dotfile
|
---Root is never a dotfile
|
||||||
|
|||||||
Reference in New Issue
Block a user