Skip to content

feat: Mixin Sorter (#1565) Self Solved #1566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions doc/nvim-tree-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ Subsequent calls to setup will replace the previous configuration.
number = false,
relativenumber = false,
signcolumn = "yes",
-- @deprecated
mappings = {
custom_only = false,
list = {
Expand Down Expand Up @@ -426,9 +425,25 @@ if the tree was previously open.

*nvim-tree.sort_by*
Changes how files within the same directory are sorted.
Can be one of 'name', 'case_sensitive', 'modification_time' or 'extension'.
Type: `string`, Default: `"name"`

Can be one of `name`, `case_sensitive`, `modification_time`, `extension` or a
function.
Type: `string` | `function(nodes)`, Default: `"name"`

Function is passed a table of nodes to be sorted, each node containing:
- `absolute_path`: `string`
- `executable`: `boolean`
- `extension`: `string`
- `link_to`: `string`
- `name`: `string`
- `type`: `"directory"` | `"file"` | `"link"`

Example: sort by name length: >
local sort_by = function(nodes)
table.sort(nodes, function(a, b)
return #a.name < #b.name
end)
end
<
*nvim-tree.hijack_unnamed_buffer_when_opening*
Opens in place of the unnamed buffer if it's empty.
Type: `boolean`, Default: `false`
Expand Down
1 change: 1 addition & 0 deletions lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ local FIELD_OVERRIDE_TYPECHECK = {
height = { string = true, ["function"] = true, number = true },
remove_keymaps = { boolean = true, table = true },
on_attach = { ["function"] = true, string = true },
sort_by = { ["function"] = true, string = true },
}

local function validate_options(conf)
Expand Down
53 changes: 47 additions & 6 deletions lua/nvim-tree/explorer/sorters.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,52 @@ end
---@param t any[]
---@param comparator function|nil
function M.merge_sort(t, comparator)
if not comparator then
comparator = function(left, right)
return left < right
if type(M.sort_by) == "function" then
local t_user = {}
local origin_index = {}

for _, n in ipairs(t) do
table.insert(t_user, {
absolute_path = n.absolute_path,
executable = n.executable,
extension = n.extension,
link_to = n.link_to,
name = n.name,
type = n.type,
})
table.insert(origin_index, n)
end
end

split_merge(t, 1, #t, comparator)
M.sort_by(t_user)

-- do merge sort for prevent memory exceed
local user_index = {}
for i, v in ipairs(t_user) do
if type(v.absolute_path) == "string" and user_index[v.absolute_path] == nil then
user_index[v.absolute_path] = i
end
end

-- if missing value found, then using origin_index
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]

if type(a_index) == "number" and type(b_index) == "number" then
return a_index <= b_index
end
return (a_index or 0) <= (b_index or 0)
end

split_merge(t, 1, #t, mini_comparator) -- sort by user order
else
if not comparator then
comparator = function(left, right)
return left < right
end
end
split_merge(t, 1, #t, comparator)
end
end

local function node_comparator_name_ignorecase_or_not(a, b, ignorecase)
Expand Down Expand Up @@ -150,7 +189,9 @@ end

function M.setup(opts)
M.sort_by = opts.sort_by
if M.sort_by == "modification_time" then
if M.sort_by and type(M.sort_by) == "function" then
M.node_comparator = M.sort_by
elseif M.sort_by == "modification_time" then
M.node_comparator = M.node_comparator_modification_time
elseif M.sort_by == "case_sensitive" then
M.node_comparator = M.node_comparator_name_case_sensisive
Expand Down