diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 2c93ae0fb00..4952a5b8e3e 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -568,8 +568,10 @@ Reloads the explorer every time a buffer is written to. *nvim-tree.sort_by* Changes how files within the same directory are sorted. -Can be one of `name`, `case_sensitive`, `modification_time`, `extension`, -`filetype` or a function. +Can be one of `"name"`, `"case_sensitive"`, `"modification_time"`, `"extension"`, +`"suffix"`, `"filetype"` or a function. +`"extension"` uses all suffixes e.g. `foo.tar.gz` -> `.tar.gz` +`"suffix"` uses the last e.g. `.gz` Type: `string` | `function(nodes)`, Default: `"name"` Function may perform a sort or return a string with one of the above diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index 5f18e5afa30..a3a2af2add6 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -168,6 +168,56 @@ function C.modification_time(a, b) return last_modified_b <= last_modified_a end +function C.suffix(a, b) + if not (a and b) then + return true + end + + -- directories go first + if a.nodes and not b.nodes then + return true + elseif not a.nodes and b.nodes then + return false + elseif a.nodes and b.nodes then + return C.name(a, b) + end + + -- dotfiles go second + if a.name:sub(1, 1) == "." and b.name:sub(1, 1) ~= "." then + return true + 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) + end + + -- unsuffixed go third + local a_suffix_ndx = a.name:find "%.%w+$" + local b_suffix_ndx = b.name:find "%.%w+$" + + if not a_suffix_ndx and b_suffix_ndx then + return true + 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) + end + + -- finally, compare by suffixes + local a_suffix = a.name:sub(a_suffix_ndx) + local b_suffix = b.name:sub(b_suffix_ndx) + + if a_suffix and not b_suffix then + return true + elseif not a_suffix and b_suffix then + return false + elseif a_suffix:lower() == b_suffix:lower() then + return C.name(a, b) + end + + return a_suffix:lower() < b_suffix:lower() +end + function C.extension(a, b) if not (a and b) then return true