From 027e5234312581efdafa7741603234232e485103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sindre=20T=2E=20Str=C3=B8m?= Date: Thu, 22 Apr 2021 21:12:47 +0200 Subject: [PATCH] feat: Sort nodes sensibly (#334) --- lua/nvim-tree/populate.lua | 18 ++++++++++ lua/nvim-tree/utils.lua | 72 +++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/lua/nvim-tree/populate.lua b/lua/nvim-tree/populate.lua index cc9ee881..18f76c74 100644 --- a/lua/nvim-tree/populate.lua +++ b/lua/nvim-tree/populate.lua @@ -106,6 +106,16 @@ local function should_group(cwd, dirs, files, links) return false end +local function node_comparator(a, b) + if a.entries and not b.entries then + return true + elseif not a.entries and b.entries then + return false + end + + return a.name:lower() <= b.name:lower() +end + local function gen_ignore_check(cwd) if not cwd then cwd = luv.cwd() end local ignore_list = {} @@ -231,12 +241,14 @@ function M.refresh_entries(entries, cwd, parent_node) local prev = nil local change_prev + local new_nodes_added = false for _, e in ipairs(all) do for _, name in ipairs(e.entries) do change_prev = true if not named_entries[name] then local n = e.fn(cwd, name) if e.check(n.link_to, n.absolute_path) then + new_nodes_added = true git.invalidate_gitignore_map(n.absolute_path) idx = 1 if prev then @@ -258,6 +270,10 @@ function M.refresh_entries(entries, cwd, parent_node) if next_node then table.insert(entries, 1, next_node) end + + if new_nodes_added then + utils.merge_sort(entries, node_comparator) + end end function M.populate(entries, cwd, parent_node) @@ -326,6 +342,8 @@ function M.populate(entries, cwd, parent_node) return end + utils.merge_sort(entries, node_comparator) + git.update_status(entries, cwd, parent_node) end diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index c09e967e..ab55de53 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -1,5 +1,5 @@ local M = {} -local uv = vim.loop -- or require("luv") ? i dont understand +local uv = vim.loop local api = vim.api function M.path_to_matching_str(path) @@ -83,4 +83,74 @@ function M.find_node(nodes, fn) return nil, 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 (a, b) + return a < b + end + end + + split_merge(t, 1, #t, comparator) +end + return M