From 35015149e2fea423fbcfcec0c2ab88b598f364fa Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 4 Nov 2024 13:17:33 +1100 Subject: [PATCH 01/38] add classic, migrating nodes classes --- lua/nvim-tree/classic.lua | 77 +++++++++++++++++++++++++++ lua/nvim-tree/core.lua | 17 +++++- lua/nvim-tree/explorer/init.lua | 56 ++++++------------- lua/nvim-tree/node/directory-link.lua | 24 +++------ lua/nvim-tree/node/directory.lua | 53 ++++++++---------- lua/nvim-tree/node/factory.lua | 8 +-- lua/nvim-tree/node/file-link.lua | 22 +++----- lua/nvim-tree/node/file.lua | 39 ++++++-------- lua/nvim-tree/node/init.lua | 11 ++-- lua/nvim-tree/node/link.lua | 8 +++ lua/nvim-tree/node/root.lua | 12 ++--- 11 files changed, 185 insertions(+), 142 deletions(-) create mode 100644 lua/nvim-tree/classic.lua create mode 100644 lua/nvim-tree/node/link.lua diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua new file mode 100644 index 00000000000..323bda4e837 --- /dev/null +++ b/lua/nvim-tree/classic.lua @@ -0,0 +1,77 @@ +-- +-- classic +-- +-- Copyright (c) 2014, rxi +-- +-- This module is free software; you can redistribute it and/or modify it under +-- the terms of the MIT license. See LICENSE for details. +-- + + +local Object = {} +Object.__index = Object + + +function Object:new() +end + + +function Object:extend() + local cls = {} + for k, v in pairs(self) do + if k:find("__") == 1 then + cls[k] = v + end + end + cls.__index = cls + cls.super = self + setmetatable(cls, self) + return cls +end + + +function Object:implement(...) + for _, cls in pairs({...}) do + for k, v in pairs(cls) do + if self[k] == nil and type(v) == "function" then + self[k] = v + end + end + end +end + + +function Object:is(T) + local mt = getmetatable(self) + while mt do + if mt == T then + return true + end + mt = getmetatable(mt) + end + return false +end + + +---Return object if it is an instance of class, otherwise nil +---@generic T +---@param cls T +---@return T|nil +function Object:as(cls) + return self:is(cls) and self or nil +end + + +function Object:__tostring() + return "Object" +end + + +function Object:__call(...) + local obj = setmetatable({}, self) + obj:new(...) + return obj +end + + +return Object diff --git a/lua/nvim-tree/core.lua b/lua/nvim-tree/core.lua index 186b1ed74e1..4ff9cc78613 100644 --- a/lua/nvim-tree/core.lua +++ b/lua/nvim-tree/core.lua @@ -1,4 +1,5 @@ local events = require("nvim-tree.events") +local notify = require("nvim-tree.notify") local view = require("nvim-tree.view") local log = require("nvim-tree.log") @@ -15,7 +16,21 @@ function M.init(foldername) if TreeExplorer then TreeExplorer:destroy() end - TreeExplorer = require("nvim-tree.explorer"):create(foldername) + + local err, path + + if foldername then + path, err = vim.loop.fs_realpath(foldername) + else + path, err = vim.loop.cwd() + end + if path then + TreeExplorer = require("nvim-tree.explorer")(path) + else + notify.error(err) + TreeExplorer = nil + end + if not first_init_done then events._dispatch_ready() first_init_done = true diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index ecb042d2dd3..d32d0ecbc96 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -3,7 +3,6 @@ local buffers = require("nvim-tree.buffers") local core = require("nvim-tree.core") local git = require("nvim-tree.git") local log = require("nvim-tree.log") -local notify = require("nvim-tree.notify") local utils = require("nvim-tree.utils") local view = require("nvim-tree.view") local node_factory = require("nvim-tree.node.factory") @@ -36,51 +35,28 @@ local config ---@field sorters Sorter ---@field marks Marks ---@field clipboard Clipboard -local Explorer = RootNode:new() - ----Static factory method ----@param path string? ----@return Explorer? -function Explorer:create(path) - local err - - if path then - path, err = vim.loop.fs_realpath(path) - else - path, err = vim.loop.cwd() - end - if not path then - notify.error(err) - return nil - end - - ---@type Explorer - local explorer_placeholder = nil - - local o = RootNode:create(explorer_placeholder, path, "..", nil) - - o = self:new(o) - - o.explorer = o +local Explorer = RootNode:extend() - o.uid_explorer = vim.loop.hrtime() - o.augroup_id = vim.api.nvim_create_augroup("NvimTree_Explorer_" .. o.uid_explorer, {}) +---@param path string +function Explorer:new(path) + Explorer.super.new(self, self, path, "..", nil) - o.open = true - o.opts = config + self.uid_explorer = vim.loop.hrtime() + self.augroup_id = vim.api.nvim_create_augroup("NvimTree_Explorer_" .. self.uid_explorer, {}) - o.sorters = Sorters:create(config) - o.renderer = Renderer:new(config, o) - o.filters = Filters:new(config, o) - o.live_filter = LiveFilter:new(config, o) - o.marks = Marks:new(config, o) - o.clipboard = Clipboard:new(config, o) + self.open = true + self.opts = config - o:create_autocmds() + self.sorters = Sorters:create(config) + self.renderer = Renderer:new(config, self) + self.filters = Filters:new(config, self) + self.live_filter = LiveFilter:new(config, self) + self.marks = Marks:new(config, self) + self.clipboard = Clipboard:new(config, self) - o:_load(o) + self:create_autocmds() - return o + self:_load(self) end function Explorer:destroy() diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 8cfa3760a9e..54b95c42552 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -3,12 +3,9 @@ local utils = require("nvim-tree.utils") local DirectoryNode = require("nvim-tree.node.directory") ----@class (exact) DirectoryLinkNode: DirectoryNode ----@field link_to string absolute path ----@field private fs_stat_target uv.fs_stat.result -local DirectoryLinkNode = DirectoryNode:new() +---@class (exact) DirectoryLinkNode: DirectoryNode, LinkNode +local DirectoryLinkNode = DirectoryNode:extend() ----Static factory method ---@param explorer Explorer ---@param parent DirectoryNode ---@param absolute_path string @@ -16,21 +13,16 @@ local DirectoryLinkNode = DirectoryNode:new() ---@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) +function DirectoryLinkNode:new(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) + DirectoryLinkNode.super.new(self, explorer, parent, link_to, name, fs_stat) -- 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 + self.absolute_path = absolute_path - return o + self.type = "link" + self.link_to = link_to + self.fs_stat_target = fs_stat_target end function DirectoryLinkNode:destroy() diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index 3d87465aa04..e7db8a1e0b6 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -10,45 +10,38 @@ local Node = require("nvim-tree.node") ---@field open boolean ---@field hidden_stats table? -- Each field of this table is a key for source and value for count ---@field private watcher Watcher? -local DirectoryNode = Node:new() +local DirectoryNode = Node:extend() ----Static factory method ---@param explorer Explorer ---@param parent DirectoryNode? ---@param absolute_path string ---@param name string ---@param fs_stat uv.fs_stat.result|nil ----@return DirectoryNode -function DirectoryNode:create(explorer, parent, absolute_path, name, fs_stat) +function DirectoryNode:new(explorer, parent, absolute_path, name, fs_stat) + DirectoryNode.super.new(self) + local handle = vim.loop.fs_scandir(absolute_path) local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil or false - ---@type DirectoryNode - local o = { - type = "directory", - explorer = explorer, - absolute_path = absolute_path, - executable = false, - fs_stat = fs_stat, - git_status = nil, - hidden = false, - name = name, - parent = parent, - watcher = nil, - diag_status = nil, - is_dot = false, - - has_children = has_children, - group_next = nil, - nodes = {}, - open = false, - hidden_stats = nil, - } - o = self:new(o) - - o.watcher = require("nvim-tree.explorer.watch").create_watcher(o) - - return o + 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.group_next = nil + self.nodes = {} + self.open = false + self.hidden_stats = nil + + self.watcher = require("nvim-tree.explorer.watch").create_watcher(self) end function DirectoryNode:destroy() diff --git a/lua/nvim-tree/node/factory.lua b/lua/nvim-tree/node/factory.lua index ee0504fc807..94cd5d483dd 100644 --- a/lua/nvim-tree/node/factory.lua +++ b/lua/nvim-tree/node/factory.lua @@ -21,11 +21,11 @@ function M.create_node(explorer, parent, absolute_path, stat, name) if stat.type == "directory" then -- 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) + return DirectoryNode(explorer, parent, absolute_path, name, stat) end elseif stat.type == "file" then -- any file - return FileNode:create(explorer, parent, absolute_path, name, stat) + return FileNode(explorer, parent, absolute_path, name, stat) elseif stat.type == "link" then -- link target path and stat must resolve local link_to = vim.loop.fs_realpath(absolute_path) @@ -36,9 +36,9 @@ function M.create_node(explorer, parent, absolute_path, stat, name) -- 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) + return DirectoryLinkNode(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) + return FileLinkNode(explorer, parent, absolute_path, link_to, name, stat, link_to_stat) end end diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index 0c168a50a93..6c98d8eceaa 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -3,12 +3,9 @@ local utils = require("nvim-tree.utils") local FileNode = require("nvim-tree.node.file") ----@class (exact) FileLinkNode: FileNode ----@field link_to string absolute path ----@field private fs_stat_target uv.fs_stat.result -local FileLinkNode = FileNode:new() +---@class (exact) FileLinkNode: FileNode, LinkNode +local FileLinkNode = FileNode:extend() ----Static factory method ---@param explorer Explorer ---@param parent DirectoryNode ---@param absolute_path string @@ -16,17 +13,12 @@ local FileLinkNode = FileNode:new() ---@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) +function FileLinkNode:new(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target) + FileLinkNode.super.new(self, explorer, parent, absolute_path, name, fs_stat) - o = self:new(o) - - o.type = "link" - o.link_to = link_to - o.fs_stat_target = fs_stat_target - - return o + self.type = "link" + self.link_to = link_to + self.fs_stat_target = fs_stat_target end function FileLinkNode:destroy() diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index 18555fef26c..b281633ea09 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -15,35 +15,28 @@ local PICTURE_MAP = { ---@class (exact) FileNode: Node ---@field extension string -local FileNode = Node:new() +local FileNode = Node:extend() ----Static factory method ---@param explorer Explorer ---@param parent DirectoryNode ---@param absolute_path string ---@param name string ---@param fs_stat uv.fs_stat.result? ----@return FileNode -function FileNode:create(explorer, parent, absolute_path, name, fs_stat) - ---@type FileNode - local o = { - type = "file", - explorer = explorer, - absolute_path = absolute_path, - executable = utils.is_executable(absolute_path), - fs_stat = fs_stat, - git_status = nil, - hidden = false, - name = name, - parent = parent, - diag_status = nil, - is_dot = false, - - extension = string.match(name, ".?[^.]+%.(.*)") or "", - } - o = self:new(o) - - return o +function FileNode:new(explorer, parent, absolute_path, name, fs_stat) + FileNode.super.new(self) + + self.type = "file" + self.explorer = explorer + self.absolute_path = absolute_path + self.executable = utils.is_executable(absolute_path) + 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 "" end function FileNode:destroy() diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index 48bf783c421..e218914016c 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -1,8 +1,7 @@ -local Class = require("nvim-tree.class") +local Object = require("nvim-tree.classic") ---Abstract Node class. ----Uses the abstract factory pattern to instantiate child instances. ----@class (exact) Node: Class +---@class (exact) Node: Object ---@field type NODE_TYPE ---@field explorer Explorer ---@field absolute_path string @@ -14,7 +13,11 @@ local Class = require("nvim-tree.class") ---@field parent DirectoryNode? ---@field diag_status DiagStatus? ---@field private is_dot boolean cached is_dotfile -local Node = Class:new() +local Node = Object:extend() + +function Node:new() + self.is_dot = false +end function Node:destroy() end diff --git a/lua/nvim-tree/node/link.lua b/lua/nvim-tree/node/link.lua new file mode 100644 index 00000000000..9193e1c8b42 --- /dev/null +++ b/lua/nvim-tree/node/link.lua @@ -0,0 +1,8 @@ +local Object = require("nvim-tree.classic") + +---@class (exact) LinkNode: Object +---@field link_to string +---@field protected fs_stat_target uv.fs_stat.result +local LinkNode = Object:extend() + +return LinkNode diff --git a/lua/nvim-tree/node/root.lua b/lua/nvim-tree/node/root.lua index 0544a141a12..4a33e33c7cb 100644 --- a/lua/nvim-tree/node/root.lua +++ b/lua/nvim-tree/node/root.lua @@ -1,20 +1,14 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@class (exact) RootNode: DirectoryNode -local RootNode = DirectoryNode:new() +local RootNode = DirectoryNode:extend() ----Static factory method ---@param explorer Explorer ---@param absolute_path string ---@param name string ---@param fs_stat uv.fs_stat.result|nil ----@return RootNode -function RootNode:create(explorer, absolute_path, name, fs_stat) - local o = DirectoryNode:create(explorer, nil, absolute_path, name, fs_stat) - - o = self:new(o) - - return o +function RootNode:new(explorer, absolute_path, name, fs_stat) + RootNode.super.new(self, explorer, nil, absolute_path, name, fs_stat) end ---Root is never a dotfile From 359398db0548cfc8efe3d36fa76a4ffcb26f9740 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 4 Nov 2024 17:26:02 +1100 Subject: [PATCH 02/38] add mixins to classic --- lua/nvim-tree/classic.lua | 72 +++++++++++++++++---------- lua/nvim-tree/node/directory-link.lua | 2 + lua/nvim-tree/node/file-link.lua | 2 + 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua index 323bda4e837..25350e4dac6 100644 --- a/lua/nvim-tree/classic.lua +++ b/lua/nvim-tree/classic.lua @@ -6,16 +6,24 @@ -- This module is free software; you can redistribute it and/or modify it under -- the terms of the MIT license. See LICENSE for details. -- +-- https://github.com/rxi/classic +-- - +---@class (exact) Object +---@field super Object +---@field private implements table local Object = {} -Object.__index = Object - +Object.__index = Object ---@diagnostic disable-line: inject-field -function Object:new() +---Default constructor +function Object:new(...) end - +---Extend a class T +---super will be set to T +---@generic T +---@param self T +---@return T function Object:extend() local cls = {} for k, v in pairs(self) do @@ -29,22 +37,32 @@ function Object:extend() return cls end - -function Object:implement(...) - for _, cls in pairs({...}) do - for k, v in pairs(cls) do - if self[k] == nil and type(v) == "function" then - self[k] = v - end +---Implement the functions of a mixin +---Add the mixin to the implements table +---@param class Object +function Object:implement(class) + if not rawget(self, "implements") then + rawset(self, "implements", {}) + end + self.implements[class] = true + for k, v in pairs(class) do + if self[k] == nil and type(v) == "function" then + self[k] = v end end end - -function Object:is(T) +---Object is an instance of class or implements a mixin +---@generic T +---@param class T +---@return boolean +function Object:is(class) local mt = getmetatable(self) while mt do - if mt == T then + if mt == class then + return true + end + if mt.implements and mt.implements[class] then return true end mt = getmetatable(mt) @@ -52,26 +70,28 @@ function Object:is(T) return false end - ----Return object if it is an instance of class, otherwise nil +---Return object if :is otherwise nil ---@generic T ----@param cls T +---@param class T ---@return T|nil -function Object:as(cls) - return self:is(cls) and self or nil +function Object:as(class) + return self:is(class) and self or nil end - -function Object:__tostring() - return "Object" -end - - +---Constructor that invokes :new on a new instance +---@generic T +---@param self T +---@param ... any +---@return T function Object:__call(...) local obj = setmetatable({}, self) obj:new(...) return obj end +-- avoid unused param warnings in abstract methods +---@param ... any +function Object:nop(...) --luacheck: ignore 212 +end return Object diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 54b95c42552..4cdc337c1ed 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -2,9 +2,11 @@ local git_utils = require("nvim-tree.git.utils") local utils = require("nvim-tree.utils") local DirectoryNode = require("nvim-tree.node.directory") +local LinkNode = require("nvim-tree.node.link") ---@class (exact) DirectoryLinkNode: DirectoryNode, LinkNode local DirectoryLinkNode = DirectoryNode:extend() +DirectoryLinkNode:implement(LinkNode) ---@param explorer Explorer ---@param parent DirectoryNode diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index 6c98d8eceaa..b892c2a07ae 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -2,9 +2,11 @@ local git_utils = require("nvim-tree.git.utils") local utils = require("nvim-tree.utils") local FileNode = require("nvim-tree.node.file") +local LinkNode = require("nvim-tree.node.link") ---@class (exact) FileLinkNode: FileNode, LinkNode local FileLinkNode = FileNode:extend() +FileLinkNode:implement(LinkNode) ---@param explorer Explorer ---@param parent DirectoryNode From ac302ae16a6601b7c42fd40719b7696cfb34fe63 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Wed, 6 Nov 2024 15:53:39 +1100 Subject: [PATCH 03/38] typechecked optargs constructors for nodes --- lua/nvim-tree/classic.lua | 15 +++------ lua/nvim-tree/core.lua | 2 +- lua/nvim-tree/enum.lua | 8 ----- lua/nvim-tree/explorer/init.lua | 32 ++++++++++++++++--- lua/nvim-tree/node/directory-link.lua | 29 ++++++++--------- lua/nvim-tree/node/directory.lua | 46 +++++++++++---------------- lua/nvim-tree/node/factory.lua | 34 ++++++++++---------- lua/nvim-tree/node/file-link.lua | 20 +++++------- lua/nvim-tree/node/file.lua | 31 +++++++----------- lua/nvim-tree/node/init.lua | 24 ++++++++++++-- lua/nvim-tree/node/link.lua | 13 ++++++++ lua/nvim-tree/node/root.lua | 13 ++++---- 12 files changed, 141 insertions(+), 126 deletions(-) diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua index 25350e4dac6..1702db35205 100644 --- a/lua/nvim-tree/classic.lua +++ b/lua/nvim-tree/classic.lua @@ -19,11 +19,7 @@ Object.__index = Object ---@diagnostic disable-line: inject-field function Object:new(...) end ----Extend a class T ----super will be set to T ----@generic T ----@param self T ----@return T +---Extend a class, setting .super function Object:extend() local cls = {} for k, v in pairs(self) do @@ -38,10 +34,11 @@ function Object:extend() end ---Implement the functions of a mixin ----Add the mixin to the implements table +---Add the mixin to .implements ---@param class Object function Object:implement(class) if not rawget(self, "implements") then + -- set on the class itself instead of parents rawset(self, "implements", {}) end self.implements[class] = true @@ -78,11 +75,7 @@ function Object:as(class) return self:is(class) and self or nil end ----Constructor that invokes :new on a new instance ----@generic T ----@param self T ----@param ... any ----@return T +---Constructor to create instance, call :new and return function Object:__call(...) local obj = setmetatable({}, self) obj:new(...) diff --git a/lua/nvim-tree/core.lua b/lua/nvim-tree/core.lua index 4ff9cc78613..60d4a0a6f6a 100644 --- a/lua/nvim-tree/core.lua +++ b/lua/nvim-tree/core.lua @@ -25,7 +25,7 @@ function M.init(foldername) path, err = vim.loop.cwd() end if path then - TreeExplorer = require("nvim-tree.explorer")(path) + TreeExplorer = require("nvim-tree.explorer")({ path = path }) else notify.error(err) TreeExplorer = nil diff --git a/lua/nvim-tree/enum.lua b/lua/nvim-tree/enum.lua index a680c2b3fdc..9c50bc27638 100644 --- a/lua/nvim-tree/enum.lua +++ b/lua/nvim-tree/enum.lua @@ -1,13 +1,5 @@ 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_*" ---@enum HL_POSITION M.HL_POSITION = { diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index d32d0ecbc96..b10de76ea35 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -37,9 +37,19 @@ local config ---@field clipboard Clipboard local Explorer = RootNode:extend() ----@param path string -function Explorer:new(path) - Explorer.super.new(self, self, path, "..", nil) +---@class Explorer +---@overload fun(opts: ExplorerArgs): Explorer + +---@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.augroup_id = vim.api.nvim_create_augroup("NvimTree_Explorer_" .. self.uid_explorer, {}) @@ -222,7 +232,13 @@ function Explorer:reload(node, project) end 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 table.insert(node.nodes, 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 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 - 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 table.insert(node.nodes, child) nodes_by_path[child.absolute_path] = true diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 4cdc337c1ed..bde98102cd8 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -8,23 +8,23 @@ local LinkNode = require("nvim-tree.node.link") local DirectoryLinkNode = DirectoryNode:extend() DirectoryLinkNode:implement(LinkNode) ----@param explorer Explorer ----@param parent DirectoryNode ----@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 -function DirectoryLinkNode:new(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target) - -- create DirectoryNode with the target path for the watcher - DirectoryLinkNode.super.new(self, explorer, parent, link_to, name, fs_stat) +---@class DirectoryLinkNode +---@overload fun(opts: LinkNodeArgs): DirectoryLinkNode + +---@protected +---@param args LinkNodeArgs +function DirectoryLinkNode:new(args) + LinkNode.new(self, args) + + -- create DirectoryNode with watcher on link_to + 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 self.absolute_path = absolute_path - - self.type = "link" - self.link_to = link_to - self.fs_stat_target = fs_stat_target end function DirectoryLinkNode:destroy() @@ -76,7 +76,6 @@ end 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 diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index e7db8a1e0b6..02de70cb397 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -12,36 +12,26 @@ local Node = require("nvim-tree.node") ---@field private watcher Watcher? local DirectoryNode = Node:extend() ----@param explorer Explorer ----@param parent 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) +---@class DirectoryNode +---@overload fun(opts: NodeArgs): DirectoryNode + +---@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 - 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.group_next = nil - self.nodes = {} - self.open = false - self.hidden_stats = nil - - self.watcher = require("nvim-tree.explorer.watch").create_watcher(self) + self.type = "directory" + + self.has_children = has_children + self.group_next = nil + self.nodes = {} + self.open = false + self.hidden_stats = nil + + self.watcher = require("nvim-tree.explorer.watch").create_watcher(self) end function DirectoryNode:destroy() diff --git a/lua/nvim-tree/node/factory.lua b/lua/nvim-tree/node/factory.lua index 94cd5d483dd..adaaa5a740c 100644 --- a/lua/nvim-tree/node/factory.lua +++ b/lua/nvim-tree/node/factory.lua @@ -7,38 +7,38 @@ local Watcher = require("nvim-tree.watcher") local M = {} ---Factory function to create the appropriate Node ----@param explorer Explorer ----@param parent DirectoryNode ----@param absolute_path string ----@param stat uv.fs_stat.result? -- on nil stat return nil Node ----@param name string +---nil on invalid stat or invalid link target stat +---@param args NodeArgs ---@return Node? -function M.create_node(explorer, parent, absolute_path, stat, name) - if not stat then +function M.create(args) + if not args.fs_stat then return nil end - if stat.type == "directory" then + if args.fs_stat.type == "directory" then -- 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(explorer, parent, absolute_path, name, stat) + if vim.loop.fs_access(args.absolute_path, "R") and Watcher.is_fs_event_capable(args.absolute_path) then + return DirectoryNode(args) end - elseif stat.type == "file" then - -- any file - return FileNode(explorer, parent, absolute_path, name, stat) - elseif stat.type == "link" then + elseif args.fs_stat.type == "file" then + return FileNode(args) + elseif args.fs_stat.type == "link" then -- 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) if not link_to or not link_to_stat then return end + ---@cast args LinkNodeArgs + args.link_to = link_to + args.fs_stat_target = link_to_stat + -- choose directory or file if link_to_stat.type == "directory" then - return DirectoryLinkNode(explorer, parent, absolute_path, link_to, name, stat, link_to_stat) + return DirectoryLinkNode(args) else - return FileLinkNode(explorer, parent, absolute_path, link_to, name, stat, link_to_stat) + return FileLinkNode(args) end end diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index b892c2a07ae..14ff24071d1 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -8,19 +8,16 @@ local LinkNode = require("nvim-tree.node.link") local FileLinkNode = FileNode:extend() FileLinkNode:implement(LinkNode) ----@param explorer Explorer ----@param parent DirectoryNode ----@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 -function FileLinkNode:new(explorer, parent, absolute_path, link_to, name, fs_stat, fs_stat_target) - FileLinkNode.super.new(self, explorer, parent, absolute_path, name, fs_stat) +---@class FileLinkNode +---@overload fun(opts: LinkNodeArgs): FileLinkNode + +---@protected +---@param args LinkNodeArgs +function FileLinkNode:new(args) + LinkNode.new(self, args) + FileLinkNode.super.new(self, args) self.type = "link" - self.link_to = link_to - self.fs_stat_target = fs_stat_target end function FileLinkNode:destroy() @@ -65,7 +62,6 @@ end 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 diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index b281633ea09..6a4fc10a510 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -17,26 +17,17 @@ local PICTURE_MAP = { ---@field extension string local FileNode = Node:extend() ----@param explorer Explorer ----@param parent DirectoryNode ----@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" - self.explorer = explorer - self.absolute_path = absolute_path - self.executable = utils.is_executable(absolute_path) - 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 "" +---@class FileNode +---@overload fun(opts: NodeArgs): FileNode + +---@protected +---@param args NodeArgs +function FileNode:new(args) + FileNode.super.new(self, args) + + self.type = "file" + self.extension = string.match(args.name, ".?[^.]+%.(.*)") or "" + self.executable = utils.is_executable(args.absolute_path) end function FileNode:destroy() diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index e218914016c..51fa7c8df61 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -2,7 +2,7 @@ local Object = require("nvim-tree.classic") ---Abstract Node class. ---@class (exact) Node: Object ----@field type NODE_TYPE +---@field type "file" | "directory" | "link" uv.fs_stat.result.type ---@field explorer Explorer ---@field absolute_path string ---@field executable boolean @@ -15,8 +15,26 @@ local Object = require("nvim-tree.classic") ---@field private is_dot boolean cached is_dotfile local Node = Object:extend() -function Node:new() - self.is_dot = false +---@class (exact) NodeArgs +---@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 function Node:destroy() diff --git a/lua/nvim-tree/node/link.lua b/lua/nvim-tree/node/link.lua index 9193e1c8b42..c76bd17f615 100644 --- a/lua/nvim-tree/node/link.lua +++ b/lua/nvim-tree/node/link.lua @@ -5,4 +5,17 @@ local Object = require("nvim-tree.classic") ---@field protected fs_stat_target uv.fs_stat.result 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 diff --git a/lua/nvim-tree/node/root.lua b/lua/nvim-tree/node/root.lua index 4a33e33c7cb..dea9372a0b8 100644 --- a/lua/nvim-tree/node/root.lua +++ b/lua/nvim-tree/node/root.lua @@ -3,12 +3,13 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@class (exact) RootNode: DirectoryNode local RootNode = DirectoryNode:extend() ----@param explorer Explorer ----@param absolute_path string ----@param name string ----@param fs_stat uv.fs_stat.result|nil -function RootNode:new(explorer, absolute_path, name, fs_stat) - RootNode.super.new(self, explorer, nil, absolute_path, name, fs_stat) +---@class RootNode +---@overload fun(opts: NodeArgs): RootNode + +---@protected +---@param args NodeArgs +function RootNode:new(args) + RootNode.super.new(self, args) end ---Root is never a dotfile From a7db5b29a4b263de0d4c3c54f6e648579050324a Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Wed, 6 Nov 2024 16:36:14 +1100 Subject: [PATCH 04/38] typechecked optargs constructors for watcher and event --- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/explorer/watch.lua | 8 +- lua/nvim-tree/git/init.lua | 9 +- lua/nvim-tree/node/directory-link.lua | 2 +- lua/nvim-tree/node/directory.lua | 2 +- lua/nvim-tree/node/file-link.lua | 2 +- lua/nvim-tree/node/file.lua | 2 +- lua/nvim-tree/node/init.lua | 6 +- lua/nvim-tree/node/link.lua | 8 +- lua/nvim-tree/node/root.lua | 2 +- lua/nvim-tree/watcher.lua | 119 +++++++++++++++----------- 11 files changed, 94 insertions(+), 68 deletions(-) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index b10de76ea35..98cf92027bb 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -38,7 +38,7 @@ local config local Explorer = RootNode:extend() ---@class Explorer ----@overload fun(opts: ExplorerArgs): Explorer +---@overload fun(args: ExplorerArgs): Explorer ---@class (exact) ExplorerArgs ---@field path string diff --git a/lua/nvim-tree/explorer/watch.lua b/lua/nvim-tree/explorer/watch.lua index bd65ae53607..06eb429ba9d 100644 --- a/lua/nvim-tree/explorer/watch.lua +++ b/lua/nvim-tree/explorer/watch.lua @@ -83,8 +83,12 @@ function M.create_watcher(node) end M.uid = M.uid + 1 - return Watcher:create(path, nil, callback, { - context = "explorer:watch:" .. path .. ":" .. M.uid, + return Watcher:create({ + path = path, + callback = callback, + data = { + context = "explorer:watch:" .. path .. ":" .. M.uid + } }) end diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index 10354f85f30..8fe7dbae97c 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -298,8 +298,13 @@ function M.load_project(path) end local git_dir = vim.env.GIT_DIR or M._git_dirs_by_toplevel[toplevel] or utils.path_join({ toplevel, ".git" }) - watcher = Watcher:create(git_dir, WATCHED_FILES, callback, { - toplevel = toplevel, + watcher = Watcher:create({ + path = git_dir, + files = WATCHED_FILES, + callback = callback, + data = { + toplevel = toplevel, + } }) end diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index bde98102cd8..019f23ebdcb 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -9,7 +9,7 @@ local DirectoryLinkNode = DirectoryNode:extend() DirectoryLinkNode:implement(LinkNode) ---@class DirectoryLinkNode ----@overload fun(opts: LinkNodeArgs): DirectoryLinkNode +---@overload fun(args: LinkNodeArgs): DirectoryLinkNode ---@protected ---@param args LinkNodeArgs diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index 02de70cb397..95c536eea10 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -13,7 +13,7 @@ local Node = require("nvim-tree.node") local DirectoryNode = Node:extend() ---@class DirectoryNode ----@overload fun(opts: NodeArgs): DirectoryNode +---@overload fun(args: NodeArgs): DirectoryNode ---@protected ---@param args NodeArgs diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index 14ff24071d1..3c5571a29a2 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -9,7 +9,7 @@ local FileLinkNode = FileNode:extend() FileLinkNode:implement(LinkNode) ---@class FileLinkNode ----@overload fun(opts: LinkNodeArgs): FileLinkNode +---@overload fun(args: LinkNodeArgs): FileLinkNode ---@protected ---@param args LinkNodeArgs diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index 6a4fc10a510..a74a213a8eb 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -18,7 +18,7 @@ local PICTURE_MAP = { local FileNode = Node:extend() ---@class FileNode ----@overload fun(opts: NodeArgs): FileNode +---@overload fun(args: NodeArgs): FileNode ---@protected ---@param args NodeArgs diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index 51fa7c8df61..de53607e157 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -1,7 +1,7 @@ -local Object = require("nvim-tree.classic") +local Class = require("nvim-tree.classic") ---Abstract Node class. ----@class (exact) Node: Object +---@class (exact) Node: Class ---@field type "file" | "directory" | "link" uv.fs_stat.result.type ---@field explorer Explorer ---@field absolute_path string @@ -13,7 +13,7 @@ local Object = require("nvim-tree.classic") ---@field parent DirectoryNode? ---@field diag_status DiagStatus? ---@field private is_dot boolean cached is_dotfile -local Node = Object:extend() +local Node = Class:extend() ---@class (exact) NodeArgs ---@field explorer Explorer diff --git a/lua/nvim-tree/node/link.lua b/lua/nvim-tree/node/link.lua index c76bd17f615..35e36490ff9 100644 --- a/lua/nvim-tree/node/link.lua +++ b/lua/nvim-tree/node/link.lua @@ -1,9 +1,9 @@ -local Object = require("nvim-tree.classic") +local Class = require("nvim-tree.classic") ----@class (exact) LinkNode: Object +---@class (exact) LinkNode: Class ---@field link_to string ---@field protected fs_stat_target uv.fs_stat.result -local LinkNode = Object:extend() +local LinkNode = Class:extend() ---@class (exact) LinkNodeArgs: NodeArgs ---@field link_to string @@ -12,8 +12,6 @@ local LinkNode = Object:extend() ---@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 diff --git a/lua/nvim-tree/node/root.lua b/lua/nvim-tree/node/root.lua index dea9372a0b8..ec3c44c4a82 100644 --- a/lua/nvim-tree/node/root.lua +++ b/lua/nvim-tree/node/root.lua @@ -4,7 +4,7 @@ local DirectoryNode = require("nvim-tree.node.directory") local RootNode = DirectoryNode:extend() ---@class RootNode ----@overload fun(opts: NodeArgs): RootNode +---@overload fun(args: NodeArgs): RootNode ---@protected ---@param args NodeArgs diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index 0dfdbf0afde..d29d080bf7e 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -2,7 +2,7 @@ local notify = require("nvim-tree.notify") local log = require("nvim-tree.log") local utils = require("nvim-tree.utils") -local Class = require("nvim-tree.class") +local Class = require("nvim-tree.classic") local FS_EVENT_FLAGS = { -- inotify or equivalent will be used; fallback to stat has not yet been implemented @@ -15,36 +15,45 @@ local M = { config = {}, } +---Registry of all events +---@type Event[] +local events = {} + ---@class (exact) Event: Class ---@field destroyed boolean ---@field private path string ---@field private fs_event uv.uv_fs_event_t? ---@field private listeners function[] -local Event = Class:new() +local Event = Class:extend() ----Registry of all events ----@type Event[] -local events = {} +---@class Event +---@overload fun(args: EventArgs): Event + +---@class (exact) EventArgs +---@field path string + +---@private +---@param args EventArgs +function Event:new(args) + self.destroyed = false + self.path = args.path + self.fs_event = nil + self.listeners = {} +end ---Static factory method ---Creates and starts an Event ----@param path string ----@return Event|nil -function Event:create(path) - log.line("watcher", "Event:create '%s'", path) - - ---@type Event - local o = { - destroyed = false, - path = path, - fs_event = nil, - listeners = {}, - } - o = self:new(o) - - if o:start() then - events[path] = o - return o +---nil on failure to start +---@param args EventArgs +---@return Event? +function Event:create(args) + log.line("watcher", "Event:create '%s'", args.path) + + local event = Event(args) + + if event:start() then + events[event.path] = event + return event else return nil end @@ -128,8 +137,10 @@ function Event:destroy(message) events[self.path] = nil end ----Static factory method ----Creates and starts a Watcher +---Registry of all watchers +---@type Watcher[] +local watchers = {} + ---@class (exact) Watcher: Class ---@field data table user data ---@field destroyed boolean @@ -138,43 +149,51 @@ end ---@field private files string[]? ---@field private listener fun(filename: string)? ---@field private event Event -local Watcher = Class:new() - ----Registry of all watchers ----@type Watcher[] -local watchers = {} +local Watcher = Class:extend() + +---@class Watcher +---@overload fun(args: WatcherArgs): Watcher + +---@class (exact) WatcherArgs +---@field path string +---@field files string[]|nil +---@field callback fun(watcher: Watcher) +---@field data table? user data + +---@private +---@param args WatcherArgs +function Watcher:new(args) + self.data = args.data + self.destroyed = false + self.path = args.path + self.callback = args.callback + self.files = args.files + self.listener = nil + self.event = args.event +end ---Static factory method ----@param path string ----@param files string[]|nil ----@param callback fun(watcher: Watcher) ----@param data table user data +---Creates and starts a Watcher +---nil on failure to create Event +---@param args WatcherArgs ---@return Watcher|nil -function Watcher:create(path, files, callback, data) - log.line("watcher", "Watcher:create '%s' %s", path, vim.inspect(files)) +function Watcher:create(args) + log.line("watcher", "Watcher:create '%s' %s", args.path, vim.inspect(args.files)) - local event = events[path] or Event:create(path) + local event = events[args.path] or Event:create({ path = args.path }) if not event then return nil end - ---@type Watcher - local o = { - data = data, - destroyed = false, - path = path, - callback = callback, - files = files, - listener = nil, - event = event, - } - o = self:new(o) + local watcher = Watcher(args) + + watcher.event = event - o:start() + watcher:start() - table.insert(watchers, o) + table.insert(watchers, watcher) - return o + return watcher end function Watcher:start() From eab49e3d6d11a54ad72af7c2fe319576eada09a6 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Wed, 6 Nov 2024 16:39:47 +1100 Subject: [PATCH 05/38] luacheck --- lua/nvim-tree/classic.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua index 1702db35205..ec0e38f961b 100644 --- a/lua/nvim-tree/classic.lua +++ b/lua/nvim-tree/classic.lua @@ -16,7 +16,7 @@ local Object = {} Object.__index = Object ---@diagnostic disable-line: inject-field ---Default constructor -function Object:new(...) +function Object:new(...) --luacheck: ignore 212 end ---Extend a class, setting .super From b2f7b9a8760c96f54812309af0c1ff7252b6f50c Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Wed, 6 Nov 2024 16:53:01 +1100 Subject: [PATCH 06/38] typechecked optargs constructors for GitRunner --- lua/nvim-tree/git/init.lua | 10 ++--- lua/nvim-tree/git/runner.lua | 71 +++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index 8fe7dbae97c..50981b961e1 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -128,8 +128,8 @@ function M.reload_project(toplevel, path, callback) return end - ---@type GitRunnerOpts - local runner_opts = { + ---@type GitRunnerArgs + local args = { toplevel = toplevel, path = path, list_untracked = git_utils.should_show_untracked(toplevel), @@ -139,14 +139,14 @@ function M.reload_project(toplevel, path, callback) if callback then ---@param path_xy GitPathXY - runner_opts.callback = function(path_xy) + args.callback = function(path_xy) reload_git_project(toplevel, path, project, path_xy) callback() end - GitRunner:run(runner_opts) + GitRunner:run(args) else -- TODO #1974 use callback once async/await is available - reload_git_project(toplevel, path, project, GitRunner:run(runner_opts)) + reload_git_project(toplevel, path, project, GitRunner:run(args)) end end diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index 13b57383cf1..4716e893d02 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -2,9 +2,18 @@ local log = require("nvim-tree.log") local utils = require("nvim-tree.utils") local notify = require("nvim-tree.notify") -local Class = require("nvim-tree.class") +local Class = require("nvim-tree.classic") ----@class (exact) GitRunnerOpts +---@class (exact) GitRunner: Class +---@field private args GitRunnerArgs +---@field private path_xy GitPathXY +---@field private rc integer? -- -1 indicates timeout +local GitRunner = Class:extend() + +---@class GitRunner +---@overload fun(args: GitRunnerArgs): GitRunner + +---@class (exact) GitRunnerArgs ---@field toplevel string absolute path ---@field path string? absolute path ---@field list_untracked boolean @@ -12,15 +21,16 @@ local Class = require("nvim-tree.class") ---@field timeout integer ---@field callback fun(path_xy: GitPathXY)? ----@class (exact) GitRunner: Class ----@field private opts GitRunnerOpts ----@field private path_xy GitPathXY ----@field private rc integer? -- -1 indicates timeout -local GitRunner = Class:new() - local timeouts = 0 local MAX_TIMEOUTS = 5 +---@private +---@param args GitRunnerArgs +function GitRunner:new(args) + self.args = args + self.path_xy = {} +end + ---@private ---@param status string ---@param path string|nil @@ -34,7 +44,7 @@ function GitRunner:parse_status_output(status, path) path = path:gsub("/", "\\") end if #status > 0 and #path > 0 then - self.path_xy[utils.path_remove_trailing(utils.path_join({ self.opts.toplevel, path }))] = status + self.path_xy[utils.path_remove_trailing(utils.path_join({ self.args.toplevel, path }))] = status end end @@ -81,11 +91,11 @@ end ---@param stderr_handle uv.uv_pipe_t ---@return uv.spawn.options function GitRunner:get_spawn_options(stdout_handle, stderr_handle) - local untracked = self.opts.list_untracked and "-u" or nil - local ignored = (self.opts.list_untracked and self.opts.list_ignored) and "--ignored=matching" or "--ignored=no" + local untracked = self.args.list_untracked and "-u" or nil + local ignored = (self.args.list_untracked and self.args.list_ignored) and "--ignored=matching" or "--ignored=no" return { - args = { "--no-optional-locks", "status", "--porcelain=v1", "-z", ignored, untracked, self.opts.path }, - cwd = self.opts.toplevel, + args = { "--no-optional-locks", "status", "--porcelain=v1", "-z", ignored, untracked, self.args.path }, + cwd = self.args.toplevel, stdio = { nil, stdout_handle, stderr_handle }, } end @@ -139,7 +149,7 @@ function GitRunner:run_git_job(callback) end local spawn_options = self:get_spawn_options(stdout, stderr) - log.line("git", "running job with timeout %dms", self.opts.timeout) + log.line("git", "running job with timeout %dms", self.args.timeout) log.line("git", "git %s", table.concat(utils.array_remove_nils(spawn_options.args), " ")) handle, pid = vim.loop.spawn( @@ -151,7 +161,7 @@ function GitRunner:run_git_job(callback) ) timer:start( - self.opts.timeout, + self.args.timeout, 0, vim.schedule_wrap(function() on_finish(-1) @@ -191,17 +201,17 @@ end ---@private function GitRunner:finalise() if self.rc == -1 then - log.line("git", "job timed out %s %s", self.opts.toplevel, self.opts.path) + log.line("git", "job timed out %s %s", self.args.toplevel, self.args.path) timeouts = timeouts + 1 if timeouts == MAX_TIMEOUTS then notify.warn(string.format("%d git jobs have timed out after git.timeout %dms, disabling git integration.", timeouts, - self.opts.timeout)) + self.args.timeout)) require("nvim-tree.git").disable_git_integration() end elseif self.rc ~= 0 then - log.line("git", "job fail rc %d %s %s", self.rc, self.opts.toplevel, self.opts.path) + log.line("git", "job fail rc %d %s %s", self.rc, self.args.toplevel, self.args.path) else - log.line("git", "job success %s %s", self.opts.toplevel, self.opts.path) + log.line("git", "job success %s %s", self.args.toplevel, self.args.path) end end @@ -209,17 +219,17 @@ end ---@private ---@return GitPathXY? function GitRunner:execute() - local async = self.opts.callback ~= nil - local profile = log.profile_start("git %s job %s %s", async and "async" or "sync", self.opts.toplevel, self.opts.path) + local async = self.args.callback ~= nil + local profile = log.profile_start("git %s job %s %s", async and "async" or "sync", self.args.toplevel, self.args.path) - if async and self.opts.callback then + if async and self.args.callback then -- async, always call back self:run_git_job(function() log.profile_end(profile) self:finalise() - self.opts.callback(self.path_xy) + self.args.callback(self.path_xy) end) else -- sync, maybe call back @@ -230,8 +240,8 @@ function GitRunner:execute() self:finalise() - if self.opts.callback then - self.opts.callback(self.path_xy) + if self.args.callback then + self.args.callback(self.path_xy) else return self.path_xy end @@ -240,15 +250,10 @@ end ---Static method to run a git process, which will be killed if it takes more than timeout ---Return nil when callback present ----@param opts GitRunnerOpts +---@param args GitRunnerArgs ---@return GitPathXY? -function GitRunner:run(opts) - ---@type GitRunner - local runner = { - opts = opts, - path_xy = {}, - } - runner = GitRunner:new(runner) +function GitRunner:run(args) + local runner = GitRunner(args) return runner:execute() end From 692fff774563775b111fc0f832727ad452058376 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Wed, 6 Nov 2024 17:07:08 +1100 Subject: [PATCH 07/38] typechecked optargs constructors for Sorter --- lua/nvim-tree/class.lua | 14 ++++---- lua/nvim-tree/classic.lua | 32 +++++++++---------- lua/nvim-tree/explorer/init.lua | 4 +-- .../explorer/{sorters.lua => sorter.lua} | 27 +++++++--------- 4 files changed, 37 insertions(+), 40 deletions(-) rename lua/nvim-tree/explorer/{sorters.lua => sorter.lua} (94%) diff --git a/lua/nvim-tree/class.lua b/lua/nvim-tree/class.lua index 33b0b5bd33d..147694d07d8 100644 --- a/lua/nvim-tree/class.lua +++ b/lua/nvim-tree/class.lua @@ -1,12 +1,12 @@ ---Generic class, useful for inheritence. ----@class (exact) Class -local Class = {} +---@class (exact) ClassOld +local ClassOld = {} ---@generic T ---@param self T ---@param o T|nil ---@return T -function Class:new(o) +function ClassOld:new(o) o = o or {} setmetatable(o, self) @@ -20,7 +20,7 @@ end ---@generic T ---@param class T ---@return boolean -function Class:is(class) +function ClassOld:is(class) local mt = getmetatable(self) while mt do if mt == class then @@ -35,13 +35,13 @@ end ---@generic T ---@param class T ---@return T|nil -function Class:as(class) +function ClassOld:as(class) return self:is(class) and self or nil end -- avoid unused param warnings in abstract methods ---@param ... any -function Class:nop(...) --luacheck: ignore 212 +function ClassOld:nop(...) --luacheck: ignore 212 end -return Class +return ClassOld diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua index ec0e38f961b..be098abe1ea 100644 --- a/lua/nvim-tree/classic.lua +++ b/lua/nvim-tree/classic.lua @@ -9,18 +9,18 @@ -- https://github.com/rxi/classic -- ----@class (exact) Object ----@field super Object ----@field private implements table -local Object = {} -Object.__index = Object ---@diagnostic disable-line: inject-field +---@class (exact) Class +---@field super Class +---@field private implements table +local Class = {} +Class.__index = Class ---@diagnostic disable-line: inject-field ---Default constructor -function Object:new(...) --luacheck: ignore 212 +function Class:new(...) --luacheck: ignore 212 end ---Extend a class, setting .super -function Object:extend() +function Class:extend() local cls = {} for k, v in pairs(self) do if k:find("__") == 1 then @@ -35,14 +35,14 @@ end ---Implement the functions of a mixin ---Add the mixin to .implements ----@param class Object -function Object:implement(class) +---@param mixin Class +function Class:implement(mixin) if not rawget(self, "implements") then -- set on the class itself instead of parents rawset(self, "implements", {}) end - self.implements[class] = true - for k, v in pairs(class) do + self.implements[mixin] = true + for k, v in pairs(mixin) do if self[k] == nil and type(v) == "function" then self[k] = v end @@ -53,7 +53,7 @@ end ---@generic T ---@param class T ---@return boolean -function Object:is(class) +function Class:is(class) local mt = getmetatable(self) while mt do if mt == class then @@ -71,12 +71,12 @@ end ---@generic T ---@param class T ---@return T|nil -function Object:as(class) +function Class:as(class) return self:is(class) and self or nil end ---Constructor to create instance, call :new and return -function Object:__call(...) +function Class:__call(...) local obj = setmetatable({}, self) obj:new(...) return obj @@ -84,7 +84,7 @@ end -- avoid unused param warnings in abstract methods ---@param ... any -function Object:nop(...) --luacheck: ignore 212 +function Class:nop(...) --luacheck: ignore 212 end -return Object +return Class diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 98cf92027bb..718fef458dc 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -17,7 +17,7 @@ local NodeIterator = require("nvim-tree.iterators.node-iterator") local Filters = require("nvim-tree.explorer.filters") local Marks = require("nvim-tree.marks") local LiveFilter = require("nvim-tree.explorer.live-filter") -local Sorters = require("nvim-tree.explorer.sorters") +local Sorter = require("nvim-tree.explorer.sorter") local Clipboard = require("nvim-tree.actions.fs.clipboard") local Renderer = require("nvim-tree.renderer") @@ -57,7 +57,7 @@ function Explorer:new(args) self.open = true self.opts = config - self.sorters = Sorters:create(config) + self.sorters = Sorter(config) self.renderer = Renderer:new(config, self) self.filters = Filters:new(config, self) self.live_filter = LiveFilter:new(config, self) diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorter.lua similarity index 94% rename from lua/nvim-tree/explorer/sorters.lua rename to lua/nvim-tree/explorer/sorter.lua index 15ed921da05..550d3b33e88 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -1,4 +1,4 @@ -local Class = require("nvim-tree.class") +local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") local C = {} @@ -12,23 +12,20 @@ local C = {} ---@field cfg SorterCfg ---@field user fun(nodes: Node[])? ---@field pre string? -local Sorter = Class:new() +local Sorter = Class:extend() + +---@class Sorter +---@overload fun(opts: table): Sorter ---@param opts table user options ----@return Sorter -function Sorter:create(opts) - ---@type Sorter - local o = { - cfg = vim.deepcopy(opts.sort), - } - o = self:new(o) - - if type(o.cfg.sorter) == "function" then - o.user = o.cfg.sorter --[[@as fun(nodes: Node[])]] - elseif type(o.cfg.sorter) == "string" then - o.pre = o.cfg.sorter --[[@as string]] +function Sorter:new(opts) + self.cfg = vim.deepcopy(opts.sort) + + if type(self.cfg.sorter) == "function" then + self.user = self.cfg.sorter --[[@as fun(nodes: Node[])]] + elseif type(self.cfg.sorter) == "string" then + self.pre = self.cfg.sorter --[[@as string]] end - return o end --- Predefined comparator, defaulting to name From 4da6f4baaa2fb9b18ce23ff3dbd96a06a287dced Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Wed, 6 Nov 2024 17:50:52 +1100 Subject: [PATCH 08/38] typechecked optargs constructors for decorators, WIP --- lua/nvim-tree/renderer/builder.lua | 24 ++++----- .../renderer/decorator/bookmarks.lua | 41 +++++++--------- lua/nvim-tree/renderer/decorator/copied.lua | 28 +++++------ lua/nvim-tree/renderer/decorator/cut.lua | 27 +++++----- lua/nvim-tree/renderer/decorator/git.lua | 49 +++++++++---------- lua/nvim-tree/renderer/decorator/init.lua | 21 +++++++- 6 files changed, 97 insertions(+), 93 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 37359269822..66fab5cd0c6 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -7,11 +7,11 @@ local DirectoryNode = require("nvim-tree.node.directory") local DecoratorBookmarks = require("nvim-tree.renderer.decorator.bookmarks") local DecoratorCopied = require("nvim-tree.renderer.decorator.copied") local DecoratorCut = require("nvim-tree.renderer.decorator.cut") -local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics") +-- local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics") local DecoratorGit = require("nvim-tree.renderer.decorator.git") -local DecoratorModified = require("nvim-tree.renderer.decorator.modified") -local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden") -local DecoratorOpened = require("nvim-tree.renderer.decorator.opened") +-- local DecoratorModified = require("nvim-tree.renderer.decorator.modified") +-- local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden") +-- local DecoratorOpened = require("nvim-tree.renderer.decorator.opened") local pad = require("nvim-tree.renderer.components.padding") @@ -61,14 +61,14 @@ function Builder:new(opts, explorer) 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), + DecoratorCut({ explorer = explorer }), + DecoratorCopied({ explorer = explorer }), + -- DecoratorDiagnostics({ explorer = explorer }), + DecoratorBookmarks({ explorer = explorer }), + -- DecoratorModified({ explorer = explorer }), + -- DecoratorHidden({ explorer = explorer }), + -- DecoratorOpened({ explorer = explorer }), + DecoratorGit({ explorer = explorer }) }, hidden_display = Builder:setup_hidden_display_function(opts), } diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index 3c188721c0c..cfed5fd9a19 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -5,31 +5,28 @@ local Decorator = require("nvim-tree.renderer.decorator") ---@class (exact) DecoratorBookmarks: Decorator ---@field icon HighlightedString? -local DecoratorBookmarks = Decorator:new() - ----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) - - if opts.renderer.icons.show.bookmarks then - o.icon = { - str = opts.renderer.icons.glyphs.bookmark, +local DecoratorBookmarks = Decorator:extend() + +---@class DecoratorBookmarks +---@overload fun(explorer: DecoratorArgs): DecoratorBookmarks + +---@private +---@param args DecoratorArgs +function DecoratorBookmarks:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_bookmarks] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.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 diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua index 3d760a97a55..0022f71a910 100644 --- a/lua/nvim-tree/renderer/decorator/copied.lua +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -4,24 +4,20 @@ 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 +---@private +---@param args DecoratorArgs +function DecoratorCopied:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_clipboard] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT.none, + }) end ---Copied highlight: renderer.highlight_clipboard and node is copied diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua index 45428969e7e..66a72c56d2d 100644 --- a/lua/nvim-tree/renderer/decorator/cut.lua +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -4,23 +4,20 @@ 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 +---@private +---@param args DecoratorArgs +function DecoratorCut:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_clipboard] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT.none, + }) end ---Cut highlight: renderer.highlight_clipboard and node is cut diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index 4a543bcd30a..fefa0aa41e9 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -20,40 +20,37 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@field folder_hl_by_xy table? ---@field icons_by_status GitIconsByStatus? ---@field icons_by_xy GitIconsByXY? -local DecoratorGit = Decorator:new() - ----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) - - if not o.enabled then - return o +local DecoratorGit = Decorator:extend() + +---@class DecoratorGit +---@overload fun(explorer: DecoratorArgs): DecoratorGit + +---@private +---@param args DecoratorArgs +function DecoratorGit:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = args.explorer.opts.git.enable, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_git] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.git_placement] or ICON_PLACEMENT.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.hl_pos ~= HL_POSITION.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 diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 44f05f8e23e..d59bc9881b8 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -1,4 +1,4 @@ -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 @@ -10,7 +10,24 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT ---@field protected enabled boolean ---@field protected hl_pos HL_POSITION ---@field protected icon_placement ICON_PLACEMENT -local Decorator = Class:new() +local Decorator = Class:extend() + +---@class (exact) DecoratorArgs +---@field explorer Explorer + +---@class (exact) AbstractDecoratorArgs: DecoratorArgs +---@field enabled boolean +---@field hl_pos HL_POSITION +---@field icon_placement ICON_PLACEMENT + +---@protected +---@param args AbstractDecoratorArgs +function Decorator:new(args) + self.explorer = args.explorer + self.enabled = args.enabled + self.hl_pos = args.hl_pos + self.icon_placement = args.icon_placement +end ---Maybe highlight groups ---@param node Node From b092915f17a6088265253d2e5637ea5f9e616aa4 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 10:48:28 +1100 Subject: [PATCH 09/38] typechecked optargs constructors for decorators, WIP --- lua/nvim-tree/renderer/builder.lua | 4 +- .../renderer/components/diagnostics.lua | 95 ------------------- lua/nvim-tree/renderer/components/init.lua | 2 - .../renderer/decorator/diagnostics.lua | 47 +++++---- 4 files changed, 24 insertions(+), 124 deletions(-) delete mode 100644 lua/nvim-tree/renderer/components/diagnostics.lua diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 66fab5cd0c6..48aefed2ee6 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -7,7 +7,7 @@ local DirectoryNode = require("nvim-tree.node.directory") local DecoratorBookmarks = require("nvim-tree.renderer.decorator.bookmarks") local DecoratorCopied = require("nvim-tree.renderer.decorator.copied") local DecoratorCut = require("nvim-tree.renderer.decorator.cut") --- local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics") +local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics") local DecoratorGit = require("nvim-tree.renderer.decorator.git") -- local DecoratorModified = require("nvim-tree.renderer.decorator.modified") -- local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden") @@ -63,7 +63,7 @@ function Builder:new(opts, explorer) -- priority order DecoratorCut({ explorer = explorer }), DecoratorCopied({ explorer = explorer }), - -- DecoratorDiagnostics({ explorer = explorer }), + DecoratorDiagnostics({ explorer = explorer }), DecoratorBookmarks({ explorer = explorer }), -- DecoratorModified({ explorer = explorer }), -- DecoratorHidden({ explorer = explorer }), diff --git a/lua/nvim-tree/renderer/components/diagnostics.lua b/lua/nvim-tree/renderer/components/diagnostics.lua deleted file mode 100644 index e91873e07ca..00000000000 --- a/lua/nvim-tree/renderer/components/diagnostics.lua +++ /dev/null @@ -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 diff --git a/lua/nvim-tree/renderer/components/init.lua b/lua/nvim-tree/renderer/components/init.lua index 776350b4b77..748bf889497 100644 --- a/lua/nvim-tree/renderer/components/init.lua +++ b/lua/nvim-tree/renderer/components/init.lua @@ -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) diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index ee495ca674e..e3239293450 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -35,38 +35,35 @@ local ICON_KEYS = { ---@class (exact) DecoratorDiagnostics: Decorator ---@field icons HighlightedString[]? -local DecoratorDiagnostics = Decorator:new() - ----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) - - if not o.enabled then - return o +local DecoratorDiagnostics = Decorator:extend() + +---@class DecoratorDiagnostics +---@overload fun(explorer: DecoratorArgs): DecoratorDiagnostics + +---@private +---@param args DecoratorArgs +function DecoratorDiagnostics:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_diagnostics] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.diagnostics_placement] or ICON_PLACEMENT.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 From f6392cf88a8b1b5bc8aa859cbb5ddf6711126e3f Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 10:57:53 +1100 Subject: [PATCH 10/38] typechecked optargs constructors for decorators --- lua/nvim-tree/renderer/builder.lua | 12 ++--- lua/nvim-tree/renderer/decorator/hidden.lua | 41 ++++++++-------- lua/nvim-tree/renderer/decorator/modified.lua | 47 +++++++++---------- lua/nvim-tree/renderer/decorator/opened.lua | 27 +++++------ 4 files changed, 59 insertions(+), 68 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 48aefed2ee6..a88b48dbe59 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -9,9 +9,9 @@ local DecoratorCopied = require("nvim-tree.renderer.decorator.copied") local DecoratorCut = require("nvim-tree.renderer.decorator.cut") local DecoratorDiagnostics = require("nvim-tree.renderer.decorator.diagnostics") local DecoratorGit = require("nvim-tree.renderer.decorator.git") --- local DecoratorModified = require("nvim-tree.renderer.decorator.modified") --- local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden") --- local DecoratorOpened = require("nvim-tree.renderer.decorator.opened") +local DecoratorModified = require("nvim-tree.renderer.decorator.modified") +local DecoratorHidden = require("nvim-tree.renderer.decorator.hidden") +local DecoratorOpened = require("nvim-tree.renderer.decorator.opened") local pad = require("nvim-tree.renderer.components.padding") @@ -65,9 +65,9 @@ function Builder:new(opts, explorer) DecoratorCopied({ explorer = explorer }), DecoratorDiagnostics({ explorer = explorer }), DecoratorBookmarks({ explorer = explorer }), - -- DecoratorModified({ explorer = explorer }), - -- DecoratorHidden({ explorer = explorer }), - -- DecoratorOpened({ explorer = explorer }), + DecoratorModified({ explorer = explorer }), + DecoratorHidden({ explorer = explorer }), + DecoratorOpened({ explorer = explorer }), DecoratorGit({ explorer = explorer }) }, hidden_display = Builder:setup_hidden_display_function(opts), diff --git a/lua/nvim-tree/renderer/decorator/hidden.lua b/lua/nvim-tree/renderer/decorator/hidden.lua index 7c62f51af5f..333056cf33b 100644 --- a/lua/nvim-tree/renderer/decorator/hidden.lua +++ b/lua/nvim-tree/renderer/decorator/hidden.lua @@ -6,31 +6,28 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@class (exact) DecoratorHidden: Decorator ---@field icon HighlightedString? -local DecoratorHidden = Decorator:new() - ----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) - - if opts.renderer.icons.show.hidden then - o.icon = { - str = opts.renderer.icons.glyphs.hidden, +local DecoratorHidden = Decorator:extend() + +---@class DecoratorHidden +---@overload fun(explorer: DecoratorArgs): DecoratorHidden + +---@private +---@param args DecoratorArgs +function DecoratorHidden:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_hidden] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.hidden_placement] or ICON_PLACEMENT.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). diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index 2126379cd14..ccab9ead1c2 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -7,36 +7,33 @@ 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() - ----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) - - if not o.enabled then - return o +---@field icon HighlightedString? +local DecoratorModified = Decorator:extend() + +---@class DecoratorModified +---@overload fun(explorer: DecoratorArgs): DecoratorModified + +---@private +---@param args DecoratorArgs +function DecoratorModified:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_modified] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.modified_placement] or ICON_PLACEMENT.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 diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index cb1843311c7..17ab88ce3ce 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -7,23 +7,20 @@ 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 +---@private +---@param args DecoratorArgs +function DecoratorOpened:new(args) + Decorator.new(self, { + explorer = args.explorer, + enabled = true, + hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_opened_files] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT.none, + }) end ---Opened highlight: renderer.highlight_opened_files and node has an open buffer From 5d7e5434f39a3c7200f83a06e2b99763d3cd528c Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 11:01:38 +1100 Subject: [PATCH 11/38] remove class --- lua/nvim-tree/class.lua | 47 ----------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 lua/nvim-tree/class.lua diff --git a/lua/nvim-tree/class.lua b/lua/nvim-tree/class.lua deleted file mode 100644 index 147694d07d8..00000000000 --- a/lua/nvim-tree/class.lua +++ /dev/null @@ -1,47 +0,0 @@ ----Generic class, useful for inheritence. ----@class (exact) ClassOld -local ClassOld = {} - ----@generic T ----@param self T ----@param o T|nil ----@return T -function ClassOld:new(o) - o = o or {} - - setmetatable(o, self) - self.__index = self ---@diagnostic disable-line: inject-field - - return o -end - ----Object is an instance of class ----This will start with the lowest class and loop over all the superclasses. ----@generic T ----@param class T ----@return boolean -function ClassOld:is(class) - local mt = getmetatable(self) - while mt do - if mt == class then - return true - end - mt = getmetatable(mt) - end - return false -end - ----Return object if it is an instance of class, otherwise nil ----@generic T ----@param class T ----@return T|nil -function ClassOld:as(class) - return self:is(class) and self or nil -end - --- avoid unused param warnings in abstract methods ----@param ... any -function ClassOld:nop(...) --luacheck: ignore 212 -end - -return ClassOld From 9af0dc487d731e7a66a86bc7d01cf476bee2925d Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 11:36:42 +1100 Subject: [PATCH 12/38] replace enums with named maps --- lua/nvim-tree/enum.lua | 19 ---------- .../renderer/decorator/bookmarks.lua | 9 ++--- lua/nvim-tree/renderer/decorator/copied.lua | 9 ++--- lua/nvim-tree/renderer/decorator/cut.lua | 9 ++--- .../renderer/decorator/diagnostics.lua | 9 ++--- lua/nvim-tree/renderer/decorator/git.lua | 15 ++++---- lua/nvim-tree/renderer/decorator/hidden.lua | 9 ++--- lua/nvim-tree/renderer/decorator/init.lua | 36 +++++++++---------- lua/nvim-tree/renderer/decorator/modified.lua | 9 ++--- lua/nvim-tree/renderer/decorator/opened.lua | 9 ++--- lua/nvim-tree/view.lua | 4 --- 11 files changed, 45 insertions(+), 92 deletions(-) diff --git a/lua/nvim-tree/enum.lua b/lua/nvim-tree/enum.lua index 9c50bc27638..e99082282ac 100644 --- a/lua/nvim-tree/enum.lua +++ b/lua/nvim-tree/enum.lua @@ -1,24 +1,5 @@ local M = {} ----Setup options for "highlight_*" ----@enum HL_POSITION -M.HL_POSITION = { - none = 0, - icon = 1, - name = 2, - all = 4, -} - ----Setup options for "*_placement" ----@enum ICON_PLACEMENT -M.ICON_PLACEMENT = { - none = 0, - signcolumn = 1, - before = 2, - after = 3, - right_align = 4, -} - ---Reason for filter in filter.lua ---@enum FILTER_REASON M.FILTER_REASON = { diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index cfed5fd9a19..e0d6e05c7bd 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -1,6 +1,3 @@ -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 @@ -16,8 +13,8 @@ function DecoratorBookmarks:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_bookmarks] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.none, + 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 @@ -42,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 diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua index 0022f71a910..90f4a21bf05 100644 --- a/lua/nvim-tree/renderer/decorator/copied.lua +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -1,6 +1,3 @@ -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 @@ -15,8 +12,8 @@ function DecoratorCopied:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_clipboard] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT.none, + hl_pos = args.explorer.opts.renderer.highlight_clipboard or "none", + icon_placement = "none", }) end @@ -24,7 +21,7 @@ end ---@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 diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua index 66a72c56d2d..0e1b699460e 100644 --- a/lua/nvim-tree/renderer/decorator/cut.lua +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -1,6 +1,3 @@ -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 @@ -15,8 +12,8 @@ function DecoratorCut:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_clipboard] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT.none, + hl_pos = args.explorer.opts.renderer.highlight_clipboard or "none", + icon_placement = "none", }) end @@ -24,7 +21,7 @@ end ---@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 diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index e3239293450..cbf7f43979c 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -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") @@ -46,8 +43,8 @@ function DecoratorDiagnostics:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_diagnostics] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.diagnostics_placement] or ICON_PLACEMENT.none, + 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 @@ -84,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 diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index fefa0aa41e9..1c03e5a8367 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -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") @@ -31,15 +28,15 @@ function DecoratorGit:new(args) Decorator.new(self, { explorer = args.explorer, enabled = args.explorer.opts.git.enable, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_git] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.git_placement] or ICON_PLACEMENT.none, + 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 self.hl_pos ~= HL_POSITION.none then + if self.range ~= "none" then self:build_file_folder_hl_by_xy() end @@ -162,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 @@ -194,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 @@ -208,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 diff --git a/lua/nvim-tree/renderer/decorator/hidden.lua b/lua/nvim-tree/renderer/decorator/hidden.lua index 333056cf33b..e79fcb2f71c 100644 --- a/lua/nvim-tree/renderer/decorator/hidden.lua +++ b/lua/nvim-tree/renderer/decorator/hidden.lua @@ -1,6 +1,3 @@ -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") @@ -17,8 +14,8 @@ function DecoratorHidden:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_hidden] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.hidden_placement] or ICON_PLACEMENT.none, + 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 @@ -43,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 diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index d59bc9881b8..f83b92dcae4 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -1,15 +1,15 @@ 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 +---@field protected range DecoratorRange +---@field protected icon_placement DecoratorIconPlacement local Decorator = Class:extend() ---@class (exact) DecoratorArgs @@ -17,15 +17,15 @@ local Decorator = Class:extend() ---@class (exact) AbstractDecoratorArgs: DecoratorArgs ---@field enabled boolean ----@field hl_pos HL_POSITION ----@field icon_placement ICON_PLACEMENT +---@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.hl_pos = args.hl_pos + self.range = args.hl_pos self.icon_placement = args.icon_placement end @@ -36,13 +36,13 @@ end 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 @@ -54,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 @@ -64,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 @@ -126,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 diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index ccab9ead1c2..b13dd45dcfd 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -1,8 +1,5 @@ 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") @@ -19,8 +16,8 @@ function DecoratorModified:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_modified] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT[args.explorer.opts.renderer.icons.modified_placement] or ICON_PLACEMENT.none, + 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 @@ -49,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 diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index 17ab88ce3ce..c42c82359ba 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -1,8 +1,5 @@ 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 @@ -18,8 +15,8 @@ function DecoratorOpened:new(args) Decorator.new(self, { explorer = args.explorer, enabled = true, - hl_pos = HL_POSITION[args.explorer.opts.renderer.highlight_opened_files] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT.none, + hl_pos = args.explorer.opts.renderer.highlight_opened_files or "none", + icon_placement = "none", }) end @@ -27,7 +24,7 @@ end ---@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 diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index e76bf089058..1f90fb426c0 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -152,7 +152,6 @@ local function set_window_options_and_buffer() pcall(vim.api.nvim_command, "buffer " .. M.get_bufnr()) if vim.fn.has("nvim-0.10") == 1 then - local eventignore = vim.api.nvim_get_option_value("eventignore", {}) vim.api.nvim_set_option_value("eventignore", "all", {}) @@ -161,9 +160,7 @@ local function set_window_options_and_buffer() end vim.api.nvim_set_option_value("eventignore", eventignore, {}) - else - local eventignore = vim.api.nvim_get_option("eventignore") ---@diagnostic disable-line: deprecated vim.api.nvim_set_option("eventignore", "all") ---@diagnostic disable-line: deprecated @@ -172,7 +169,6 @@ local function set_window_options_and_buffer() end vim.api.nvim_set_option("eventignore", eventignore) ---@diagnostic disable-line: deprecated - end end From 5ef0616ff1ee57ff343f9458b96652e9db2cf1e4 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 11:48:08 +1100 Subject: [PATCH 13/38] Renderer and Builder use classic, tidy opts --- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/renderer/builder.lua | 79 ++++++++++++++---------------- lua/nvim-tree/renderer/init.lua | 36 ++++++-------- 3 files changed, 53 insertions(+), 64 deletions(-) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 718fef458dc..0a8c36b6cf7 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -58,7 +58,7 @@ function Explorer:new(args) self.opts = config self.sorters = Sorter(config) - self.renderer = Renderer:new(config, self) + self.renderer = Renderer({ explorer = self }) self.filters = Filters:new(config, self) self.live_filter = LiveFilter:new(config, self) self.marks = Marks:new(config, self) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index a88b48dbe59..2e2f15947f5 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -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") @@ -33,50 +34,44 @@ local pad = require("nvim-tree.renderer.components.padding") ---@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 combined group names ---@field private markers boolean[] indent markers ---@field private decorators Decorator[] ---@field private hidden_display fun(node: Node): string|nil -local Builder = {} - ----@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({ explorer = explorer }), - DecoratorCopied({ explorer = explorer }), - DecoratorDiagnostics({ explorer = explorer }), - DecoratorBookmarks({ explorer = explorer }), - DecoratorModified({ explorer = explorer }), - DecoratorHidden({ explorer = explorer }), - DecoratorOpened({ explorer = explorer }), - DecoratorGit({ explorer = explorer }) - }, - hidden_display = Builder:setup_hidden_display_function(opts), +local Builder = Class:extend() + +---@class Builder +---@overload fun(args: BuilderArgs): Builder + +---@class (exact) BuilderArgs +---@field explorer Explorer + +---@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(args.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 diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index f61c4be4e5f..69db3ca2757 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -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,19 @@ 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 = {} - ----@param opts table user options ----@param explorer Explorer ----@return Renderer -function Renderer:new(opts, explorer) - ---@type Renderer - local o = { - opts = opts, - explorer = explorer, - } - - setmetatable(o, self) - self.__index = self - - return o +---@class (exact) Renderer: Class +---@field explorer Explorer +local Renderer = Class:extend() + +---@class Renderer +---@overload fun(args: RendererArgs): Renderer + +---@class (exact) RendererArgs +---@field explorer Explorer + +---@param args RendererArgs +function Renderer:new(args) + self.explorer = args.explorer end ---@private @@ -106,7 +100,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) From 2c172cf0376e9a5c6d4b6215c830111e2b2c4383 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 11:51:31 +1100 Subject: [PATCH 14/38] LiveFilter uses classic, tidy opts --- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/explorer/live-filter.lua | 32 +++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 0a8c36b6cf7..36c3391e4af 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -60,7 +60,7 @@ function Explorer:new(args) self.sorters = Sorter(config) self.renderer = Renderer({ explorer = self }) self.filters = Filters:new(config, self) - self.live_filter = LiveFilter:new(config, self) + self.live_filter = LiveFilter({ explorer = self }) self.marks = Marks:new(config, self) self.clipboard = Clipboard:new(config, self) diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index 9861195c4ba..30170f40f65 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -1,29 +1,29 @@ local view = require("nvim-tree.view") local utils = require("nvim-tree.utils") +local Class = require("nvim-tree.classic") local Iterator = require("nvim-tree.iterators.node-iterator") local DirectoryNode = require("nvim-tree.node.directory") ----@class LiveFilter +---@class (exact) LiveFilter: Class ---@field explorer Explorer ---@field prefix string ---@field always_show_folders boolean ---@field filter string -local LiveFilter = {} - ----@param opts table ----@param explorer Explorer ----@return LiveFilter -function LiveFilter:new(opts, explorer) - local o = { - explorer = explorer, - prefix = opts.live_filter.prefix, - always_show_folders = opts.live_filter.always_show_folders, - filter = nil, - } - setmetatable(o, self) - self.__index = self - return o +local LiveFilter = Class:extend() + +---@class LiveFilter +---@overload fun(args: LiveFilterArgs): LiveFilter + +---@class (exact) LiveFilterArgs +---@field explorer Explorer + +---@param args LiveFilterArgs +function LiveFilter:new(args) + self.explorer = args.explorer + self.prefix = args.explorer.opts.live_filter.prefix + self.always_show_folders = args.explorer.opts.live_filter.always_show_folders + self.filter = nil end ---@param node_ Node? From 67cc06e6513d389914127c5e0a175e67ad576cba Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 12:00:44 +1100 Subject: [PATCH 15/38] Filter uses classic, tidy opts --- lua/nvim-tree/explorer/filters.lua | 57 +++++++++++++------------- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/explorer/live-filter.lua | 4 +- lua/nvim-tree/renderer/builder.lua | 2 +- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 8de9f15076b..0fb44ec8102 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -1,47 +1,48 @@ local utils = require("nvim-tree.utils") local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON ----@class Filters to handle all opts.filters and related API +local Class = require("nvim-tree.classic") + +---@class (exact) Filters: Class ---@field config table hydrated user opts.filters ---@field private explorer Explorer ---@field private exclude_list string[] filters.exclude ----@field private ignore_list string[] filters.custom string table +---@field private ignore_list table filters.custom string table ---@field private custom_function (fun(absolute_path: string): boolean)|nil filters.custom function -local Filters = {} - ----@param opts table user options ----@param explorer Explorer ----@return Filters -function Filters:new(opts, explorer) - local o = { - explorer = explorer, - ignore_list = {}, - exclude_list = opts.filters.exclude, - custom_function = nil, - config = { - enable = opts.filters.enable, - filter_custom = true, - filter_dotfiles = opts.filters.dotfiles, - filter_git_ignored = opts.filters.git_ignored, - filter_git_clean = opts.filters.git_clean, - filter_no_buffer = opts.filters.no_buffer, - filter_no_bookmark = opts.filters.no_bookmark, - }, +local Filters = Class:extend() + +---@class Filters +---@overload fun(args: FiltersArgs): Filters + +---@class (exact) FiltersArgs +---@field explorer Explorer + +---@param args FiltersArgs +function Filters:new(args) + self.explorer = args.explorer + self.ignore_list = {} + self.exclude_list = self.explorer.opts.filters.exclude + self.custom_function = nil + self.config = { + enable = self.explorer.opts.filters.enable, + filter_custom = true, + filter_dotfiles = self.explorer.opts.filters.dotfiles, + filter_git_ignored = self.explorer.opts.filters.git_ignored, + filter_git_clean = self.explorer.opts.filters.git_clean, + filter_no_buffer = self.explorer.opts.filters.no_buffer, + filter_no_bookmark = self.explorer.opts.filters.no_bookmark, } - local custom_filter = opts.filters.custom + local custom_filter = self.explorer.opts.filters.custom if type(custom_filter) == "function" then - o.custom_function = custom_filter + self.custom_function = custom_filter else if custom_filter and #custom_filter > 0 then for _, filter_name in pairs(custom_filter) do - o.ignore_list[filter_name] = true + self.ignore_list[filter_name] = true end end end - setmetatable(o, self) - self.__index = self - return o end ---@param path string diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 36c3391e4af..23434fab096 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -59,7 +59,7 @@ function Explorer:new(args) self.sorters = Sorter(config) self.renderer = Renderer({ explorer = self }) - self.filters = Filters:new(config, self) + self.filters = Filters({ explorer = self }) self.live_filter = LiveFilter({ explorer = self }) self.marks = Marks:new(config, self) self.clipboard = Clipboard:new(config, self) diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index 30170f40f65..c59b0c0bffd 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -21,8 +21,8 @@ local LiveFilter = Class:extend() ---@param args LiveFilterArgs function LiveFilter:new(args) self.explorer = args.explorer - self.prefix = args.explorer.opts.live_filter.prefix - self.always_show_folders = args.explorer.opts.live_filter.always_show_folders + self.prefix = self.explorer.opts.live_filter.prefix + self.always_show_folders = self.explorer.opts.live_filter.always_show_folders self.filter = nil end diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 2e2f15947f5..29b3d337447 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -71,7 +71,7 @@ function Builder:new(args) DecoratorOpened({ explorer = args.explorer }), DecoratorGit({ explorer = args.explorer }) } - self.hidden_display = Builder:setup_hidden_display_function(args.explorer.opts) + self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts) end ---Insert ranged highlight groups into self.highlights From 84d5f0a9856a534bbd54037d63f1780258853e5c Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 12:39:45 +1100 Subject: [PATCH 16/38] add FilterTypes named map --- .../actions/tree/modifiers/toggles.lua | 14 +++---- lua/nvim-tree/explorer/filters.lua | 40 ++++++++++--------- lua/nvim-tree/explorer/init.lua | 4 +- lua/nvim-tree/explorer/live-filter.lua | 2 +- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/lua/nvim-tree/actions/tree/modifiers/toggles.lua b/lua/nvim-tree/actions/tree/modifiers/toggles.lua index 8a468a959f2..73f687cd74d 100644 --- a/lua/nvim-tree/actions/tree/modifiers/toggles.lua +++ b/lua/nvim-tree/actions/tree/modifiers/toggles.lua @@ -22,43 +22,43 @@ end ---@param explorer Explorer local function custom(explorer) - explorer.filters.config.filter_custom = not explorer.filters.config.filter_custom + explorer.filters.states.custom = not explorer.filters.states.custom reload(explorer) end ---@param explorer Explorer local function git_ignored(explorer) - explorer.filters.config.filter_git_ignored = not explorer.filters.config.filter_git_ignored + explorer.filters.states.git_ignored = not explorer.filters.states.git_ignored reload(explorer) end ---@param explorer Explorer local function git_clean(explorer) - explorer.filters.config.filter_git_clean = not explorer.filters.config.filter_git_clean + explorer.filters.states.git_clean = not explorer.filters.states.git_clean reload(explorer) end ---@param explorer Explorer local function no_buffer(explorer) - explorer.filters.config.filter_no_buffer = not explorer.filters.config.filter_no_buffer + explorer.filters.states.no_buffer = not explorer.filters.states.no_buffer reload(explorer) end ---@param explorer Explorer local function no_bookmark(explorer) - explorer.filters.config.filter_no_bookmark = not explorer.filters.config.filter_no_bookmark + explorer.filters.states.no_bookmark = not explorer.filters.states.no_bookmark reload(explorer) end ---@param explorer Explorer local function dotfiles(explorer) - explorer.filters.config.filter_dotfiles = not explorer.filters.config.filter_dotfiles + explorer.filters.states.dotfiles = not explorer.filters.states.dotfiles reload(explorer) end ---@param explorer Explorer local function enable(explorer) - explorer.filters.config.enable = not explorer.filters.config.enable + explorer.filters.enabled = not explorer.filters.enabled reload(explorer) end diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 0fb44ec8102..78c7234ae29 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -3,8 +3,11 @@ local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON local Class = require("nvim-tree.classic") +---@alias FilterTypes "custom" | "dotfiles" | "git_ignored" | "git_clean" | "no_buffer" | "no_bookmark" + ---@class (exact) Filters: Class ----@field config table hydrated user opts.filters +---@field enabled boolean +---@field states table ---@field private explorer Explorer ---@field private exclude_list string[] filters.exclude ---@field private ignore_list table filters.custom string table @@ -23,14 +26,15 @@ function Filters:new(args) self.ignore_list = {} self.exclude_list = self.explorer.opts.filters.exclude self.custom_function = nil - self.config = { - enable = self.explorer.opts.filters.enable, - filter_custom = true, - filter_dotfiles = self.explorer.opts.filters.dotfiles, - filter_git_ignored = self.explorer.opts.filters.git_ignored, - filter_git_clean = self.explorer.opts.filters.git_clean, - filter_no_buffer = self.explorer.opts.filters.no_buffer, - filter_no_bookmark = self.explorer.opts.filters.no_bookmark, + + self.enabled = self.explorer.opts.filters.enable + self.states = { + custom = true, + dotfiles = self.explorer.opts.filters.dotfiles, + git_ignored = self.explorer.opts.filters.git_ignored, + git_clean = self.explorer.opts.filters.git_clean, + no_buffer = self.explorer.opts.filters.no_buffer, + no_bookmark = self.explorer.opts.filters.no_bookmark, } local custom_filter = self.explorer.opts.filters.custom @@ -71,12 +75,12 @@ local function git(self, path, project) xy = xy or project.dirs.indirect[path] and project.dirs.indirect[path][1] -- filter ignored; overrides clean as they are effectively dirty - if self.config.filter_git_ignored and xy == "!!" then + if self.states.git_ignored and xy == "!!" then return true end -- filter clean - if self.config.filter_git_clean and not xy then + if self.states.git_clean and not xy then return true end @@ -88,7 +92,7 @@ end ---@param bufinfo table vim.fn.getbufinfo { buflisted = 1 } ---@return boolean local function buf(self, path, bufinfo) - if not self.config.filter_no_buffer or type(bufinfo) ~= "table" then + if not self.states.no_buffer or type(bufinfo) ~= "table" then return false end @@ -105,7 +109,7 @@ end ---@param path string ---@return boolean local function dotfile(self, path) - return self.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "." + return self.states.dotfiles and utils.path_basename(path):sub(1, 1) == "." end ---Bookmark is present @@ -114,7 +118,7 @@ end ---@param bookmarks table path, filetype table of bookmarked files ---@return boolean local function bookmark(self, path, path_type, bookmarks) - if not self.config.filter_no_bookmark then + if not self.states.no_bookmark then return false end -- if bookmark is empty, we should see a empty filetree @@ -149,7 +153,7 @@ end ---@param path string ---@return boolean local function custom(self, path) - if not self.config.filter_custom then + if not self.states.custom then return false end @@ -191,7 +195,7 @@ function Filters:prepare(project) bookmarks = {}, } - if self.config.filter_no_buffer then + if self.states.no_buffer then status.bufinfo = vim.fn.getbufinfo({ buflisted = 1 }) end @@ -211,7 +215,7 @@ end ---@param status table from prepare ---@return boolean function Filters:should_filter(path, fs_stat, status) - if not self.config.enable then + if not self.enabled then return false end @@ -233,7 +237,7 @@ end ---@param status table from prepare ---@return FILTER_REASON function Filters:should_filter_as_reason(path, fs_stat, status) - if not self.config.enable then + if not self.enabled then return FILTER_REASON.none end diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 23434fab096..90ace32cc88 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -100,7 +100,7 @@ function Explorer:create_autocmds() vim.api.nvim_create_autocmd("BufReadPost", { group = self.augroup_id, callback = function(data) - if (self.filters.config.filter_no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then + if (self.filters.states.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function() self:reload_explorer() end) @@ -112,7 +112,7 @@ function Explorer:create_autocmds() vim.api.nvim_create_autocmd("BufUnload", { group = self.augroup_id, callback = function(data) - if (self.filters.config.filter_no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then + if (self.filters.states.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function() self:reload_explorer() end) diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index c59b0c0bffd..89c994edefa 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -81,7 +81,7 @@ end ---@param node Node ---@return boolean local function matches(self, node) - if not self.explorer.filters.config.enable then + if not self.explorer.filters.enabled then return true end From db90f5953245ec4f723d5e1a70e1918adc26f8ac Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 13:31:02 +1100 Subject: [PATCH 17/38] move toggles into filters --- lua/nvim-tree/actions/tree/modifiers/init.lua | 1 - .../actions/tree/modifiers/toggles.lua | 73 ------------------- lua/nvim-tree/api.lua | 30 ++++++-- lua/nvim-tree/explorer/filters.lua | 20 ++++- 4 files changed, 41 insertions(+), 83 deletions(-) delete mode 100644 lua/nvim-tree/actions/tree/modifiers/toggles.lua diff --git a/lua/nvim-tree/actions/tree/modifiers/init.lua b/lua/nvim-tree/actions/tree/modifiers/init.lua index 717b8d7e8f0..f3ce27fc616 100644 --- a/lua/nvim-tree/actions/tree/modifiers/init.lua +++ b/lua/nvim-tree/actions/tree/modifiers/init.lua @@ -2,7 +2,6 @@ local M = {} M.collapse_all = require("nvim-tree.actions.tree.modifiers.collapse-all") M.expand_all = require("nvim-tree.actions.tree.modifiers.expand-all") -M.toggles = require("nvim-tree.actions.tree.modifiers.toggles") function M.setup(opts) M.expand_all.setup(opts) diff --git a/lua/nvim-tree/actions/tree/modifiers/toggles.lua b/lua/nvim-tree/actions/tree/modifiers/toggles.lua deleted file mode 100644 index 73f687cd74d..00000000000 --- a/lua/nvim-tree/actions/tree/modifiers/toggles.lua +++ /dev/null @@ -1,73 +0,0 @@ -local utils = require("nvim-tree.utils") -local core = require("nvim-tree.core") -local M = {} - ----@param explorer Explorer -local function reload(explorer) - local node = explorer:get_node_at_cursor() - explorer:reload_explorer() - if node then - utils.focus_node_or_parent(node) - end -end - -local function wrap_explorer(fn) - return function(...) - local explorer = core.get_explorer() - if explorer then - return fn(explorer, ...) - end - end -end - ----@param explorer Explorer -local function custom(explorer) - explorer.filters.states.custom = not explorer.filters.states.custom - reload(explorer) -end - ----@param explorer Explorer -local function git_ignored(explorer) - explorer.filters.states.git_ignored = not explorer.filters.states.git_ignored - reload(explorer) -end - ----@param explorer Explorer -local function git_clean(explorer) - explorer.filters.states.git_clean = not explorer.filters.states.git_clean - reload(explorer) -end - ----@param explorer Explorer -local function no_buffer(explorer) - explorer.filters.states.no_buffer = not explorer.filters.states.no_buffer - reload(explorer) -end - ----@param explorer Explorer -local function no_bookmark(explorer) - explorer.filters.states.no_bookmark = not explorer.filters.states.no_bookmark - reload(explorer) -end - ----@param explorer Explorer -local function dotfiles(explorer) - explorer.filters.states.dotfiles = not explorer.filters.states.dotfiles - reload(explorer) -end - ----@param explorer Explorer -local function enable(explorer) - explorer.filters.enabled = not explorer.filters.enabled - reload(explorer) -end - -M.custom = wrap_explorer(custom) -M.git_ignored = wrap_explorer(git_ignored) -M.git_clean = wrap_explorer(git_clean) -M.no_buffer = wrap_explorer(no_buffer) -M.no_bookmark = wrap_explorer(no_bookmark) -M.dotfiles = wrap_explorer(dotfiles) -M.enable = wrap_explorer(enable) - -return M diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index 85762656a1d..31fcf2199d6 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -89,6 +89,22 @@ local function wrap_node_or_nil(fn) end end +---Invoke a member's method on the singleton explorer. +---Print error when setup not called. +---@param explorer_member string explorer member name +---@param member_method string method name to invoke on member +---@param ... any passed to method +---@return fun(...): any +local function wrap_explorer_member_args(explorer_member, member_method, ...) + local method_args = ... + return wrap(function(...) + local explorer = core.get_explorer() + if explorer then + return explorer[explorer_member][member_method](explorer[explorer_member], method_args, ...) + end + end) +end + ---Invoke a member's method on the singleton explorer. ---Print error when setup not called. ---@param explorer_member string explorer member name @@ -165,13 +181,13 @@ Api.tree.find_file = wrap(actions.tree.find_file.fn) Api.tree.search_node = wrap(actions.finders.search_node.fn) Api.tree.collapse_all = wrap(actions.tree.modifiers.collapse_all.fn) Api.tree.expand_all = wrap_node(actions.tree.modifiers.expand_all.fn) -Api.tree.toggle_enable_filters = wrap(actions.tree.modifiers.toggles.enable) -Api.tree.toggle_gitignore_filter = wrap(actions.tree.modifiers.toggles.git_ignored) -Api.tree.toggle_git_clean_filter = wrap(actions.tree.modifiers.toggles.git_clean) -Api.tree.toggle_no_buffer_filter = wrap(actions.tree.modifiers.toggles.no_buffer) -Api.tree.toggle_custom_filter = wrap(actions.tree.modifiers.toggles.custom) -Api.tree.toggle_hidden_filter = wrap(actions.tree.modifiers.toggles.dotfiles) -Api.tree.toggle_no_bookmark_filter = wrap(actions.tree.modifiers.toggles.no_bookmark) +Api.tree.toggle_enable_filters = wrap_explorer_member("filters", "toggle") +Api.tree.toggle_gitignore_filter = wrap_explorer_member_args("filters", "toggle", "git_ignored") +Api.tree.toggle_git_clean_filter = wrap_explorer_member_args("filters", "toggle", "git_clean") +Api.tree.toggle_no_buffer_filter = wrap_explorer_member_args("filters", "toggle", "no_buffer") +Api.tree.toggle_custom_filter = wrap_explorer_member_args("filters", "toggle", "custom") +Api.tree.toggle_hidden_filter = wrap_explorer_member_args("filters", "toggle", "dotfiles") +Api.tree.toggle_no_bookmark_filter = wrap_explorer_member_args("filters", "toggle", "no_bookmark") Api.tree.toggle_help = wrap(help.toggle) Api.tree.is_tree_buf = wrap(utils.is_nvim_tree_buf) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 78c7234ae29..fc540666b1a 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -3,11 +3,11 @@ local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON local Class = require("nvim-tree.classic") ----@alias FilterTypes "custom" | "dotfiles" | "git_ignored" | "git_clean" | "no_buffer" | "no_bookmark" +---@alias FilterType "custom" | "dotfiles" | "git_ignored" | "git_clean" | "no_buffer" | "no_bookmark" ---@class (exact) Filters: Class ---@field enabled boolean ----@field states table +---@field states table ---@field private explorer Explorer ---@field private exclude_list string[] filters.exclude ---@field private ignore_list table filters.custom string table @@ -260,4 +260,20 @@ function Filters:should_filter_as_reason(path, fs_stat, status) end end +---Toggle a type and refresh +---@param type FilterType? nil to disable all +function Filters:toggle(type) + if not type or self.states[type] == nil then + self.enabled = not self.enabled + else + self.states[type] = not self.states[type] + end + + local node = self.explorer:get_node_at_cursor() + self.explorer:reload_explorer() + if node then + utils.focus_node_or_parent(node) + end +end + return Filters From ef7184118cea40450b1daa5ec7e860fedb24b196 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 13:50:45 +1100 Subject: [PATCH 18/38] Marks uses classic, tidy opts --- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/marks/init.lua | 39 ++++++++++++++------------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 90ace32cc88..c07e3f5857e 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -61,7 +61,7 @@ function Explorer:new(args) self.renderer = Renderer({ explorer = self }) self.filters = Filters({ explorer = self }) self.live_filter = LiveFilter({ explorer = self }) - self.marks = Marks:new(config, self) + self.marks = Marks({ explorer = self }) self.clipboard = Clipboard:new(config, self) self:create_autocmds() diff --git a/lua/nvim-tree/marks/init.lua b/lua/nvim-tree/marks/init.lua index ddeb5cc9200..8c569e5f395 100644 --- a/lua/nvim-tree/marks/init.lua +++ b/lua/nvim-tree/marks/init.lua @@ -8,37 +8,32 @@ local rename_file = require("nvim-tree.actions.fs.rename-file") local trash = require("nvim-tree.actions.fs.trash") local utils = require("nvim-tree.utils") +local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") ----@class Marks ----@field config table hydrated user opts.filters +---@class (exact) Marks: Class ---@field private explorer Explorer ---@field private marks table by absolute path -local Marks = {} - ----@return Marks ----@param opts table user options ----@param explorer Explorer -function Marks:new(opts, explorer) - local o = { - explorer = explorer, - config = { - ui = opts.ui, - filesystem_watchers = opts.filesystem_watchers, - }, - marks = {}, - } +local Marks = Class:extend() + +---@class Marks +---@overload fun(args: MarksArgs): Marks - setmetatable(o, self) - self.__index = self - return o +---@class (exact) MarksArgs +---@field explorer Explorer + +---@param args MarksArgs +function Marks:new(args) + self.explorer = args.explorer + + self.marks = {} end ---Clear all marks and reload if watchers disabled ---@private function Marks:clear_reload() self:clear() - if not self.config.filesystem_watchers.enable then + if not self.explorer.opts.filesystem_watchers.enable then self.explorer:reload_explorer() end end @@ -100,7 +95,7 @@ function Marks:bulk_delete() self:clear_reload() end - if self.config.ui.confirm.remove then + if self.explorer.opts.ui.confirm.remove then local prompt_select = "Remove bookmarked ?" local prompt_input = prompt_select .. " y/N: " lib.prompt(prompt_input, prompt_select, { "", "y" }, { "No", "Yes" }, "nvimtree_bulk_delete", function(item_short) @@ -129,7 +124,7 @@ function Marks:bulk_trash() self:clear_reload() end - if self.config.ui.confirm.trash then + if self.explorer.opts.ui.confirm.trash then local prompt_select = "Trash bookmarked ?" local prompt_input = prompt_select .. " y/N: " lib.prompt(prompt_input, prompt_select, { "", "y" }, { "No", "Yes" }, "nvimtree_bulk_trash", function(item_short) From 1faa8a1762e3f4e08323b82a429e1ed474c0e0fb Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 13:53:48 +1100 Subject: [PATCH 19/38] Sorter uses classic, tidy opts --- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/explorer/sorter.lua | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index c07e3f5857e..624bbb21bcd 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -57,7 +57,7 @@ function Explorer:new(args) self.open = true self.opts = config - self.sorters = Sorter(config) + self.sorters = Sorter({ explorer = self }) self.renderer = Renderer({ explorer = self }) self.filters = Filters({ explorer = self }) self.live_filter = LiveFilter({ explorer = self }) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index 550d3b33e88..9eb34ece1d9 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -3,28 +3,31 @@ local DirectoryNode = require("nvim-tree.node.directory") local C = {} ----@class (exact) SorterCfg +---@class (exact) SorterState ---@field sorter string|fun(nodes: Node[]) ---@field folders_first boolean ---@field files_first boolean ---@class (exact) Sorter: Class ----@field cfg SorterCfg +---@field state SorterState ---@field user fun(nodes: Node[])? ---@field pre string? local Sorter = Class:extend() ---@class Sorter ----@overload fun(opts: table): Sorter +---@overload fun(args: SorterArgs): Sorter ----@param opts table user options -function Sorter:new(opts) - self.cfg = vim.deepcopy(opts.sort) +---@class (exact) SorterArgs +---@field explorer Explorer - if type(self.cfg.sorter) == "function" then - self.user = self.cfg.sorter --[[@as fun(nodes: Node[])]] - elseif type(self.cfg.sorter) == "string" then - self.pre = self.cfg.sorter --[[@as string]] +---@param args SorterArgs +function Sorter:new(args) + self.state = vim.deepcopy(args.explorer.opts.sort) + + if type(self.state.sorter) == "function" then + self.user = self.state.sorter --[[@as fun(nodes: Node[])]] + elseif type(self.state.sorter) == "string" then + self.pre = self.state.sorter --[[@as string]] end end @@ -33,7 +36,7 @@ end ---@return fun(a: Node, b: Node): boolean function Sorter:get_comparator(sorter) return function(a, b) - return (C[sorter] or C.name)(a, b, self.cfg) + return (C[sorter] or C.name)(a, b, self.state) end end @@ -54,7 +57,7 @@ end ---Evaluate `sort.folders_first` and `sort.files_first` ---@param a Node ---@param b Node ----@param cfg SorterCfg +---@param cfg SorterState ---@return boolean|nil local function folders_or_files_first(a, b, cfg) if not (cfg.folders_first or cfg.files_first) then @@ -178,7 +181,7 @@ end ---@param a Node ---@param b Node ---@param ignorecase boolean|nil ----@param cfg SorterCfg +---@param cfg SorterState ---@return boolean local function node_comparator_name_ignorecase_or_not(a, b, ignorecase, cfg) if not (a and b) then From 92fa49051f293583e52a920124eb9c702575d5c1 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 15:26:32 +1100 Subject: [PATCH 20/38] Clipboard uses classic, tidy opts --- lua/nvim-tree/actions/fs/clipboard.lua | 44 ++++++++++++-------------- lua/nvim-tree/explorer/init.lua | 18 +++++------ 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index 1e786f025db..9963b49f492 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -7,6 +7,7 @@ local notify = require("nvim-tree.notify") local find_file = require("nvim-tree.actions.finders.find-file").fn +local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") ---@alias ClipboardAction "copy" | "cut" @@ -14,35 +15,30 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@alias ClipboardActionFn fun(source: string, dest: string): boolean, string? ----@class Clipboard to handle all actions.fs clipboard API ----@field config table hydrated user opts.filters +---@class (exact) Clipboard: Class ---@field private explorer Explorer ---@field private data ClipboardData ---@field private clipboard_name string ---@field private reg string -local Clipboard = {} - ----@param opts table user options ----@param explorer Explorer ----@return Clipboard -function Clipboard:new(opts, explorer) - ---@type Clipboard - local o = { - explorer = explorer, - data = { - copy = {}, - cut = {}, - }, - clipboard_name = opts.actions.use_system_clipboard and "system" or "neovim", - reg = opts.actions.use_system_clipboard and "+" or "1", - config = { - filesystem_watchers = opts.filesystem_watchers, - }, +local Clipboard = Class:extend() + +---@class Clipboard +---@overload fun(args: ClipboardArgs): Clipboard + +---@class (exact) ClipboardArgs +---@field explorer Explorer + +---@param args ClipboardArgs +function Clipboard:new(args) + self.explorer = args.explorer + + self.data = { + copy = {}, + cut = {}, } - setmetatable(o, self) - self.__index = self - return o + self.clipboard_name = self.explorer.opts.actions.use_system_clipboard and "system" or "neovim" + self.reg = self.explorer.opts.actions.use_system_clipboard and "+" or "1" end ---@param source string @@ -252,7 +248,7 @@ function Clipboard:do_paste(node, action, action_fn) end self.data[action] = {} - if not self.config.filesystem_watchers.enable then + if not self.explorer.opts.filesystem_watchers.enable then self.explorer:reload_explorer() end end diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 624bbb21bcd..4fee9753682 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -52,17 +52,17 @@ function Explorer:new(args) }) 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, {}) - self.open = true - self.opts = config + self.open = true + self.opts = config - self.sorters = Sorter({ explorer = self }) - self.renderer = Renderer({ explorer = self }) - self.filters = Filters({ explorer = self }) - self.live_filter = LiveFilter({ explorer = self }) - self.marks = Marks({ explorer = self }) - self.clipboard = Clipboard:new(config, self) + self.sorters = Sorter({ explorer = self }) + self.renderer = Renderer({ explorer = self }) + self.filters = Filters({ explorer = self }) + self.live_filter = LiveFilter({ explorer = self }) + self.marks = Marks({ explorer = self }) + self.clipboard = Clipboard({ explorer = self }) self:create_autocmds() From 9fc7a866ec019215d7abc66c979b0859eed816ab Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 15:37:04 +1100 Subject: [PATCH 21/38] use supers for node methods --- lua/nvim-tree/node/directory-link.lua | 6 +++--- lua/nvim-tree/node/directory.lua | 5 +++-- lua/nvim-tree/node/file-link.lua | 4 ++-- lua/nvim-tree/node/file.lua | 4 ++-- lua/nvim-tree/node/root.lua | 2 +- lua/nvim-tree/renderer/decorator/init.lua | 1 - 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 019f23ebdcb..16774afacd8 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -28,7 +28,7 @@ function DirectoryLinkNode:new(args) end function DirectoryLinkNode:destroy() - DirectoryNode.destroy(self) + self.super.destroy(self) end ---Update the directory git_status of link target and the file status of the link itself @@ -60,7 +60,7 @@ end ---Maybe override name with arrow ---@return HighlightedString name function DirectoryLinkNode:highlighted_name() - local name = DirectoryNode.highlighted_name(self) + local name = self.super.highlighted_name(self) if self.explorer.opts.renderer.symlink_destination then local link_to = utils.path_relative(self.link_to, self.explorer.absolute_path) @@ -74,7 +74,7 @@ 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]] + local clone = self.super.clone(self) --[[@as DirectoryLinkNode]] clone.link_to = self.link_to clone.fs_stat_target = self.fs_stat_target diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index 95c536eea10..e848a80c577 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -1,6 +1,7 @@ local git_utils = require("nvim-tree.git.utils") local icons = require("nvim-tree.renderer.components.devicons") local notify = require("nvim-tree.notify") + local Node = require("nvim-tree.node") ---@class (exact) DirectoryNode: Node @@ -46,7 +47,7 @@ function DirectoryNode:destroy() end end - Node.destroy(self) + self.super.destroy(self) end ---Update the git_status of the directory @@ -272,7 +273,7 @@ end ---Create a sanitized partial copy of a node, populating children recursively. ---@return DirectoryNode cloned function DirectoryNode:clone() - local clone = Node.clone(self) --[[@as DirectoryNode]] + local clone = self.super.clone(self) --[[@as DirectoryNode]] clone.has_children = self.has_children clone.group_next = nil diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index 3c5571a29a2..aa0cde6422b 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -21,7 +21,7 @@ function FileLinkNode:new(args) end function FileLinkNode:destroy() - FileNode.destroy(self) + self.super.destroy(self) end ---Update the git_status of the target otherwise the link itself @@ -60,7 +60,7 @@ end ---Create a sanitized partial copy of a node ---@return FileLinkNode cloned function FileLinkNode:clone() - local clone = FileNode.clone(self) --[[@as FileLinkNode]] + local clone = self.super.clone(self) --[[@as FileLinkNode]] clone.link_to = self.link_to clone.fs_stat_target = self.fs_stat_target diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index a74a213a8eb..5e45dab757a 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -31,7 +31,7 @@ function FileNode:new(args) end function FileNode:destroy() - Node.destroy(self) + self.super.destroy(self) end ---Update the GitStatus of the file @@ -96,7 +96,7 @@ end ---Create a sanitized partial copy of a node ---@return FileNode cloned function FileNode:clone() - local clone = Node.clone(self) --[[@as FileNode]] + local clone = self.super.clone(self) --[[@as FileNode]] clone.extension = self.extension diff --git a/lua/nvim-tree/node/root.lua b/lua/nvim-tree/node/root.lua index ec3c44c4a82..a77b4718736 100644 --- a/lua/nvim-tree/node/root.lua +++ b/lua/nvim-tree/node/root.lua @@ -19,7 +19,7 @@ function RootNode:is_dotfile() end function RootNode:destroy() - DirectoryNode.destroy(self) + self.super.destroy(self) end return RootNode diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index f83b92dcae4..9b7d8027eb9 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -4,7 +4,6 @@ local Class = require("nvim-tree.classic") ---@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 From 82fc5296ffb0955911a3e88d320500b209c4bc35 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 15:42:57 +1100 Subject: [PATCH 22/38] HighlightDisplay uses classic --- lua/nvim-tree/appearance/diagnostics.lua | 38 +++++++++++++----------- lua/nvim-tree/renderer/builder.lua | 1 - 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/lua/nvim-tree/appearance/diagnostics.lua b/lua/nvim-tree/appearance/diagnostics.lua index 5c292104655..a5b0dcda71e 100644 --- a/lua/nvim-tree/appearance/diagnostics.lua +++ b/lua/nvim-tree/appearance/diagnostics.lua @@ -1,45 +1,47 @@ local appearance = require("nvim-tree.appearance") +local Class = require("nvim-tree.classic") + -- others with name and links less than this arbitrary value are short local SHORT_LEN = 50 local M = {} ----@class HighlightDisplay for :NvimTreeHiTest +---@class (exact) HighlightDisplay: Class for :NvimTreeHiTest ---@field group string nvim-tree highlight group name ---@field links string link chain to a concretely defined group ---@field def string :hi concrete definition after following any links -local HighlightDisplay = {} +local HighlightDisplay = Class:extend() + +---@class HighlightDisplay +---@overload fun(args: HighlightDisplayArgs): HighlightDisplay ----@param group string nvim-tree highlight group name ----@return HighlightDisplay -function HighlightDisplay:new(group) - local o = {} - setmetatable(o, self) - self.__index = self +---@class (exact) HighlightDisplayArgs +---@field group string nvim-tree highlight group name - o.group = group - local concrete = o.group +---@param args HighlightDisplayArgs +function HighlightDisplay:new(args) + self.group = args.group + + local concrete = self.group -- maybe follow links local links = {} - local link = vim.api.nvim_get_hl(0, { name = o.group }).link + local link = vim.api.nvim_get_hl(0, { name = self.group }).link while link do table.insert(links, link) concrete = link link = vim.api.nvim_get_hl(0, { name = link }).link end - o.links = table.concat(links, " ") + self.links = table.concat(links, " ") -- concrete definition local ok, res = pcall(vim.api.nvim_cmd, { cmd = "highlight", args = { concrete } }, { output = true }) if ok and type(res) == "string" then - o.def = res:gsub(".*xxx *", "") + self.def = res:gsub(".*xxx *", "") else - o.def = "" + self.def = "" end - - return o end ---Render one group. @@ -96,7 +98,7 @@ function M.hi_test() -- nvim-tree groups, ordered local displays = {} for _, highlight_group in ipairs(appearance.HIGHLIGHT_GROUPS) do - local display = HighlightDisplay:new(highlight_group.group) + local display = HighlightDisplay({ group = highlight_group.group }) table.insert(displays, display) end l = render_displays("nvim-tree", displays, bufnr, l) @@ -110,7 +112,7 @@ function M.hi_test() if ok then for group in string.gmatch(out, "(%w*)%s+xxx") do if group:find("NvimTree", 1, true) ~= 1 then - local display = HighlightDisplay:new(group) + local display = HighlightDisplay({ group = group }) if #display.group + #display.links > SHORT_LEN then table.insert(displays_long, display) else diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 29b3d337447..4efa88a25f9 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -27,7 +27,6 @@ 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 From 412475e4f7fd2f47ca62506ac371a2fa4cf050f1 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 17:55:15 +1100 Subject: [PATCH 23/38] protected :new --- lua/nvim-tree/actions/fs/clipboard.lua | 1 + lua/nvim-tree/appearance/diagnostics.lua | 1 + lua/nvim-tree/classic.lua | 1 + lua/nvim-tree/explorer/filters.lua | 1 + lua/nvim-tree/explorer/init.lua | 1 + lua/nvim-tree/explorer/live-filter.lua | 1 + lua/nvim-tree/explorer/sorter.lua | 1 + lua/nvim-tree/git/runner.lua | 2 +- lua/nvim-tree/marks/init.lua | 1 + lua/nvim-tree/node/link.lua | 2 +- lua/nvim-tree/renderer/builder.lua | 1 + lua/nvim-tree/renderer/decorator/bookmarks.lua | 2 +- lua/nvim-tree/renderer/decorator/copied.lua | 2 +- lua/nvim-tree/renderer/decorator/cut.lua | 2 +- lua/nvim-tree/renderer/decorator/diagnostics.lua | 2 +- lua/nvim-tree/renderer/decorator/git.lua | 2 +- lua/nvim-tree/renderer/decorator/hidden.lua | 2 +- lua/nvim-tree/renderer/decorator/modified.lua | 2 +- lua/nvim-tree/renderer/decorator/opened.lua | 2 +- lua/nvim-tree/renderer/init.lua | 1 + lua/nvim-tree/watcher.lua | 4 ++-- 21 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index 9963b49f492..3f3ed37c94d 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -28,6 +28,7 @@ local Clipboard = Class:extend() ---@class (exact) ClipboardArgs ---@field explorer Explorer +---@protected ---@param args ClipboardArgs function Clipboard:new(args) self.explorer = args.explorer diff --git a/lua/nvim-tree/appearance/diagnostics.lua b/lua/nvim-tree/appearance/diagnostics.lua index a5b0dcda71e..d843ffb3f2c 100644 --- a/lua/nvim-tree/appearance/diagnostics.lua +++ b/lua/nvim-tree/appearance/diagnostics.lua @@ -19,6 +19,7 @@ local HighlightDisplay = Class:extend() ---@class (exact) HighlightDisplayArgs ---@field group string nvim-tree highlight group name +---@protected ---@param args HighlightDisplayArgs function HighlightDisplay:new(args) self.group = args.group diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua index be098abe1ea..6e856bc90c0 100644 --- a/lua/nvim-tree/classic.lua +++ b/lua/nvim-tree/classic.lua @@ -16,6 +16,7 @@ local Class = {} Class.__index = Class ---@diagnostic disable-line: inject-field ---Default constructor +---@protected function Class:new(...) --luacheck: ignore 212 end diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index fc540666b1a..b2573a460a2 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -20,6 +20,7 @@ local Filters = Class:extend() ---@class (exact) FiltersArgs ---@field explorer Explorer +---@protected ---@param args FiltersArgs function Filters:new(args) self.explorer = args.explorer diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 4fee9753682..8a0ae425fff 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -43,6 +43,7 @@ local Explorer = RootNode:extend() ---@class (exact) ExplorerArgs ---@field path string +---@protected ---@param args ExplorerArgs function Explorer:new(args) Explorer.super.new(self, { diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index 89c994edefa..bd67194826c 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -18,6 +18,7 @@ local LiveFilter = Class:extend() ---@class (exact) LiveFilterArgs ---@field explorer Explorer +---@protected ---@param args LiveFilterArgs function LiveFilter:new(args) self.explorer = args.explorer diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index 9eb34ece1d9..302f2372861 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -20,6 +20,7 @@ local Sorter = Class:extend() ---@class (exact) SorterArgs ---@field explorer Explorer +---@protected ---@param args SorterArgs function Sorter:new(args) self.state = vim.deepcopy(args.explorer.opts.sort) diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index 4716e893d02..a10215da022 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -24,7 +24,7 @@ local GitRunner = Class:extend() local timeouts = 0 local MAX_TIMEOUTS = 5 ----@private +---@protected ---@param args GitRunnerArgs function GitRunner:new(args) self.args = args diff --git a/lua/nvim-tree/marks/init.lua b/lua/nvim-tree/marks/init.lua index 8c569e5f395..c940f999983 100644 --- a/lua/nvim-tree/marks/init.lua +++ b/lua/nvim-tree/marks/init.lua @@ -22,6 +22,7 @@ local Marks = Class:extend() ---@class (exact) MarksArgs ---@field explorer Explorer +---@protected ---@param args MarksArgs function Marks:new(args) self.explorer = args.explorer diff --git a/lua/nvim-tree/node/link.lua b/lua/nvim-tree/node/link.lua index 35e36490ff9..ff2d8e4df5b 100644 --- a/lua/nvim-tree/node/link.lua +++ b/lua/nvim-tree/node/link.lua @@ -8,7 +8,7 @@ local LinkNode = Class: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) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 4efa88a25f9..916597afc33 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -47,6 +47,7 @@ local Builder = Class:extend() ---@class (exact) BuilderArgs ---@field explorer Explorer +---@protected ---@param args BuilderArgs function Builder:new(args) self.explorer = args.explorer diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index e0d6e05c7bd..c83290aa4ed 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -7,7 +7,7 @@ local DecoratorBookmarks = Decorator:extend() ---@class DecoratorBookmarks ---@overload fun(explorer: DecoratorArgs): DecoratorBookmarks ----@private +---@protected ---@param args DecoratorArgs function DecoratorBookmarks:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua index 90f4a21bf05..4d54e1dc290 100644 --- a/lua/nvim-tree/renderer/decorator/copied.lua +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -6,7 +6,7 @@ local DecoratorCopied = Decorator:extend() ---@class DecoratorCopied ---@overload fun(explorer: DecoratorArgs): DecoratorCopied ----@private +---@protected ---@param args DecoratorArgs function DecoratorCopied:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua index 0e1b699460e..92eb1b8355c 100644 --- a/lua/nvim-tree/renderer/decorator/cut.lua +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -6,7 +6,7 @@ local DecoratorCut = Decorator:extend() ---@class DecoratorCut ---@overload fun(explorer: DecoratorArgs): DecoratorCut ----@private +---@protected ---@param args DecoratorArgs function DecoratorCut:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index cbf7f43979c..bcff66fafad 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -37,7 +37,7 @@ local DecoratorDiagnostics = Decorator:extend() ---@class DecoratorDiagnostics ---@overload fun(explorer: DecoratorArgs): DecoratorDiagnostics ----@private +---@protected ---@param args DecoratorArgs function DecoratorDiagnostics:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index 1c03e5a8367..87546768b03 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -22,7 +22,7 @@ local DecoratorGit = Decorator:extend() ---@class DecoratorGit ---@overload fun(explorer: DecoratorArgs): DecoratorGit ----@private +---@protected ---@param args DecoratorArgs function DecoratorGit:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/hidden.lua b/lua/nvim-tree/renderer/decorator/hidden.lua index e79fcb2f71c..291d9482774 100644 --- a/lua/nvim-tree/renderer/decorator/hidden.lua +++ b/lua/nvim-tree/renderer/decorator/hidden.lua @@ -8,7 +8,7 @@ local DecoratorHidden = Decorator:extend() ---@class DecoratorHidden ---@overload fun(explorer: DecoratorArgs): DecoratorHidden ----@private +---@protected ---@param args DecoratorArgs function DecoratorHidden:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index b13dd45dcfd..68dc322bde1 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -10,7 +10,7 @@ local DecoratorModified = Decorator:extend() ---@class DecoratorModified ---@overload fun(explorer: DecoratorArgs): DecoratorModified ----@private +---@protected ---@param args DecoratorArgs function DecoratorModified:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index c42c82359ba..4f47e09727d 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -9,7 +9,7 @@ local DecoratorOpened = Decorator:extend() ---@class DecoratorOpened ---@overload fun(explorer: DecoratorArgs): DecoratorOpened ----@private +---@protected ---@param args DecoratorArgs function DecoratorOpened:new(args) Decorator.new(self, { diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 69db3ca2757..0585b40a660 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -21,6 +21,7 @@ local Renderer = Class:extend() ---@class (exact) RendererArgs ---@field explorer Explorer +---@protected ---@param args RendererArgs function Renderer:new(args) self.explorer = args.explorer diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index d29d080bf7e..abc44d27fab 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -32,7 +32,7 @@ local Event = Class:extend() ---@class (exact) EventArgs ---@field path string ----@private +---@protected ---@param args EventArgs function Event:new(args) self.destroyed = false @@ -160,7 +160,7 @@ local Watcher = Class:extend() ---@field callback fun(watcher: Watcher) ---@field data table? user data ----@private +---@protected ---@param args WatcherArgs function Watcher:new(args) self.data = args.data From 388439e6390bf91f9cddfbe054756f8e437f81ac Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 17:59:07 +1100 Subject: [PATCH 24/38] Watcher tidy --- lua/nvim-tree/watcher.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index abc44d27fab..bda0cb2740d 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -169,7 +169,6 @@ function Watcher:new(args) self.callback = args.callback self.files = args.files self.listener = nil - self.event = args.event end ---Static factory method From 53fa471777826e1b3da6c351fbe028f22aee9c3b Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 18:00:13 +1100 Subject: [PATCH 25/38] Revert "use supers for node methods" This reverts commit 9fc7a866ec019215d7abc66c979b0859eed816ab. --- lua/nvim-tree/node/directory-link.lua | 6 +++--- lua/nvim-tree/node/directory.lua | 5 ++--- lua/nvim-tree/node/file-link.lua | 4 ++-- lua/nvim-tree/node/file.lua | 4 ++-- lua/nvim-tree/node/root.lua | 2 +- lua/nvim-tree/renderer/decorator/init.lua | 1 + 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 16774afacd8..019f23ebdcb 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -28,7 +28,7 @@ function DirectoryLinkNode:new(args) end function DirectoryLinkNode:destroy() - self.super.destroy(self) + DirectoryNode.destroy(self) end ---Update the directory git_status of link target and the file status of the link itself @@ -60,7 +60,7 @@ end ---Maybe override name with arrow ---@return HighlightedString name function DirectoryLinkNode:highlighted_name() - local name = self.super.highlighted_name(self) + local name = DirectoryNode.highlighted_name(self) if self.explorer.opts.renderer.symlink_destination then local link_to = utils.path_relative(self.link_to, self.explorer.absolute_path) @@ -74,7 +74,7 @@ end ---Create a sanitized partial copy of a node, populating children recursively. ---@return DirectoryLinkNode cloned function DirectoryLinkNode:clone() - local clone = self.super.clone(self) --[[@as DirectoryLinkNode]] + local clone = DirectoryNode.clone(self) --[[@as DirectoryLinkNode]] clone.link_to = self.link_to clone.fs_stat_target = self.fs_stat_target diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index e848a80c577..95c536eea10 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -1,7 +1,6 @@ local git_utils = require("nvim-tree.git.utils") local icons = require("nvim-tree.renderer.components.devicons") local notify = require("nvim-tree.notify") - local Node = require("nvim-tree.node") ---@class (exact) DirectoryNode: Node @@ -47,7 +46,7 @@ function DirectoryNode:destroy() end end - self.super.destroy(self) + Node.destroy(self) end ---Update the git_status of the directory @@ -273,7 +272,7 @@ end ---Create a sanitized partial copy of a node, populating children recursively. ---@return DirectoryNode cloned function DirectoryNode:clone() - local clone = self.super.clone(self) --[[@as DirectoryNode]] + local clone = Node.clone(self) --[[@as DirectoryNode]] clone.has_children = self.has_children clone.group_next = nil diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index aa0cde6422b..3c5571a29a2 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -21,7 +21,7 @@ function FileLinkNode:new(args) end function FileLinkNode:destroy() - self.super.destroy(self) + FileNode.destroy(self) end ---Update the git_status of the target otherwise the link itself @@ -60,7 +60,7 @@ end ---Create a sanitized partial copy of a node ---@return FileLinkNode cloned function FileLinkNode:clone() - local clone = self.super.clone(self) --[[@as FileLinkNode]] + local clone = FileNode.clone(self) --[[@as FileLinkNode]] clone.link_to = self.link_to clone.fs_stat_target = self.fs_stat_target diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index 5e45dab757a..a74a213a8eb 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -31,7 +31,7 @@ function FileNode:new(args) end function FileNode:destroy() - self.super.destroy(self) + Node.destroy(self) end ---Update the GitStatus of the file @@ -96,7 +96,7 @@ end ---Create a sanitized partial copy of a node ---@return FileNode cloned function FileNode:clone() - local clone = self.super.clone(self) --[[@as FileNode]] + local clone = Node.clone(self) --[[@as FileNode]] clone.extension = self.extension diff --git a/lua/nvim-tree/node/root.lua b/lua/nvim-tree/node/root.lua index a77b4718736..ec3c44c4a82 100644 --- a/lua/nvim-tree/node/root.lua +++ b/lua/nvim-tree/node/root.lua @@ -19,7 +19,7 @@ function RootNode:is_dotfile() end function RootNode:destroy() - self.super.destroy(self) + DirectoryNode.destroy(self) end return RootNode diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 9b7d8027eb9..f83b92dcae4 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -4,6 +4,7 @@ local Class = require("nvim-tree.classic") ---@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 From a219a19f0224674d3732c90948cce6f9b59e5b69 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 18:01:23 +1100 Subject: [PATCH 26/38] Watcher tidy --- lua/nvim-tree/node/directory.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index 95c536eea10..ebec8f4c284 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -1,6 +1,7 @@ local git_utils = require("nvim-tree.git.utils") local icons = require("nvim-tree.renderer.components.devicons") local notify = require("nvim-tree.notify") + local Node = require("nvim-tree.node") ---@class (exact) DirectoryNode: Node From f2dd8a439725ee79b78cfc45cc953eedca71dab9 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 18:09:44 +1100 Subject: [PATCH 27/38] format --- lua/nvim-tree/renderer/builder.lua | 22 +++++++++++----------- lua/nvim-tree/watcher.lua | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 916597afc33..2cb3c500ff5 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -50,17 +50,17 @@ local Builder = Class:extend() ---@protected ---@param args BuilderArgs function Builder:new(args) - self.explorer = args.explorer - self.index = 0 - self.depth = 0 - self.hl_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 = { + self.lines = {} + self.markers = {} + self.signs = {} + self.extmarks = {} + self.virtual_lines = {} + self.decorators = { -- priority order DecoratorCut({ explorer = args.explorer }), DecoratorCopied({ explorer = args.explorer }), @@ -71,7 +71,7 @@ function Builder:new(args) DecoratorOpened({ explorer = args.explorer }), DecoratorGit({ explorer = args.explorer }) } - self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts) + self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts) end ---Insert ranged highlight groups into self.highlights diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index bda0cb2740d..960e9246d75 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -36,8 +36,8 @@ local Event = Class:extend() ---@param args EventArgs function Event:new(args) self.destroyed = false - self.path = args.path - self.fs_event = nil + self.path = args.path + self.fs_event = nil self.listeners = {} end @@ -163,12 +163,12 @@ local Watcher = Class:extend() ---@protected ---@param args WatcherArgs function Watcher:new(args) - self.data = args.data + self.data = args.data self.destroyed = false - self.path = args.path - self.callback = args.callback - self.files = args.files - self.listener = nil + self.path = args.path + self.callback = args.callback + self.files = args.files + self.listener = nil end ---Static factory method From ddd28ecd011c991fc9a99cc23de9ba298d4da652 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Fri, 8 Nov 2024 18:18:51 +1100 Subject: [PATCH 28/38] format --- lua/nvim-tree/explorer/filters.lua | 8 ++-- lua/nvim-tree/explorer/init.lua | 32 +++++++------- lua/nvim-tree/explorer/live-filter.lua | 16 +++---- lua/nvim-tree/explorer/sorter.lua | 12 +++--- lua/nvim-tree/git/init.lua | 24 +++++------ lua/nvim-tree/git/runner.lua | 4 +- lua/nvim-tree/git/utils.lua | 4 +- lua/nvim-tree/node/directory-link.lua | 9 ++-- lua/nvim-tree/node/directory.lua | 8 ++-- lua/nvim-tree/node/init.lua | 20 ++++----- lua/nvim-tree/renderer/builder.lua | 10 ++--- .../renderer/components/full-name.lua | 12 +++--- lua/nvim-tree/renderer/decorator/git.lua | 18 ++++---- lua/nvim-tree/renderer/init.lua | 8 ++-- lua/nvim-tree/view.lua | 42 +++++++++---------- 15 files changed, 114 insertions(+), 113 deletions(-) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index b2573a460a2..6a147ff9134 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -30,11 +30,11 @@ function Filters:new(args) self.enabled = self.explorer.opts.filters.enable self.states = { - custom = true, - dotfiles = self.explorer.opts.filters.dotfiles, + custom = true, + dotfiles = self.explorer.opts.filters.dotfiles, git_ignored = self.explorer.opts.filters.git_ignored, - git_clean = self.explorer.opts.filters.git_clean, - no_buffer = self.explorer.opts.filters.no_buffer, + git_clean = self.explorer.opts.filters.git_clean, + no_buffer = self.explorer.opts.filters.no_buffer, no_bookmark = self.explorer.opts.filters.no_bookmark, } diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 8a0ae425fff..5d40bc2fba4 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -200,10 +200,10 @@ function Explorer:reload(node, project) -- To reset we must 'zero' everything that we use node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, { - git = 0, - buf = 0, - dotfile = 0, - custom = 0, + git = 0, + buf = 0, + dotfile = 0, + custom = 0, bookmark = 0, }) @@ -234,11 +234,11 @@ function Explorer:reload(node, project) if not nodes_by_path[abs] then local new_child = node_factory.create({ - explorer = self, - parent = node, + explorer = self, + parent = node, absolute_path = abs, - name = name, - fs_stat = stat + name = name, + fs_stat = stat }) if new_child then table.insert(node.nodes, new_child) @@ -355,10 +355,10 @@ function Explorer:populate_children(handle, cwd, node, project, parent) local filter_status = parent.filters:prepare(project) node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, { - git = 0, - buf = 0, - dotfile = 0, - custom = 0, + git = 0, + buf = 0, + dotfile = 0, + custom = 0, bookmark = 0, }) @@ -378,11 +378,11 @@ function Explorer:populate_children(handle, cwd, node, project, parent) 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 local child = node_factory.create({ - explorer = self, - parent = node, + explorer = self, + parent = node, absolute_path = abs, - name = name, - fs_stat = stat + name = name, + fs_stat = stat }) if child then table.insert(node.nodes, child) diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index bd67194826c..62a7dd9ef64 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -169,21 +169,21 @@ local function create_overlay(self) if view.View.float.enable then -- don't close nvim-tree float when focus is changed to filter window vim.api.nvim_clear_autocmds({ - event = "WinLeave", + event = "WinLeave", pattern = "NvimTree_*", - group = vim.api.nvim_create_augroup("NvimTree", { clear = false }), + group = vim.api.nvim_create_augroup("NvimTree", { clear = false }), }) end configure_buffer_overlay(self) overlay_winnr = vim.api.nvim_open_win(overlay_bufnr, true, { - col = 1, - row = 0, + col = 1, + row = 0, relative = "cursor", - width = calculate_overlay_win_width(self), - height = 1, - border = "none", - style = "minimal", + width = calculate_overlay_win_width(self), + height = 1, + border = "none", + style = "minimal", }) if vim.fn.has("nvim-0.10") == 1 then diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index 302f2372861..2b44ec9e6fc 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -138,12 +138,12 @@ function Sorter:sort(t) for _, n in ipairs(t) do table.insert(t_user, { absolute_path = n.absolute_path, - executable = n.executable, - extension = n.extension, - filetype = vim.filetype.match({ filename = n.name }), - link_to = n.link_to, - name = n.name, - type = n.type, + executable = n.executable, + extension = n.extension, + filetype = vim.filetype.match({ filename = n.name }), + link_to = n.link_to, + name = n.name, + type = n.type, }) table.insert(origin_index, n) end diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index 50981b961e1..a0294b776cd 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -130,11 +130,11 @@ function M.reload_project(toplevel, path, callback) ---@type GitRunnerArgs local args = { - toplevel = toplevel, - path = path, + toplevel = toplevel, + path = path, list_untracked = git_utils.should_show_untracked(toplevel), - list_ignored = true, - timeout = M.config.git.timeout, + list_ignored = true, + timeout = M.config.git.timeout, } if callback then @@ -276,10 +276,10 @@ function M.load_project(path) end local path_xys = GitRunner:run({ - toplevel = toplevel, + toplevel = toplevel, list_untracked = git_utils.should_show_untracked(toplevel), - list_ignored = true, - timeout = M.config.git.timeout, + list_ignored = true, + timeout = M.config.git.timeout, }) local watcher = nil @@ -299,10 +299,10 @@ function M.load_project(path) local git_dir = vim.env.GIT_DIR or M._git_dirs_by_toplevel[toplevel] or utils.path_join({ toplevel, ".git" }) watcher = Watcher:create({ - path = git_dir, - files = WATCHED_FILES, + path = git_dir, + files = WATCHED_FILES, callback = callback, - data = { + data = { toplevel = toplevel, } }) @@ -310,8 +310,8 @@ function M.load_project(path) if path_xys then M._projects_by_toplevel[toplevel] = { - files = path_xys, - dirs = git_utils.project_files_to_project_dirs(path_xys, toplevel), + files = path_xys, + dirs = git_utils.project_files_to_project_dirs(path_xys, toplevel), watcher = watcher, } return M._projects_by_toplevel[toplevel] diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index a10215da022..bb570d064c0 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -94,8 +94,8 @@ function GitRunner:get_spawn_options(stdout_handle, stderr_handle) local untracked = self.args.list_untracked and "-u" or nil local ignored = (self.args.list_untracked and self.args.list_ignored) and "--ignored=matching" or "--ignored=no" return { - args = { "--no-optional-locks", "status", "--porcelain=v1", "-z", ignored, untracked, self.args.path }, - cwd = self.args.toplevel, + args = { "--no-optional-locks", "status", "--porcelain=v1", "-z", ignored, untracked, self.args.path }, + cwd = self.args.toplevel, stdio = { nil, stdout_handle, stderr_handle }, } end diff --git a/lua/nvim-tree/git/utils.lua b/lua/nvim-tree/git/utils.lua index a5a1efc21b1..b805ebfe4cd 100644 --- a/lua/nvim-tree/git/utils.lua +++ b/lua/nvim-tree/git/utils.lua @@ -172,8 +172,8 @@ function M.git_status_dir(parent_ignored, project, path, path_fallback) elseif project then ns = { file = project.files and (project.files[path] or project.files[path_fallback]), - dir = project.dirs and { - direct = project.dirs.direct and project.dirs.direct[path], + dir = project.dirs and { + direct = project.dirs.direct and project.dirs.direct[path], indirect = project.dirs.indirect and project.dirs.indirect[path], }, } diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 019f23ebdcb..82383088b91 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -48,10 +48,10 @@ function DirectoryLinkNode:highlighted_icon() if self.open then str = self.explorer.opts.renderer.icons.glyphs.folder.symlink_open - hl = "NvimTreeOpenedFolderIcon" + hl = "NvimTreeOpenedFolderIcon" else str = self.explorer.opts.renderer.icons.glyphs.folder.symlink - hl = "NvimTreeClosedFolderIcon" + hl = "NvimTreeClosedFolderIcon" end return { str = str, hl = { hl } } @@ -64,8 +64,9 @@ function DirectoryLinkNode:highlighted_name() if self.explorer.opts.renderer.symlink_destination then local link_to = utils.path_relative(self.link_to, self.explorer.absolute_path) - name.str = string.format("%s%s%s", name.str, self.explorer.opts.renderer.icons.symlink_arrow, link_to) - name.hl = { "NvimTreeSymlinkFolderName" } + + name.str = string.format("%s%s%s", name.str, self.explorer.opts.renderer.icons.symlink_arrow, link_to) + name.hl = { "NvimTreeSymlinkFolderName" } end return name diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index ebec8f4c284..899de184044 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -273,12 +273,12 @@ end ---Create a sanitized partial copy of a node, populating children recursively. ---@return DirectoryNode cloned function DirectoryNode:clone() - local clone = Node.clone(self) --[[@as DirectoryNode]] + local clone = Node.clone(self) --[[@as DirectoryNode]] clone.has_children = self.has_children - clone.group_next = nil - clone.nodes = {} - clone.open = self.open + clone.group_next = nil + clone.nodes = {} + clone.open = self.open clone.hidden_stats = nil for _, child in ipairs(self.nodes) do diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index de53607e157..f6ecf24d036 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -125,17 +125,17 @@ function Node:clone() ---@type Node local clone = { - type = self.type, - explorer = explorer_placeholder, + type = self.type, + explorer = explorer_placeholder, absolute_path = self.absolute_path, - executable = self.executable, - fs_stat = self.fs_stat, - git_status = self.git_status, - hidden = self.hidden, - name = self.name, - parent = nil, - diag_status = nil, - is_dot = self.is_dot, + executable = self.executable, + fs_stat = self.fs_stat, + git_status = self.git_status, + hidden = self.hidden, + name = self.name, + parent = nil, + diag_status = nil, + is_dot = self.is_dot, } return clone diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 2cb3c500ff5..303e02a39d3 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -408,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) diff --git a/lua/nvim-tree/renderer/components/full-name.lua b/lua/nvim-tree/renderer/components/full-name.lua index 39729ffa1e8..54742812630 100644 --- a/lua/nvim-tree/renderer/components/full-name.lua +++ b/lua/nvim-tree/renderer/components/full-name.lua @@ -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"] diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index 87546768b03..32e1aed07ef 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -52,14 +52,14 @@ 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 @@ -96,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 @@ -115,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", diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 0585b40a660..00d49f7f86f 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -59,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 @@ -69,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 diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 1f90fb426c0..eb72b774ce1 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -15,31 +15,31 @@ local DEFAULT_MAX_WIDTH = -1 local DEFAULT_PADDING = 1 M.View = { - adaptive_size = false, + adaptive_size = false, centralize_selection = false, - tabpages = {}, - cursors = {}, - hide_root_folder = false, - live_filter = { + tabpages = {}, + cursors = {}, + hide_root_folder = false, + live_filter = { prev_focused_node = nil, }, - winopts = { + winopts = { relativenumber = false, - number = false, - list = false, - foldenable = false, - winfixwidth = true, - winfixheight = true, - spell = false, - signcolumn = "yes", - foldmethod = "manual", - foldcolumn = "0", - cursorcolumn = false, - cursorline = true, - cursorlineopt = "both", - colorcolumn = "0", - wrap = false, - winhl = table.concat({ + number = false, + list = false, + foldenable = false, + winfixwidth = true, + winfixheight = true, + spell = false, + signcolumn = "yes", + foldmethod = "manual", + foldcolumn = "0", + cursorcolumn = false, + cursorline = true, + cursorlineopt = "both", + colorcolumn = "0", + wrap = false, + winhl = table.concat({ "EndOfBuffer:NvimTreeEndOfBuffer", "CursorLine:NvimTreeCursorLine", "CursorLineNr:NvimTreeCursorLineNr", From 07a9fb17c0377d305d551110fcf3d542af6a0059 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 09:35:55 +1100 Subject: [PATCH 29/38] Filters private methods --- lua/nvim-tree/explorer/filters.lua | 65 +++++++++++++++++------------- lua/nvim-tree/explorer/init.lua | 4 +- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 6a147ff9134..68afe11158e 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -7,7 +7,7 @@ local Class = require("nvim-tree.classic") ---@class (exact) Filters: Class ---@field enabled boolean ----@field states table +---@field state table ---@field private explorer Explorer ---@field private exclude_list string[] filters.exclude ---@field private ignore_list table filters.custom string table @@ -29,7 +29,7 @@ function Filters:new(args) self.custom_function = nil self.enabled = self.explorer.opts.filters.enable - self.states = { + self.state = { custom = true, dotfiles = self.explorer.opts.filters.dotfiles, git_ignored = self.explorer.opts.filters.git_ignored, @@ -50,9 +50,10 @@ function Filters:new(args) end end +---@private ---@param path string ---@return boolean -local function is_excluded(self, path) +function Filters:is_excluded(path) for _, node in ipairs(self.exclude_list) do if path:match(node) then return true @@ -62,10 +63,11 @@ local function is_excluded(self, path) end ---Check if the given path is git clean/ignored +---@private ---@param path string Absolute path ---@param project GitProject from prepare ---@return boolean -local function git(self, path, project) +function Filters:git(path, project) if type(project) ~= "table" or type(project.files) ~= "table" or type(project.dirs) ~= "table" then return false end @@ -76,12 +78,12 @@ local function git(self, path, project) xy = xy or project.dirs.indirect[path] and project.dirs.indirect[path][1] -- filter ignored; overrides clean as they are effectively dirty - if self.states.git_ignored and xy == "!!" then + if self.state.git_ignored and xy == "!!" then return true end -- filter clean - if self.states.git_clean and not xy then + if self.state.git_clean and not xy then return true end @@ -89,11 +91,12 @@ local function git(self, path, project) end ---Check if the given path has no listed buffer +---@private ---@param path string Absolute path ---@param bufinfo table vim.fn.getbufinfo { buflisted = 1 } ---@return boolean -local function buf(self, path, bufinfo) - if not self.states.no_buffer or type(bufinfo) ~= "table" then +function Filters:buf(path, bufinfo) + if not self.state.no_buffer or type(bufinfo) ~= "table" then return false end @@ -107,19 +110,21 @@ local function buf(self, path, bufinfo) return true end +---@private ---@param path string ---@return boolean -local function dotfile(self, path) - return self.states.dotfiles and utils.path_basename(path):sub(1, 1) == "." +function Filters:dotfile(path) + return self.state.dotfiles and utils.path_basename(path):sub(1, 1) == "." end ---Bookmark is present +---@private ---@param path string ---@param path_type string|nil filetype of path ---@param bookmarks table path, filetype table of bookmarked files ---@return boolean -local function bookmark(self, path, path_type, bookmarks) - if not self.states.no_bookmark then +function Filters:bookmark(path, path_type, bookmarks) + if not self.state.no_bookmark then return false end -- if bookmark is empty, we should see a empty filetree @@ -151,10 +156,11 @@ local function bookmark(self, path, path_type, bookmarks) return true end +---@private ---@param path string ---@return boolean -local function custom(self, path) - if not self.states.custom then +function Filters:custom(path) + if not self.state.custom then return false end @@ -196,7 +202,7 @@ function Filters:prepare(project) bookmarks = {}, } - if self.states.no_buffer then + if self.state.no_buffer then status.bufinfo = vim.fn.getbufinfo({ buflisted = 1 }) end @@ -221,15 +227,15 @@ function Filters:should_filter(path, fs_stat, status) end -- exclusions override all filters - if is_excluded(self, path) then + if self:is_excluded(path) then return false end - return git(self, path, status.project) - or buf(self, path, status.bufinfo) - or dotfile(self, path) - or custom(self, path) - or bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks) + return self:git(path, status.project) + or self:buf(path, status.bufinfo) + or self:dotfile(path) + or self:custom(path) + or self:bookmark(path, fs_stat and fs_stat.type, status.bookmarks) end --- Check if the given path should be filtered, and provide the reason why it was @@ -242,19 +248,19 @@ function Filters:should_filter_as_reason(path, fs_stat, status) return FILTER_REASON.none end - if is_excluded(self, path) then + if self:is_excluded(path) then return FILTER_REASON.none end - if git(self, path, status.project) then + if self:git(path, status.project) then return FILTER_REASON.git - elseif buf(self, path, status.bufinfo) then + elseif self:buf(path, status.bufinfo) then return FILTER_REASON.buf - elseif dotfile(self, path) then + elseif self:dotfile(path) then return FILTER_REASON.dotfile - elseif custom(self, path) then + elseif self:custom(path) then return FILTER_REASON.custom - elseif bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks) then + elseif self:bookmark(path, fs_stat and fs_stat.type, status.bookmarks) then return FILTER_REASON.bookmark else return FILTER_REASON.none @@ -262,12 +268,13 @@ function Filters:should_filter_as_reason(path, fs_stat, status) end ---Toggle a type and refresh +---@private ---@param type FilterType? nil to disable all function Filters:toggle(type) - if not type or self.states[type] == nil then + if not type or self.state[type] == nil then self.enabled = not self.enabled else - self.states[type] = not self.states[type] + self.state[type] = not self.state[type] end local node = self.explorer:get_node_at_cursor() diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 5d40bc2fba4..0c637b2a3d3 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -101,7 +101,7 @@ function Explorer:create_autocmds() vim.api.nvim_create_autocmd("BufReadPost", { group = self.augroup_id, callback = function(data) - if (self.filters.states.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then + if (self.filters.state.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function() self:reload_explorer() end) @@ -113,7 +113,7 @@ function Explorer:create_autocmds() vim.api.nvim_create_autocmd("BufUnload", { group = self.augroup_id, callback = function(data) - if (self.filters.states.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then + if (self.filters.state.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function() self:reload_explorer() end) From a08a54e135997ef022168a40a7da5267e90fd55b Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 09:39:50 +1100 Subject: [PATCH 30/38] format --- lua/nvim-tree/explorer/filters.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 68afe11158e..62230687e40 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -23,13 +23,13 @@ local Filters = Class:extend() ---@protected ---@param args FiltersArgs function Filters:new(args) - self.explorer = args.explorer - self.ignore_list = {} - self.exclude_list = self.explorer.opts.filters.exclude + self.explorer = args.explorer + self.ignore_list = {} + self.exclude_list = self.explorer.opts.filters.exclude self.custom_function = nil - self.enabled = self.explorer.opts.filters.enable - self.state = { + self.enabled = self.explorer.opts.filters.enable + self.state = { custom = true, dotfiles = self.explorer.opts.filters.dotfiles, git_ignored = self.explorer.opts.filters.git_ignored, @@ -38,7 +38,7 @@ function Filters:new(args) no_bookmark = self.explorer.opts.filters.no_bookmark, } - local custom_filter = self.explorer.opts.filters.custom + local custom_filter = self.explorer.opts.filters.custom if type(custom_filter) == "function" then self.custom_function = custom_filter else From b70bb6792e5503c2c9bd384bc6e728e5a0346627 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 10:04:14 +1100 Subject: [PATCH 31/38] Sorter type safety --- lua/nvim-tree/explorer/sorter.lua | 34 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index 2b44ec9e6fc..e201ca67728 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -3,15 +3,15 @@ local DirectoryNode = require("nvim-tree.node.directory") local C = {} +---@alias SorterType "name" | "case_sensitive" | "modification_time" | "extension" | "suffix" | "filetype" + ---@class (exact) SorterState ----@field sorter string|fun(nodes: Node[]) +---@field sorter SorterType|fun(nodes: Node[]) ---@field folders_first boolean ---@field files_first boolean ---@class (exact) Sorter: Class ----@field state SorterState ----@field user fun(nodes: Node[])? ----@field pre string? +---@field private state SorterState local Sorter = Class:extend() ---@class Sorter @@ -23,21 +23,19 @@ local Sorter = Class:extend() ---@protected ---@param args SorterArgs function Sorter:new(args) - self.state = vim.deepcopy(args.explorer.opts.sort) - - if type(self.state.sorter) == "function" then - self.user = self.state.sorter --[[@as fun(nodes: Node[])]] - elseif type(self.state.sorter) == "string" then - self.pre = self.state.sorter --[[@as string]] - end + self.state = { + sorter = args.explorer.opts.sort.sorter, + folders_first = args.explorer.opts.sort.folders_first, + files_first = args.explorer.opts.sort.files_first, + } end ---- Predefined comparator, defaulting to name ----@param sorter string as per options +---Predefined comparator +---@param type SorterType ---@return fun(a: Node, b: Node): boolean -function Sorter:get_comparator(sorter) +function Sorter:get_comparator(type) return function(a, b) - return (C[sorter] or C.name)(a, b, self.state) + return (C[type] or C.name)(a, b, self.state) end end @@ -131,7 +129,7 @@ end ---Perform a merge sort using sorter option. ---@param t Node[] function Sorter:sort(t) - if self.user then + if type(self.state.sorter) == "function" then local t_user = {} local origin_index = {} @@ -148,7 +146,7 @@ function Sorter:sort(t) table.insert(origin_index, n) end - local predefined = self.user(t_user) + local predefined = self.state.sorter(t_user) if predefined then split_merge(t, 1, #t, self:get_comparator(predefined)) return @@ -174,7 +172,7 @@ function Sorter:sort(t) end split_merge(t, 1, #t, mini_comparator) -- sort by user order - elseif self.pre then + elseif type(self.state.sorter) == "string" then split_merge(t, 1, #t, self:get_comparator(self.pre)) end end From f06bd90d20a50f8e9970f89db09f28247c2253b6 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 11:03:36 +1100 Subject: [PATCH 32/38] Sorter type safety --- lua/nvim-tree/explorer/sorter.lua | 33 ++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index e201ca67728..2c112ba0747 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -1,17 +1,19 @@ local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") -local C = {} - ---@alias SorterType "name" | "case_sensitive" | "modification_time" | "extension" | "suffix" | "filetype" +---@alias SorterComparator fun(a: Node, b: Node, cfg: SorterCfg): boolean + +---@type table +local C = {} ----@class (exact) SorterState +---@class (exact) SorterCfg ---@field sorter SorterType|fun(nodes: Node[]) ---@field folders_first boolean ---@field files_first boolean ---@class (exact) Sorter: Class ----@field private state SorterState +---@field private cfg SorterCfg local Sorter = Class:extend() ---@class Sorter @@ -23,7 +25,7 @@ local Sorter = Class:extend() ---@protected ---@param args SorterArgs function Sorter:new(args) - self.state = { + self.cfg = { sorter = args.explorer.opts.sort.sorter, folders_first = args.explorer.opts.sort.folders_first, files_first = args.explorer.opts.sort.files_first, @@ -35,7 +37,7 @@ end ---@return fun(a: Node, b: Node): boolean function Sorter:get_comparator(type) return function(a, b) - return (C[type] or C.name)(a, b, self.state) + return (C[type] or C.name)(a, b, self.cfg) end end @@ -56,7 +58,7 @@ end ---Evaluate `sort.folders_first` and `sort.files_first` ---@param a Node ---@param b Node ----@param cfg SorterState +---@param cfg SorterCfg ---@return boolean|nil local function folders_or_files_first(a, b, cfg) if not (cfg.folders_first or cfg.files_first) then @@ -129,7 +131,7 @@ end ---Perform a merge sort using sorter option. ---@param t Node[] function Sorter:sort(t) - if type(self.state.sorter) == "function" then + if type(self.cfg.sorter) == "function" then local t_user = {} local origin_index = {} @@ -146,7 +148,7 @@ function Sorter:sort(t) table.insert(origin_index, n) end - local predefined = self.state.sorter(t_user) + local predefined = self.cfg.sorter(t_user) if predefined then split_merge(t, 1, #t, self:get_comparator(predefined)) return @@ -172,15 +174,16 @@ function Sorter:sort(t) end split_merge(t, 1, #t, mini_comparator) -- sort by user order - elseif type(self.state.sorter) == "string" then - split_merge(t, 1, #t, self:get_comparator(self.pre)) + elseif type(self.cfg.sorter) == "string" then + local sorter = self.cfg.sorter --[[@as string]] + split_merge(t, 1, #t, self:get_comparator(sorter)) end end ---@param a Node ---@param b Node ---@param ignorecase boolean|nil ----@param cfg SorterState +---@param cfg SorterCfg ---@return boolean local function node_comparator_name_ignorecase_or_not(a, b, ignorecase, cfg) if not (a and b) then @@ -199,14 +202,17 @@ local function node_comparator_name_ignorecase_or_not(a, b, ignorecase, cfg) end end +---@type SorterComparator function C.case_sensitive(a, b, cfg) return node_comparator_name_ignorecase_or_not(a, b, false, cfg) end +---@type SorterComparator function C.name(a, b, cfg) return node_comparator_name_ignorecase_or_not(a, b, true, cfg) end +---@type SorterComparator function C.modification_time(a, b, cfg) if not (a and b) then return true @@ -231,6 +237,7 @@ function C.modification_time(a, b, cfg) return last_modified_b <= last_modified_a end +---@type SorterComparator function C.suffix(a, b, cfg) if not (a and b) then return true @@ -280,6 +287,7 @@ function C.suffix(a, b, cfg) return a_suffix:lower() < b_suffix:lower() end +---@type SorterComparator function C.extension(a, b, cfg) if not (a and b) then return true @@ -305,6 +313,7 @@ function C.extension(a, b, cfg) return a_ext < b_ext end +---@type SorterComparator function C.filetype(a, b, cfg) local a_ft = vim.filetype.match({ filename = a.name }) local b_ft = vim.filetype.match({ filename = b.name }) From 06b63260b3e64ec4b47dbfcc7e40343b21443419 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 11:49:40 +1100 Subject: [PATCH 33/38] Sorter type safety --- lua/nvim-tree/explorer/sorter.lua | 63 ++++++++++++++----------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index 2c112ba0747..37b33fa764b 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -2,13 +2,16 @@ local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") ---@alias SorterType "name" | "case_sensitive" | "modification_time" | "extension" | "suffix" | "filetype" ----@alias SorterComparator fun(a: Node, b: Node, cfg: SorterCfg): boolean + +---@alias SorterUser fun(nodes: Node[]): SorterType? + +---@alias SorterComparator fun(a: Node, b: Node, cfg: SorterCfg): boolean? ---@type table local C = {} ---@class (exact) SorterCfg ----@field sorter SorterType|fun(nodes: Node[]) +---@field sorter SorterType|SorterUser ---@field folders_first boolean ---@field files_first boolean @@ -32,15 +35,6 @@ function Sorter:new(args) } end ----Predefined comparator ----@param type SorterType ----@return fun(a: Node, b: Node): boolean -function Sorter:get_comparator(type) - return function(a, b) - return (C[type] or C.name)(a, b, self.cfg) - end -end - ---Create a shallow copy of a portion of a list. ---@param t table ---@param first integer First index, inclusive @@ -56,13 +50,10 @@ local function tbl_slice(t, first, last) end ---Evaluate `sort.folders_first` and `sort.files_first` ----@param a Node ----@param b Node ----@param cfg SorterCfg ----@return boolean|nil +---@type SorterComparator local function folders_or_files_first(a, b, cfg) if not (cfg.folders_first or cfg.files_first) then - return + return nil end if not a:is(DirectoryNode) and b:is(DirectoryNode) then @@ -72,14 +63,17 @@ local function folders_or_files_first(a, b, cfg) -- folder <> file return not cfg.files_first end + + return nil end ----@param t table +---@param t Node[] +---@param cfg SorterCfg ---@param first number ---@param mid number ---@param last number ----@param comparator fun(a: Node, b: Node): boolean -local function merge(t, first, mid, last, comparator) +---@param comparator SorterComparator +local function merge(t, cfg, first, mid, last, comparator) local n1 = mid - first + 1 local n2 = last - mid local ls = tbl_slice(t, first, mid) @@ -89,7 +83,7 @@ local function merge(t, first, mid, last, comparator) local k = first while i <= n1 and j <= n2 do - if comparator(ls[i], rs[j]) then + if comparator(ls[i], rs[j], cfg) then t[k] = ls[i] i = i + 1 else @@ -112,26 +106,29 @@ local function merge(t, first, mid, last, comparator) end end ----@param t table +---@param t Node[] +---@param cfg SorterCfg ---@param first number ---@param last number ----@param comparator fun(a: Node, b: Node): boolean -local function split_merge(t, first, last, comparator) +---@param comparator SorterComparator +local function split_merge(t, cfg, first, last, comparator) if (last - first) < 1 then return end local mid = math.floor((first + last) / 2) - split_merge(t, first, mid, comparator) - split_merge(t, mid + 1, last, comparator) - merge(t, first, mid, last, comparator) + split_merge(t, cfg, first, mid, comparator) + split_merge(t, cfg, mid + 1, last, comparator) + merge(t, cfg, first, mid, last, comparator) end ---Perform a merge sort using sorter option. ---@param t Node[] function Sorter:sort(t) - if type(self.cfg.sorter) == "function" then + if C[self.cfg.sorter] then + split_merge(t, self.cfg, 1, #t, C[self.cfg.sorter]) + elseif type(self.cfg.sorter) == "function" then local t_user = {} local origin_index = {} @@ -148,9 +145,10 @@ function Sorter:sort(t) table.insert(origin_index, n) end - local predefined = self.cfg.sorter(t_user) - if predefined then - split_merge(t, 1, #t, self:get_comparator(predefined)) + -- user may return a SorterType + local ret = self.cfg.sorter(t_user) + if C[ret] then + split_merge(t, self.cfg, 1, #t, C[ret]) return end @@ -173,10 +171,7 @@ function Sorter:sort(t) return (a_index or 0) <= (b_index or 0) end - split_merge(t, 1, #t, mini_comparator) -- sort by user order - elseif type(self.cfg.sorter) == "string" then - local sorter = self.cfg.sorter --[[@as string]] - split_merge(t, 1, #t, self:get_comparator(sorter)) + split_merge(t, self.cfg, 1, #t, mini_comparator) -- sort by user order end end From f92db92a49fdd24f6a1fb8a790769e19832bbc5f Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 13:05:49 +1100 Subject: [PATCH 34/38] Sorter type safety --- lua/nvim-tree/explorer/sorter.lua | 107 ++++++++++++++---------------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index 37b33fa764b..bf51a7b5a8c 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -2,21 +2,14 @@ local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") ---@alias SorterType "name" | "case_sensitive" | "modification_time" | "extension" | "suffix" | "filetype" +---@alias SorterComparator fun(self: Sorter, a: Node, b: Node): boolean? ---@alias SorterUser fun(nodes: Node[]): SorterType? ----@alias SorterComparator fun(a: Node, b: Node, cfg: SorterCfg): boolean? - ----@type table -local C = {} - ----@class (exact) SorterCfg ----@field sorter SorterType|SorterUser ----@field folders_first boolean ----@field files_first boolean - ---@class (exact) Sorter: Class ----@field private cfg SorterCfg +---@field private sorter SorterType|SorterUser +---@field private folders_first boolean +---@field private files_first boolean local Sorter = Class:extend() ---@class Sorter @@ -28,11 +21,9 @@ local Sorter = Class:extend() ---@protected ---@param args SorterArgs function Sorter:new(args) - self.cfg = { - sorter = args.explorer.opts.sort.sorter, - folders_first = args.explorer.opts.sort.folders_first, - files_first = args.explorer.opts.sort.files_first, - } + self.sorter = args.explorer.opts.sort.sorter + self.folders_first = args.explorer.opts.sort.folders_first + self.files_first = args.explorer.opts.sort.files_first end ---Create a shallow copy of a portion of a list. @@ -51,29 +42,28 @@ end ---Evaluate `sort.folders_first` and `sort.files_first` ---@type SorterComparator -local function folders_or_files_first(a, b, cfg) - if not (cfg.folders_first or cfg.files_first) then +function Sorter:folders_or_files_first(a, b) + if not (self.folders_first or self.files_first) then return nil end if not a:is(DirectoryNode) and b:is(DirectoryNode) then -- file <> folder - return cfg.files_first + return self.files_first elseif a:is(DirectoryNode) and not b:is(DirectoryNode) then -- folder <> file - return not cfg.files_first + return not self.files_first end return nil end ---@param t Node[] ----@param cfg SorterCfg ---@param first number ---@param mid number ---@param last number ---@param comparator SorterComparator -local function merge(t, cfg, first, mid, last, comparator) +function Sorter:merge(t, first, mid, last, comparator) local n1 = mid - first + 1 local n2 = last - mid local ls = tbl_slice(t, first, mid) @@ -83,7 +73,7 @@ local function merge(t, cfg, first, mid, last, comparator) local k = first while i <= n1 and j <= n2 do - if comparator(ls[i], rs[j], cfg) then + if comparator(self, ls[i], rs[j]) then t[k] = ls[i] i = i + 1 else @@ -107,28 +97,27 @@ local function merge(t, cfg, first, mid, last, comparator) end ---@param t Node[] ----@param cfg SorterCfg ---@param first number ---@param last number ---@param comparator SorterComparator -local function split_merge(t, cfg, first, last, comparator) +function Sorter:split_merge(t, first, last, comparator) if (last - first) < 1 then return end local mid = math.floor((first + last) / 2) - split_merge(t, cfg, first, mid, comparator) - split_merge(t, cfg, mid + 1, last, comparator) - merge(t, cfg, first, mid, last, comparator) + self:split_merge(t, first, mid, comparator) + self:split_merge(t, mid + 1, last, comparator) + self:merge(t, first, mid, last, comparator) end ---Perform a merge sort using sorter option. ---@param t Node[] function Sorter:sort(t) - if C[self.cfg.sorter] then - split_merge(t, self.cfg, 1, #t, C[self.cfg.sorter]) - elseif type(self.cfg.sorter) == "function" then + if self[self.sorter] then + self:split_merge(t, 1, #t, self[self.sorter]) + elseif type(self.sorter) == "function" then local t_user = {} local origin_index = {} @@ -145,10 +134,11 @@ function Sorter:sort(t) table.insert(origin_index, n) end + --- TODO code injection? -- user may return a SorterType - local ret = self.cfg.sorter(t_user) - if C[ret] then - split_merge(t, self.cfg, 1, #t, C[ret]) + local ret = self.sorter(t_user) + if self[ret] then + self:split_merge(t, 1, #t, self[ret]) return end @@ -161,7 +151,7 @@ function Sorter:sort(t) end -- if missing value found, then using origin_index - local mini_comparator = function(a, b) + local mini_comparator = function(_, a, b) local a_index = user_index[a.absolute_path] or origin_index[a.absolute_path] local b_index = user_index[b.absolute_path] or origin_index[b.absolute_path] @@ -171,26 +161,25 @@ function Sorter:sort(t) return (a_index or 0) <= (b_index or 0) end - split_merge(t, self.cfg, 1, #t, mini_comparator) -- sort by user order + self:split_merge(t, 1, #t, mini_comparator) -- sort by user order end end ---@param a Node ---@param b Node ----@param ignorecase boolean|nil ----@param cfg SorterCfg +---@param ignore_case boolean ---@return boolean -local function node_comparator_name_ignorecase_or_not(a, b, ignorecase, cfg) +function Sorter:name_case(a, b, ignore_case) if not (a and b) then return true end - local early_return = folders_or_files_first(a, b, cfg) + local early_return = self:folders_or_files_first(a, b) if early_return ~= nil then return early_return end - if ignorecase then + if ignore_case then return a.name:lower() <= b.name:lower() else return a.name <= b.name @@ -198,22 +187,22 @@ local function node_comparator_name_ignorecase_or_not(a, b, ignorecase, cfg) end ---@type SorterComparator -function C.case_sensitive(a, b, cfg) - return node_comparator_name_ignorecase_or_not(a, b, false, cfg) +function Sorter:case_sensitive(a, b) + return self:name_case(a, b, false) end ---@type SorterComparator -function C.name(a, b, cfg) - return node_comparator_name_ignorecase_or_not(a, b, true, cfg) +function Sorter:name(a, b) + return self:name_case(a, b, true) end ---@type SorterComparator -function C.modification_time(a, b, cfg) +function Sorter:modification_time(a, b) if not (a and b) then return true end - local early_return = folders_or_files_first(a, b, cfg) + local early_return = self:folders_or_files_first(a, b) if early_return ~= nil then return early_return end @@ -233,17 +222,17 @@ function C.modification_time(a, b, cfg) end ---@type SorterComparator -function C.suffix(a, b, cfg) +function Sorter:suffix(a, b) if not (a and b) then return true end -- directories go first - local early_return = folders_or_files_first(a, b, cfg) + local early_return = self:folders_or_files_first(a, b) if early_return ~= nil then return early_return elseif a.nodes and b.nodes then - return C.name(a, b, cfg) + return self:name(a, b) end -- dotfiles go second @@ -252,7 +241,7 @@ function C.suffix(a, b, cfg) elseif a.name:sub(1, 1) ~= "." and b.name:sub(1, 1) == "." then return false elseif a.name:sub(1, 1) == "." and b.name:sub(1, 1) == "." then - return C.name(a, b, cfg) + return self:name(a, b) end -- unsuffixed go third @@ -264,7 +253,7 @@ function C.suffix(a, b, cfg) elseif a_suffix_ndx and not b_suffix_ndx then return false elseif not (a_suffix_ndx and b_suffix_ndx) then - return C.name(a, b, cfg) + return self:name(a, b) end -- finally, compare by suffixes @@ -276,19 +265,19 @@ function C.suffix(a, b, cfg) elseif not a_suffix and b_suffix then return false elseif a_suffix:lower() == b_suffix:lower() then - return C.name(a, b, cfg) + return self:name(a, b) end return a_suffix:lower() < b_suffix:lower() end ---@type SorterComparator -function C.extension(a, b, cfg) +function Sorter:extension(a, b) if not (a and b) then return true end - local early_return = folders_or_files_first(a, b, cfg) + local early_return = self:folders_or_files_first(a, b) if early_return ~= nil then return early_return end @@ -302,19 +291,19 @@ function C.extension(a, b, cfg) local a_ext = (a.extension or ""):lower() local b_ext = (b.extension or ""):lower() if a_ext == b_ext then - return C.name(a, b, cfg) + return self:name(a, b) end return a_ext < b_ext end ---@type SorterComparator -function C.filetype(a, b, cfg) +function Sorter:filetype(a, b) local a_ft = vim.filetype.match({ filename = a.name }) local b_ft = vim.filetype.match({ filename = b.name }) -- directories first - local early_return = folders_or_files_first(a, b, cfg) + local early_return = self:folders_or_files_first(a, b) if early_return ~= nil then return early_return end @@ -328,7 +317,7 @@ function C.filetype(a, b, cfg) -- same filetype or both nil, sort by name if a_ft == b_ft then - return C.name(a, b, cfg) + return self:name(a, b) end return a_ft < b_ft From 30f1aa3bd762123c622d95cd5231301a0a52553e Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 13:17:47 +1100 Subject: [PATCH 35/38] Sorter type safety --- lua/nvim-tree/explorer/sorter.lua | 45 +++++++++++++++++++------------ 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index bf51a7b5a8c..c0fe9f4d0cf 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -10,7 +10,9 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@field private sorter SorterType|SorterUser ---@field private folders_first boolean ---@field private files_first boolean +---@field private comparators table local Sorter = Class:extend() +Sorter.comparators = {} ---@class Sorter ---@overload fun(args: SorterArgs): Sorter @@ -41,6 +43,7 @@ local function tbl_slice(t, first, last) end ---Evaluate `sort.folders_first` and `sort.files_first` +---@private ---@type SorterComparator function Sorter:folders_or_files_first(a, b) if not (self.folders_first or self.files_first) then @@ -58,6 +61,7 @@ function Sorter:folders_or_files_first(a, b) return nil end +---@private ---@param t Node[] ---@param first number ---@param mid number @@ -96,6 +100,7 @@ function Sorter:merge(t, first, mid, last, comparator) end end +---@private ---@param t Node[] ---@param first number ---@param last number @@ -115,8 +120,8 @@ end ---Perform a merge sort using sorter option. ---@param t Node[] function Sorter:sort(t) - if self[self.sorter] then - self:split_merge(t, 1, #t, self[self.sorter]) + if self.comparators[self.sorter] then + self:split_merge(t, 1, #t, self.comparators[self.sorter]) elseif type(self.sorter) == "function" then local t_user = {} local origin_index = {} @@ -134,11 +139,10 @@ function Sorter:sort(t) table.insert(origin_index, n) end - --- TODO code injection? -- user may return a SorterType local ret = self.sorter(t_user) - if self[ret] then - self:split_merge(t, 1, #t, self[ret]) + if self.comparators[ret] then + self:split_merge(t, 1, #t, self.comparators[ret]) return end @@ -165,6 +169,7 @@ function Sorter:sort(t) end end +---@private ---@param a Node ---@param b Node ---@param ignore_case boolean @@ -186,18 +191,21 @@ function Sorter:name_case(a, b, ignore_case) end end +---@private ---@type SorterComparator -function Sorter:case_sensitive(a, b) +function Sorter.comparators:case_sensitive(a, b) return self:name_case(a, b, false) end +---@private ---@type SorterComparator -function Sorter:name(a, b) +function Sorter.comparators:name(a, b) return self:name_case(a, b, true) end +---@private ---@type SorterComparator -function Sorter:modification_time(a, b) +function Sorter.comparators:modification_time(a, b) if not (a and b) then return true end @@ -221,8 +229,9 @@ function Sorter:modification_time(a, b) return last_modified_b <= last_modified_a end +---@private ---@type SorterComparator -function Sorter:suffix(a, b) +function Sorter.comparators:suffix(a, b) if not (a and b) then return true end @@ -232,7 +241,7 @@ function Sorter:suffix(a, b) if early_return ~= nil then return early_return elseif a.nodes and b.nodes then - return self:name(a, b) + return self.comparators:name(a, b) end -- dotfiles go second @@ -241,7 +250,7 @@ function Sorter:suffix(a, b) elseif a.name:sub(1, 1) ~= "." and b.name:sub(1, 1) == "." then return false elseif a.name:sub(1, 1) == "." and b.name:sub(1, 1) == "." then - return self:name(a, b) + return self.comparators:name(a, b) end -- unsuffixed go third @@ -253,7 +262,7 @@ function Sorter:suffix(a, b) elseif a_suffix_ndx and not b_suffix_ndx then return false elseif not (a_suffix_ndx and b_suffix_ndx) then - return self:name(a, b) + return self.comparators:name(a, b) end -- finally, compare by suffixes @@ -265,14 +274,15 @@ function Sorter:suffix(a, b) elseif not a_suffix and b_suffix then return false elseif a_suffix:lower() == b_suffix:lower() then - return self:name(a, b) + return self.comparators:name(a, b) end return a_suffix:lower() < b_suffix:lower() end +---@private ---@type SorterComparator -function Sorter:extension(a, b) +function Sorter.comparators:extension(a, b) if not (a and b) then return true end @@ -291,14 +301,15 @@ function Sorter:extension(a, b) local a_ext = (a.extension or ""):lower() local b_ext = (b.extension or ""):lower() if a_ext == b_ext then - return self:name(a, b) + return self.comparators:name(a, b) end return a_ext < b_ext end +---@private ---@type SorterComparator -function Sorter:filetype(a, b) +function Sorter.comparators:filetype(a, b) local a_ft = vim.filetype.match({ filename = a.name }) local b_ft = vim.filetype.match({ filename = b.name }) @@ -317,7 +328,7 @@ function Sorter:filetype(a, b) -- same filetype or both nil, sort by name if a_ft == b_ft then - return self:name(a, b) + return self.comparators:name(a, b) end return a_ft < b_ft From bb0e0ec277c7ab162eb16fdfd051a6ae2b56b23d Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 13:37:43 +1100 Subject: [PATCH 36/38] Sorter type safety --- lua/nvim-tree/explorer/sorter.lua | 54 ++++++++++++++----------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/lua/nvim-tree/explorer/sorter.lua b/lua/nvim-tree/explorer/sorter.lua index c0fe9f4d0cf..799cfa481b1 100644 --- a/lua/nvim-tree/explorer/sorter.lua +++ b/lua/nvim-tree/explorer/sorter.lua @@ -7,12 +7,8 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@alias SorterUser fun(nodes: Node[]): SorterType? ---@class (exact) Sorter: Class ----@field private sorter SorterType|SorterUser ----@field private folders_first boolean ----@field private files_first boolean ----@field private comparators table +---@field private explorer Explorer local Sorter = Class:extend() -Sorter.comparators = {} ---@class Sorter ---@overload fun(args: SorterArgs): Sorter @@ -23,9 +19,7 @@ Sorter.comparators = {} ---@protected ---@param args SorterArgs function Sorter:new(args) - self.sorter = args.explorer.opts.sort.sorter - self.folders_first = args.explorer.opts.sort.folders_first - self.files_first = args.explorer.opts.sort.files_first + self.explorer = args.explorer end ---Create a shallow copy of a portion of a list. @@ -42,20 +36,20 @@ local function tbl_slice(t, first, last) return slice end ----Evaluate `sort.folders_first` and `sort.files_first` +---Evaluate folders_first and sort.files_first returning nil when no order is necessary ---@private ---@type SorterComparator function Sorter:folders_or_files_first(a, b) - if not (self.folders_first or self.files_first) then + if not (self.explorer.opts.sort.folders_first or self.explorer.opts.sort.files_first) then return nil end if not a:is(DirectoryNode) and b:is(DirectoryNode) then -- file <> folder - return self.files_first + return self.explorer.opts.sort.files_first elseif a:is(DirectoryNode) and not b:is(DirectoryNode) then -- folder <> file - return not self.files_first + return not self.explorer.opts.sort.files_first end return nil @@ -120,9 +114,9 @@ end ---Perform a merge sort using sorter option. ---@param t Node[] function Sorter:sort(t) - if self.comparators[self.sorter] then - self:split_merge(t, 1, #t, self.comparators[self.sorter]) - elseif type(self.sorter) == "function" then + if self[self.explorer.opts.sort.sorter] then + self:split_merge(t, 1, #t, self[self.explorer.opts.sort.sorter]) + elseif type(self.explorer.opts.sort.sorter) == "function" then local t_user = {} local origin_index = {} @@ -140,9 +134,9 @@ function Sorter:sort(t) end -- user may return a SorterType - local ret = self.sorter(t_user) - if self.comparators[ret] then - self:split_merge(t, 1, #t, self.comparators[ret]) + local ret = self.explorer.opts.sort.sorter(t_user) + if self[ret] then + self:split_merge(t, 1, #t, self[ret]) return end @@ -193,19 +187,19 @@ end ---@private ---@type SorterComparator -function Sorter.comparators:case_sensitive(a, b) +function Sorter:case_sensitive(a, b) return self:name_case(a, b, false) end ---@private ---@type SorterComparator -function Sorter.comparators:name(a, b) +function Sorter:name(a, b) return self:name_case(a, b, true) end ---@private ---@type SorterComparator -function Sorter.comparators:modification_time(a, b) +function Sorter:modification_time(a, b) if not (a and b) then return true end @@ -231,7 +225,7 @@ end ---@private ---@type SorterComparator -function Sorter.comparators:suffix(a, b) +function Sorter:suffix(a, b) if not (a and b) then return true end @@ -241,7 +235,7 @@ function Sorter.comparators:suffix(a, b) if early_return ~= nil then return early_return elseif a.nodes and b.nodes then - return self.comparators:name(a, b) + return self:name(a, b) end -- dotfiles go second @@ -250,7 +244,7 @@ function Sorter.comparators:suffix(a, b) elseif a.name:sub(1, 1) ~= "." and b.name:sub(1, 1) == "." then return false elseif a.name:sub(1, 1) == "." and b.name:sub(1, 1) == "." then - return self.comparators:name(a, b) + return self:name(a, b) end -- unsuffixed go third @@ -262,7 +256,7 @@ function Sorter.comparators:suffix(a, b) elseif a_suffix_ndx and not b_suffix_ndx then return false elseif not (a_suffix_ndx and b_suffix_ndx) then - return self.comparators:name(a, b) + return self:name(a, b) end -- finally, compare by suffixes @@ -274,7 +268,7 @@ function Sorter.comparators:suffix(a, b) elseif not a_suffix and b_suffix then return false elseif a_suffix:lower() == b_suffix:lower() then - return self.comparators:name(a, b) + return self:name(a, b) end return a_suffix:lower() < b_suffix:lower() @@ -282,7 +276,7 @@ end ---@private ---@type SorterComparator -function Sorter.comparators:extension(a, b) +function Sorter:extension(a, b) if not (a and b) then return true end @@ -301,7 +295,7 @@ function Sorter.comparators:extension(a, b) local a_ext = (a.extension or ""):lower() local b_ext = (b.extension or ""):lower() if a_ext == b_ext then - return self.comparators:name(a, b) + return self:name(a, b) end return a_ext < b_ext @@ -309,7 +303,7 @@ end ---@private ---@type SorterComparator -function Sorter.comparators:filetype(a, b) +function Sorter:filetype(a, b) local a_ft = vim.filetype.match({ filename = a.name }) local b_ft = vim.filetype.match({ filename = b.name }) @@ -328,7 +322,7 @@ function Sorter.comparators:filetype(a, b) -- same filetype or both nil, sort by name if a_ft == b_ft then - return self.comparators:name(a, b) + return self:name(a, b) end return a_ft < b_ft From 795792258c57ec5305c039dc84f823f2a7d20033 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 13:55:43 +1100 Subject: [PATCH 37/38] tidy Runner --- lua/nvim-tree/git/runner.lua | 52 ++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index bb570d064c0..0c540575198 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -5,7 +5,12 @@ local notify = require("nvim-tree.notify") local Class = require("nvim-tree.classic") ---@class (exact) GitRunner: Class ----@field private args GitRunnerArgs +---@field private toplevel string absolute path +---@field private path string? absolute path +---@field private list_untracked boolean +---@field private list_ignored boolean +---@field private timeout integer +---@field private callback fun(path_xy: GitPathXY)? ---@field private path_xy GitPathXY ---@field private rc integer? -- -1 indicates timeout local GitRunner = Class:extend() @@ -27,8 +32,15 @@ local MAX_TIMEOUTS = 5 ---@protected ---@param args GitRunnerArgs function GitRunner:new(args) - self.args = args - self.path_xy = {} + self.toplevel = args.toplevel + self.path = args.path + self.list_untracked = args.list_untracked + self.list_ignored = args.list_ignored + self.timeout = args.timeout + self.callback = args.callback + + self.path_xy = {} + self.rc = nil end ---@private @@ -44,7 +56,7 @@ function GitRunner:parse_status_output(status, path) path = path:gsub("/", "\\") end if #status > 0 and #path > 0 then - self.path_xy[utils.path_remove_trailing(utils.path_join({ self.args.toplevel, path }))] = status + self.path_xy[utils.path_remove_trailing(utils.path_join({ self.toplevel, path }))] = status end end @@ -91,11 +103,11 @@ end ---@param stderr_handle uv.uv_pipe_t ---@return uv.spawn.options function GitRunner:get_spawn_options(stdout_handle, stderr_handle) - local untracked = self.args.list_untracked and "-u" or nil - local ignored = (self.args.list_untracked and self.args.list_ignored) and "--ignored=matching" or "--ignored=no" + local untracked = self.list_untracked and "-u" or nil + local ignored = (self.list_untracked and self.list_ignored) and "--ignored=matching" or "--ignored=no" return { - args = { "--no-optional-locks", "status", "--porcelain=v1", "-z", ignored, untracked, self.args.path }, - cwd = self.args.toplevel, + args = { "--no-optional-locks", "status", "--porcelain=v1", "-z", ignored, untracked, self.path }, + cwd = self.toplevel, stdio = { nil, stdout_handle, stderr_handle }, } end @@ -149,7 +161,7 @@ function GitRunner:run_git_job(callback) end local spawn_options = self:get_spawn_options(stdout, stderr) - log.line("git", "running job with timeout %dms", self.args.timeout) + log.line("git", "running job with timeout %dms", self.timeout) log.line("git", "git %s", table.concat(utils.array_remove_nils(spawn_options.args), " ")) handle, pid = vim.loop.spawn( @@ -161,7 +173,7 @@ function GitRunner:run_git_job(callback) ) timer:start( - self.args.timeout, + self.timeout, 0, vim.schedule_wrap(function() on_finish(-1) @@ -201,17 +213,17 @@ end ---@private function GitRunner:finalise() if self.rc == -1 then - log.line("git", "job timed out %s %s", self.args.toplevel, self.args.path) + log.line("git", "job timed out %s %s", self.toplevel, self.path) timeouts = timeouts + 1 if timeouts == MAX_TIMEOUTS then notify.warn(string.format("%d git jobs have timed out after git.timeout %dms, disabling git integration.", timeouts, - self.args.timeout)) + self.timeout)) require("nvim-tree.git").disable_git_integration() end elseif self.rc ~= 0 then - log.line("git", "job fail rc %d %s %s", self.rc, self.args.toplevel, self.args.path) + log.line("git", "job fail rc %d %s %s", self.rc, self.toplevel, self.path) else - log.line("git", "job success %s %s", self.args.toplevel, self.args.path) + log.line("git", "job success %s %s", self.toplevel, self.path) end end @@ -219,17 +231,17 @@ end ---@private ---@return GitPathXY? function GitRunner:execute() - local async = self.args.callback ~= nil - local profile = log.profile_start("git %s job %s %s", async and "async" or "sync", self.args.toplevel, self.args.path) + local async = self.callback ~= nil + local profile = log.profile_start("git %s job %s %s", async and "async" or "sync", self.toplevel, self.path) - if async and self.args.callback then + if async and self.callback then -- async, always call back self:run_git_job(function() log.profile_end(profile) self:finalise() - self.args.callback(self.path_xy) + self.callback(self.path_xy) end) else -- sync, maybe call back @@ -240,8 +252,8 @@ function GitRunner:execute() self:finalise() - if self.args.callback then - self.args.callback(self.path_xy) + if self.callback then + self.callback(self.path_xy) else return self.path_xy end From 4f40875bbc98cbb93005a181c111585e93ecb9d5 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Nov 2024 14:05:24 +1100 Subject: [PATCH 38/38] tidy hi-test name --- lua/nvim-tree/api.lua | 4 ++-- lua/nvim-tree/appearance/{diagnostics.lua => hi-test.lua} | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) rename lua/nvim-tree/appearance/{diagnostics.lua => hi-test.lua} (98%) diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index 31fcf2199d6..00118c3acb0 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -2,7 +2,7 @@ local core = require("nvim-tree.core") local view = require("nvim-tree.view") local utils = require("nvim-tree.utils") local actions = require("nvim-tree.actions") -local appearance_diagnostics = require("nvim-tree.appearance.diagnostics") +local appearance_hi_test = require("nvim-tree.appearance.hi-test") local events = require("nvim-tree.events") local help = require("nvim-tree.help") local keymap = require("nvim-tree.keymap") @@ -305,7 +305,7 @@ Api.config.mappings.get_keymap = wrap(keymap.get_keymap) Api.config.mappings.get_keymap_default = wrap(keymap.get_keymap_default) Api.config.mappings.default_on_attach = keymap.default_on_attach -Api.diagnostics.hi_test = wrap(appearance_diagnostics.hi_test) +Api.diagnostics.hi_test = wrap(appearance_hi_test) Api.commands.get = wrap(function() return require("nvim-tree.commands").get() diff --git a/lua/nvim-tree/appearance/diagnostics.lua b/lua/nvim-tree/appearance/hi-test.lua similarity index 98% rename from lua/nvim-tree/appearance/diagnostics.lua rename to lua/nvim-tree/appearance/hi-test.lua index d843ffb3f2c..25edb9ce4b6 100644 --- a/lua/nvim-tree/appearance/diagnostics.lua +++ b/lua/nvim-tree/appearance/hi-test.lua @@ -5,8 +5,6 @@ local Class = require("nvim-tree.classic") -- others with name and links less than this arbitrary value are short local SHORT_LEN = 50 -local M = {} - ---@class (exact) HighlightDisplay: Class for :NvimTreeHiTest ---@field group string nvim-tree highlight group name ---@field links string link chain to a concretely defined group @@ -90,7 +88,7 @@ end ---Run a test similar to :so $VIMRUNTIME/syntax/hitest.vim ---Display all nvim-tree and neovim highlight groups, their link chain and actual definition -function M.hi_test() +return function() -- create a buffer local bufnr = vim.api.nvim_create_buf(false, true) @@ -140,5 +138,3 @@ function M.hi_test() vim.cmd.buffer(bufnr) end - -return M