From 76d181d480df656289eb5a51d9f747eb83b51185 Mon Sep 17 00:00:00 2001 From: kiyan Date: Sun, 6 Mar 2022 14:14:56 +0100 Subject: [PATCH] refacto: move filters and sorters in their own modules Also exclude filters is taken into account in git ignore fixes #892 --- lua/nvim-tree/actions/toggles.lua | 6 +- lua/nvim-tree/explorer/common.lua | 11 ++ lua/nvim-tree/explorer/explore.lua | 10 +- .../explorer/{utils.lua => filters.lua} | 63 ++------- lua/nvim-tree/explorer/init.lua | 3 +- lua/nvim-tree/explorer/reload.lua | 10 +- lua/nvim-tree/explorer/sorters.lua | 122 ++++++++++++++++++ lua/nvim-tree/utils.lua | 70 ---------- 8 files changed, 159 insertions(+), 136 deletions(-) create mode 100644 lua/nvim-tree/explorer/common.lua rename lua/nvim-tree/explorer/{utils.lua => filters.lua} (56%) create mode 100644 lua/nvim-tree/explorer/sorters.lua diff --git a/lua/nvim-tree/actions/toggles.lua b/lua/nvim-tree/actions/toggles.lua index adf9c021..aa2cb9ab 100644 --- a/lua/nvim-tree/actions/toggles.lua +++ b/lua/nvim-tree/actions/toggles.lua @@ -1,17 +1,17 @@ local view = require"nvim-tree.view" -local eutils = require"nvim-tree.explorer.utils" +local filters = require"nvim-tree.explorer.filters" local renderer = require"nvim-tree.renderer" local reloaders = require"nvim-tree.actions.reloaders" local M = {} function M.ignored() - eutils.config.filter_ignored = not eutils.config.filter_ignored + filters.config.filter_ignored = not filters.config.filter_ignored return reloaders.reload_explorer() end function M.dotfiles() - eutils.config.filter_dotfiles = not eutils.config.filter_dotfiles + filters.config.filter_dotfiles = not filters.config.filter_dotfiles return reloaders.reload_explorer() end diff --git a/lua/nvim-tree/explorer/common.lua b/lua/nvim-tree/explorer/common.lua new file mode 100644 index 00000000..deec0246 --- /dev/null +++ b/lua/nvim-tree/explorer/common.lua @@ -0,0 +1,11 @@ +local uv = vim.loop + +local M = {} + +function M.has_one_child_folder(node) + return #node.nodes == 1 + and node.nodes[1].nodes + and uv.fs_access(node.nodes[1].absolute_path, 'R') +end + +return M diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index 6cadae5a..cbc1f635 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -2,8 +2,10 @@ local api = vim.api local uv = vim.loop local utils = require'nvim-tree.utils' -local eutils = require'nvim-tree.explorer.utils' local builders = require'nvim-tree.explorer.node-builders' +local common = require'nvim-tree.explorer.common' +local sorters = require"nvim-tree.explorer.sorters" +local filters = require"nvim-tree.explorer.filters" local M = {} @@ -19,7 +21,7 @@ local function populate_children(handle, cwd, node, status) local abs = utils.path_join({cwd, name}) t = get_type_from(t, abs) - if not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then + if not filters.should_ignore(abs) and not filters.should_ignore_git(abs, status.files) then if t == 'directory' and uv.fs_access(abs, 'R') then table.insert(node.nodes, builders.folder(abs, name, status, node_ignored)) elseif t == 'file' then @@ -51,7 +53,7 @@ function M.explore(node, status) populate_children(handle, cwd, node, status) local is_root = node.cwd ~= nil - local child_folder_only = eutils.has_one_child_folder(node) and node.nodes[1] + local child_folder_only = common.has_one_child_folder(node) and node.nodes[1] if vim.g.nvim_tree_group_empty == 1 and not is_root and child_folder_only then node.group_next = child_folder_only local ns = M.explore(child_folder_only, status) @@ -59,7 +61,7 @@ function M.explore(node, status) return ns end - utils.merge_sort(node.nodes, eutils.node_comparator) + sorters.merge_sort(node.nodes, sorters.node_comparator) return node.nodes end diff --git a/lua/nvim-tree/explorer/utils.lua b/lua/nvim-tree/explorer/filters.lua similarity index 56% rename from lua/nvim-tree/explorer/utils.lua rename to lua/nvim-tree/explorer/filters.lua index f0c3ca0a..04b793fe 100644 --- a/lua/nvim-tree/explorer/utils.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -1,48 +1,17 @@ -local uv = vim.loop - local utils = require'nvim-tree.utils' local M = { ignore_list = {}, exclude_list = {}, - node_comparator = nil, } -function M.node_comparator_name(a, b) - if not (a and b) then - return true +local function is_excluded(path) + for _, node in ipairs(M.exclude_list) do + if path:match(node) then + return true + end end - if a.nodes and not b.nodes then - return true - elseif not a.nodes and b.nodes then - return false - end - - return a.name:lower() <= b.name:lower() -end - -function M.node_comparator_modification_time(a, b) - if not (a and b) then - return true - end - if a.nodes and not b.nodes then - return true - elseif not a.nodes and b.nodes then - return false - end - - local last_modified_a = 0 - local last_modified_b = 0 - - if a.fs_stat ~= nil then - last_modified_a = a.fs_stat.mtime.sec - end - - if b.fs_stat ~= nil then - last_modified_b = b.fs_stat.mtime.sec - end - - return last_modified_a <= last_modified_b + return false end ---Check if the given path should be ignored. @@ -51,10 +20,8 @@ end function M.should_ignore(path) local basename = utils.path_basename(path) - for _, node in ipairs(M.exclude_list) do - if path:match(node) then - return false - end + if is_excluded(path) then + return false end if M.config.filter_dotfiles then @@ -85,12 +52,7 @@ end function M.should_ignore_git(path, status) return M.config.filter_ignored and (M.config.filter_git_ignored and status and status[path] == '!!') -end - -function M.has_one_child_folder(node) - return #node.nodes == 1 - and node.nodes[1].nodes - and uv.fs_access(node.nodes[1].absolute_path, 'R') + and not is_excluded(path) end function M.setup(opts) @@ -98,7 +60,6 @@ function M.setup(opts) filter_ignored = true, filter_dotfiles = opts.filters.dotfiles, filter_git_ignored = opts.git.ignore, - sort_by = opts.sort_by, } M.exclude_list = opts.filters.exclude @@ -109,12 +70,6 @@ function M.setup(opts) M.ignore_list[filter_name] = true end end - - if M.config.sort_by == "modification_time" then - M.node_comparator = M.node_comparator_modification_time - else - M.node_comparator = M.node_comparator_name - end end return M diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 1903d6c0..8d13f5a4 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -31,7 +31,8 @@ function Explorer:expand(node) end function M.setup(opts) - require"nvim-tree.explorer.utils".setup(opts) + require"nvim-tree.explorer.filters".setup(opts) + require"nvim-tree.explorer.sorters".setup(opts) end M.Explorer = Explorer diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index b3a58ed7..c3a2dcc3 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -2,8 +2,10 @@ local api = vim.api local uv = vim.loop local utils = require'nvim-tree.utils' -local eutils = require'nvim-tree.explorer.utils' local builders = require'nvim-tree.explorer.node-builders' +local common = require'nvim-tree.explorer.common' +local filters = require'nvim-tree.explorer.filters' +local sorters = require'nvim-tree.explorer.sorters' local M = {} @@ -51,7 +53,7 @@ function M.reload(node, status) local abs = utils.path_join({cwd, name}) t = t or (uv.fs_stat(abs) or {}).type - if not eutils.should_ignore(abs) and not eutils.should_ignore_git(abs, status.files) then + if not filters.should_ignore(abs) and not filters.should_ignore_git(abs, status.files) then child_names[abs] = true if not nodes_by_path[abs] then if t == 'directory' and uv.fs_access(abs, 'R') then @@ -76,7 +78,7 @@ function M.reload(node, status) )) local is_root = node.cwd ~= nil - local child_folder_only = eutils.has_one_child_folder(node) and node.nodes[1] + local child_folder_only = common.has_one_child_folder(node) and node.nodes[1] if vim.g.nvim_tree_group_empty == 1 and not is_root and child_folder_only then node.group_next = child_folder_only local ns = M.reload(child_folder_only, status) @@ -84,7 +86,7 @@ function M.reload(node, status) return ns end - utils.merge_sort(node.nodes, eutils.node_comparator) + sorters.merge_sort(node.nodes, sorters.node_comparator) return node.nodes end diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua new file mode 100644 index 00000000..2e8bb350 --- /dev/null +++ b/lua/nvim-tree/explorer/sorters.lua @@ -0,0 +1,122 @@ +local M = { + sort_by = nil, + node_comparator = nil, +} + +---Create a shallow copy of a portion of a list. +---@param t table +---@param first integer First index, inclusive +---@param last integer Last index, inclusive +---@return table +local function tbl_slice(t, first, last) + local slice = {} + for i = first, last or #t, 1 do + table.insert(slice, t[i]) + end + + return slice +end + +local function merge(t, first, mid, last, comparator) + local n1 = mid - first + 1 + local n2 = last - mid + local ls = tbl_slice(t, first, mid) + local rs = tbl_slice(t, mid + 1, last) + local i = 1 + local j = 1 + local k = first + + while (i <= n1 and j <= n2) do + if comparator(ls[i], rs[j]) then + t[k] = ls[i] + i = i + 1 + else + t[k] = rs[j] + j = j + 1 + end + k = k + 1 + end + + while i <= n1 do + t[k] = ls[i] + i = i + 1 + k = k + 1 + end + + while j <= n2 do + t[k] = rs[j] + j = j + 1 + k = k + 1 + end +end + +local function split_merge(t, 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) +end + +---Perform a merge sort on a given list. +---@param t any[] +---@param comparator function|nil +function M.merge_sort(t, comparator) + if not comparator then + comparator = function (left, right) + return left < right + end + end + + split_merge(t, 1, #t, comparator) +end + +function M.node_comparator_name(a, b) + if not (a and b) then + return true + end + if a.nodes and not b.nodes then + return true + elseif not a.nodes and b.nodes then + return false + end + + return a.name:lower() <= b.name:lower() +end + +function M.node_comparator_modification_time(a, b) + if not (a and b) then + return true + end + if a.nodes and not b.nodes then + return true + elseif not a.nodes and b.nodes then + return false + end + + local last_modified_a = 0 + local last_modified_b = 0 + + if a.fs_stat ~= nil then + last_modified_a = a.fs_stat.mtime.sec + end + + if b.fs_stat ~= nil then + last_modified_b = b.fs_stat.mtime.sec + end + + return last_modified_a <= last_modified_b +end + +function M.setup(opts) + M.sort_by = opts.sort_by + if M.sort_by == "modification_time" then + M.node_comparator = M.node_comparator_modification_time + else + M.node_comparator = M.node_comparator_name + end +end + +return M diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index f468a7f8..b1968665 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -113,76 +113,6 @@ function M.find_node(_nodes, _fn) return node, i end ----Create a shallow copy of a portion of a list. ----@param t table ----@param first integer First index, inclusive ----@param last integer Last index, inclusive ----@return table -function M.tbl_slice(t, first, last) - local slice = {} - for i = first, last or #t, 1 do - table.insert(slice, t[i]) - end - - return slice -end - -local function merge(t, first, mid, last, comparator) - local n1 = mid - first + 1 - local n2 = last - mid - local ls = M.tbl_slice(t, first, mid) - local rs = M.tbl_slice(t, mid + 1, last) - local i = 1 - local j = 1 - local k = first - - while (i <= n1 and j <= n2) do - if comparator(ls[i], rs[j]) then - t[k] = ls[i] - i = i + 1 - else - t[k] = rs[j] - j = j + 1 - end - k = k + 1 - end - - while i <= n1 do - t[k] = ls[i] - i = i + 1 - k = k + 1 - end - - while j <= n2 do - t[k] = rs[j] - j = j + 1 - k = k + 1 - end -end - -local function split_merge(t, 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) -end - ----Perform a merge sort on a given list. ----@param t any[] ----@param comparator function|nil -function M.merge_sort(t, comparator) - if not comparator then - comparator = function (left, right) - return left < right - end - end - - split_merge(t, 1, #t, comparator) -end - ---Matching executable files in Windows. ---@param ext string ---@return boolean