-
-
Notifications
You must be signed in to change notification settings - Fork 626
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
Conversation
adding `mixin` sort options for `rust` like package systems ``` package.rs package/ __inside__ lib.rs lib/ _inside_ a.rs b.rs module.rs ```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This additional sorting functionality is very useful, however mixin is very specific.
It would be more useful for the user to provide their own sorting function:
*nvim-tree.sort_by*
Changes how files within the same directory are sorted.
Can be one of 'name', 'case_sensitive', 'modification_time',
'extension' or a function.
Type: `string` or `function`, Default: `"name"`
sort_by = function(nodes)
insert a simple example that sorts, say, file name length
end
Thanks For Review 👍🏻 that will be more better! i think it will be better not to use default merge sort function when user provide function (MEMO) todo ] 기본적인 정렬을 포함하여, 함수를 인자로 받아 해당 함수로 정렬 함수를 대체하도록 소스수정 |
Do you mean the user provides a sort_by = function(a, b)
-- return a <= b
end Yes, please build that. |
Please grant me push access to your repo so that I can help you with the documentation. |
sure! invited! |
Thanks. I'll wait for your changes then write the help doc. |
``` *nvim-tree.sort_by* Changes how files within the same directory are sorted. Can be one of 'name', 'case_sensitive', 'modification_time' or 'extension', 'function'. > sort_by = function(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 end Type: `string | function(a, b)`, Default: `"name"` *nvim-tree.after_sort* Related to nvim-tree.sort_by, this function runs without mergesort. Can be defined by your own after-sort works. Type: `function(table)`, Default: `disable` > after_sort = function(t) local i = 1 while i <= #t do if t[i] and t[i].nodes then local j = i + 1 while j <= #t do if t[j] and not t[j].nodes and t[i].name:lower() == t[j].name:lower():match "(.+)%..+$" then local change_target = t[j] table.remove(t, j) table.insert(t, i, change_target) break end j = j + 1 end end i = i + 1 end end ```
@alex-courtis i've changed something! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Questions I have:
- Do we need to provide a comparator and a merge sort function?
- The input to a comparator can be sanitised by passing in a cut-down copy of the nodes. The input to
after_sort
cannot be sanitised in this way, and would allow users to directly modify the nodes.
Let me consider...
doc/nvim-tree-lua.txt
Outdated
Type: `string | function(a, b)`, Default: `"name"` | ||
|
||
*nvim-tree.after_sort* | ||
Related to nvim-tree.sort_by, this function runs without mergesort. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this? Is it because mixin sort cannot be achieved via a comparator?
lua/nvim-tree/explorer/sorters.lua
Outdated
@@ -73,6 +73,9 @@ function M.merge_sort(t, comparator) | |||
end | |||
|
|||
split_merge(t, 1, #t, comparator) | |||
if M.after_sort then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to run the comparator and split_merge first?
We should call the user's after_sort instead of M.merge_sort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMZ,,, I miss understood..
I thought 'sort_by' comparator must be run through merge sort function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMZ,,, I miss understood.. I thought 'sort_by' comparator must be run through merge sort function
We would need to try it.
Please try explorer.lua
and reload.lua
calling after_sort
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i will try this too
sort_by parameter can be function. ``` lua sort_by = function(t) local sorters = require "nvim-tree.explorer.sorters" local comparator = sorters.retrieve_comparator("name") sorters.split_merge(t, 1, #t, comparator) -- run default merge_sort local i = 1 while i <= #t do if t[i] and t[i].nodes then local j = i + 1 while j <= #t do if t[j] and not t[j].nodes and t[i].name:lower() == t[j].name:lower():match "(.+)%..+$" then local change_target = t[j] table.remove(t, j) table.insert(t, i, change_target) break end j = j + 1 end end i = i + 1 end end, ```
Reply to Answer:
|
That is thoughtful, however it adds complexity and exposes non-API functionality. If the user is to write their own sort, they will just have to do everything themselves. The doc can contain a simple example that use
Existing Something like this. The TODO is for you ;) function M.merge_sort(t, comparator)
if type(M.sort_by) == "function" then
local t_user = {}
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,
})
end
-- returns an array of absolute_path that represents the order
local user_order = M.sort_by(t_user)
-- TODO reorder t based on user_order
else
if not comparator then
comparator = function(left, right)
return left < right
end
end
M.split_merge(t, 1, #t, comparator)
end
end |
ohhhhhh thx for make it simple good first issue for me :) I've been using this extension so much usefully, so I really wanted to participate as a contributor.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested:
- empty sort_by
- nil sort_by - FAIL
- partial sort_by
- complete sort_by
- duplicates in sort_by (garbage in garbage out)
- nonexistent absolute paths in sort_by
- huge (double size) sort_by - FAIL
Pushed update to doc for function params/return; add more complex example.
apply merge_sort check nil & type for senitize
for performance, create index once, using index to re-ordering
add complex example
dear @alex-courtis,
Best regards, 👍🏻 |
|
Fantastic! That works well.
Sorry, we will only provide a trivial example. Users can devise their own solutions. I have reverted 26e4066 |
After considering, I realise I made a huge mistake by asking the user to return a table of absolute path. The user now simply sorts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All tested OK.
I'm happy; if you're happy I will merge.
excited to die, hhh |
thanksssss have a nice day!!!! |
Thank you so much for all your work! |
Hi sorry to chime in here: is possible to dynamically sort the nodes once a tree is opened? i.e I would like to have a map to "toggle"sorting between name, time etc. AFAICT sort_by currently is only available as part of |
Your You could change the sorting by storing your own state. Hacky example: local sort_by = function(nodes)
table.sort(nodes, function(a, b)
if vim.g.my_sort_by == "length" then
-- sort by name length
return #a.name < #b.name
else
-- sort by name alphanumerically
return a.name <= b.name
end
end)
end |
I'm afraid I don't quite follow. Is it possible to place that function behind a mapping to actually toggle sorting? My ideal use is to define something like the following map: { key = 'T', cb = ':lua NvimTreeConfig.toggle_sort("time")<CR>' }, where by pressing |
The callback needs to be a lua function.
Something like this to set your sort then refresh the tree: {
key = "T",
action = "sort_by_time",
action_cb = function()
vim.g.my_sort_by = "time"
require("nvim-tree.api").tree.reload()
end
}, It doesn't have to be an nvim-tree mapping, however it is more convenient than defining a global mapping. |
I tried doing the following: local tree_api = require('nvim-tree.api').tree
vim.g.my_sort_by = 'name'
require('nvim-tree').setup({
sort_by = vim.g.my_sort_by,
.....
local map_list = {
{
key = 'T',
action = 'sort_by_time',
action_cb = function()
vim.g.my_sort_by = 'modification_time'
tree_api.reload()
end,
},
} However when I open a nvim tree and press |
You need to set Complete working example to run with |
Hi. Thanks for the reply. I tried: local sorters = require('nvim-tree.explorer.sorters')
local my_sort_by_mode = 'name'
local my_sort_by_function = function(nodes)
print('sorting by ' .. my_sort_by_mode)
table.sort(nodes, function(a, b)
if my_sort_by_mode == 'time' then
return sorters.node_comparator_modification_time(a, b)
else
return sorters.node_comparator_name_ignorecase(a, b)
end
end)
end
local my_sort_by_action_callback = function()
if my_sort_by_mode == 'time' then
my_sort_by_mode = 'name'
else
my_sort_by_mode = 'time'
end
require('nvim-tree.api').tree.reload()
end But:
At the end of the day my request is: can you add some api function to easily toggle sorting? I imagine something like Thanks for the help and patience. |
That is problematic in that sort states and the available methods need to be configured and tracked. How about this: *nvim-tree.sort_by*
Changes how files within the same directory are sorted.
Can be a method: `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"`
Function should return a table with the nodes sorted or one of the method
strings defined above.
Example: sort by name length: >
local my_sort_by = function(nodes)
table.sort(nodes, function(a, b)
return #a.name < #b.name
end)
end
<
Example: toggle between `name` and `extension` >
local my_sort_method = "name"
local my_sort_by = function(nodes)
if sort_method == "name" then
sort_method = "extension"
else
sort_method = "name"
end
return my_sort_method
end
< |
resolves #1490 #1565
adding
mixin
sort options forrust
like package systems