diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index 8cb4bc4a350..3d48f95a583 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -2,7 +2,6 @@ local utils = require "nvim-tree.utils" local builders = require "nvim-tree.explorer.node-builders" local explorer_node = require "nvim-tree.explorer.node" local git = require "nvim-tree.git" -local sorters = require "nvim-tree.explorer.sorters" local live_filter = require "nvim-tree.live-filter" local log = require "nvim-tree.log" @@ -82,7 +81,7 @@ function M.explore(node, status, parent) return ns end - sorters.sort(node.nodes) + parent.sorters:sort(node.nodes) live_filter.apply_filter(node) log.profile_end(profile) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 5b682b72c55..5dc085e7ee3 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -4,6 +4,7 @@ local watch = require "nvim-tree.explorer.watch" local explorer_node = require "nvim-tree.explorer.node" local Filters = require "nvim-tree.explorer.filters" local Marks = require "nvim-tree.marks" +local Sorters = require "nvim-tree.explorer.sorters" local M = {} @@ -40,6 +41,7 @@ function Explorer.new(path) nodes = {}, open = true, marks = Marks:new(), + sorters = Sorters:new(M.config), }, Explorer) explorer.watcher = watch.create_watcher(explorer) explorer.filters = Filters:new(M.config, explorer) @@ -76,7 +78,6 @@ function M.setup(opts) M.config = opts require("nvim-tree.explorer.node").setup(opts) require("nvim-tree.explorer.explore").setup(opts) - require("nvim-tree.explorer.sorters").setup(opts) require("nvim-tree.explorer.reload").setup(opts) require("nvim-tree.explorer.watch").setup(opts) end diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index 3243861ea6d..101a22cf000 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -1,7 +1,6 @@ local utils = require "nvim-tree.utils" local builders = require "nvim-tree.explorer.node-builders" local explorer_node = require "nvim-tree.explorer.node" -local sorters = require "nvim-tree.explorer.sorters" local live_filter = require "nvim-tree.live-filter" local git = require "nvim-tree.git" local log = require "nvim-tree.log" @@ -165,7 +164,7 @@ function M.reload(node, git_status) return ns end - sorters.sort(node.nodes) + explorer.sorters:sort(node.nodes) live_filter.apply_filter(node) log.profile_end(profile) return node.nodes diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index cb7400f512e..3fa40c9d3b7 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -1,12 +1,27 @@ -local M = {} - local C = {} +---@class Sorter +local Sorter = {} + +function Sorter:new(opts) + local o = {} + setmetatable(o, self) + self.__index = self + o.config = vim.deepcopy(opts.sort) + + if type(o.config.sorter) == "function" then + o.user = o.config.sorter + end + return o +end + --- Predefined comparator, defaulting to name ---@param sorter string as per options ---@return function -local function get_comparator(sorter) - return C[sorter] or C.name +function Sorter:get_comparator(sorter) + return function(a, b) + return (C[sorter] or C.name)(a, b, self.config) + end end ---Create a shallow copy of a portion of a list. @@ -27,17 +42,17 @@ end ---@param a Node ---@param b Node ---@return boolean|nil -local function folders_or_files_first(a, b) - if not (M.config.sort.folders_first or M.config.sort.files_first) then +local function folders_or_files_first(a, b, cfg) + if not (cfg.folders_first or cfg.files_first) then return end if not a.nodes and b.nodes then -- file <> folder - return M.config.sort.files_first + return cfg.files_first elseif a.nodes and not b.nodes then -- folder <> file - return not M.config.sort.files_first + return not cfg.files_first end end @@ -97,8 +112,8 @@ end ---Perform a merge sort using sorter option. ---@param t table nodes -function M.sort(t) - if C.user then +function Sorter:sort(t) + if self.user then local t_user = {} local origin_index = {} @@ -115,9 +130,9 @@ function M.sort(t) table.insert(origin_index, n) end - local predefined = C.user(t_user) + local predefined = self.user(t_user) if predefined then - split_merge(t, 1, #t, get_comparator(predefined)) + split_merge(t, 1, #t, self:get_comparator(predefined)) return end @@ -142,7 +157,7 @@ function M.sort(t) split_merge(t, 1, #t, mini_comparator) -- sort by user order else - split_merge(t, 1, #t, get_comparator(M.config.sort.sorter)) + split_merge(t, 1, #t, self:get_comparator(self.config.sorter)) end end @@ -150,12 +165,12 @@ end ---@param b Node ---@param ignorecase boolean|nil ---@return boolean -local function node_comparator_name_ignorecase_or_not(a, b, ignorecase) +local function node_comparator_name_ignorecase_or_not(a, b, ignorecase, cfg) if not (a and b) then return true end - local early_return = folders_or_files_first(a, b) + local early_return = folders_or_files_first(a, b, cfg) if early_return ~= nil then return early_return end @@ -167,20 +182,20 @@ local function node_comparator_name_ignorecase_or_not(a, b, ignorecase) end end -function C.case_sensitive(a, b) - return node_comparator_name_ignorecase_or_not(a, b, false) +function C.case_sensitive(a, b, cfg) + return node_comparator_name_ignorecase_or_not(a, b, false, cfg) end -function C.name(a, b) - return node_comparator_name_ignorecase_or_not(a, b, true) +function C.name(a, b, cfg) + return node_comparator_name_ignorecase_or_not(a, b, true, cfg) end -function C.modification_time(a, b) +function C.modification_time(a, b, cfg) if not (a and b) then return true end - local early_return = folders_or_files_first(a, b) + local early_return = folders_or_files_first(a, b, cfg) if early_return ~= nil then return early_return end @@ -199,17 +214,17 @@ function C.modification_time(a, b) return last_modified_b <= last_modified_a end -function C.suffix(a, b) +function C.suffix(a, b, cfg) if not (a and b) then return true end -- directories go first - local early_return = folders_or_files_first(a, b) + local early_return = folders_or_files_first(a, b, cfg) if early_return ~= nil then return early_return elseif a.nodes and b.nodes then - return C.name(a, b) + return C.name(a, b, cfg) end -- dotfiles go second @@ -218,7 +233,7 @@ function C.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 C.name(a, b) + return C.name(a, b, cfg) end -- unsuffixed go third @@ -230,7 +245,7 @@ function C.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 C.name(a, b) + return C.name(a, b, cfg) end -- finally, compare by suffixes @@ -242,18 +257,18 @@ function C.suffix(a, b) elseif not a_suffix and b_suffix then return false elseif a_suffix:lower() == b_suffix:lower() then - return C.name(a, b) + return C.name(a, b, cfg) end return a_suffix:lower() < b_suffix:lower() end -function C.extension(a, b) +function C.extension(a, b, cfg) if not (a and b) then return true end - local early_return = folders_or_files_first(a, b) + local early_return = folders_or_files_first(a, b, cfg) if early_return ~= nil then return early_return end @@ -267,18 +282,18 @@ function C.extension(a, b) 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) + return C.name(a, b, cfg) end return a_ext < b_ext end -function C.filetype(a, b) +function C.filetype(a, b, cfg) 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) + local early_return = folders_or_files_first(a, b, cfg) if early_return ~= nil then return early_return end @@ -292,19 +307,10 @@ function C.filetype(a, b) -- same filetype or both nil, sort by name if a_ft == b_ft then - return C.name(a, b) + return C.name(a, b, cfg) end return a_ft < b_ft end -function M.setup(opts) - M.config = {} - M.config.sort = opts.sort - - if type(M.config.sort.sorter) == "function" then - C.user = M.config.sort.sorter - end -end - -return M +return Sorter