From 9310db08736e77c751c987c4508d502b816cabf2 Mon Sep 17 00:00:00 2001 From: Akmadan23 Date: Fri, 11 Aug 2023 16:07:59 +0200 Subject: [PATCH 1/4] feat(#2364): add option to show files first --- doc/nvim-tree-lua.txt | 6 +++ lua/nvim-tree.lua | 1 + lua/nvim-tree/explorer/sorters.lua | 75 +++++++++++++++++------------- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 29565bc6b98..2fcf86d9cf0 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -317,6 +317,7 @@ applying configuration. sort = { sorter = "name", folders_first = true, + files_first = false, }, root_dirs = {}, prefer_startup_root = false, @@ -605,6 +606,11 @@ File and folder sorting options. function. Type: `boolean`, Default: `true` + *nvim-tree.sort.files_first* + Sort files before folders. Has no effect when |nvim-tree.sort.sorter| is a + function. If set to `true` it overrides |nvim-tree.sort.folders_first|. + Type: `boolean`, Default: `false` + *nvim-tree.hijack_unnamed_buffer_when_opening* Opens in place of the unnamed buffer if it's empty. Type: `boolean`, Default: `false` diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index d07a4870a5e..bc5b2881315 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -373,6 +373,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS sort = { sorter = "name", folders_first = true, + files_first = false, }, root_dirs = {}, prefer_startup_root = false, diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index e685d6c0c72..dc87272d1d1 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -23,6 +23,31 @@ local function tbl_slice(t, first, last) return slice end +---Evaluate `sort.folders_first` and `sort.files_first` +---@param a table +---@param b table +---@param third_option_callback function|nil function should return `boolean`. Evaluated only if necessary +---@return boolean|nil +local function folders_or_files_first(a, b, third_option_callback) + local x = nil + + if a.nodes and not b.nodes then + x = true + elseif not a.nodes and b.nodes then + x = false + elseif a.nodes and b.nodes and third_option_callback ~= nil then + x = third_option_callback() + end + + if x ~= nil then + if M.config.sort.files_first then + return not x + elseif M.config.sort.folders_first then + return x + end + end +end + local function merge(t, first, mid, last, comparator) local n1 = mid - first + 1 local n2 = last - mid @@ -124,12 +149,9 @@ local function node_comparator_name_ignorecase_or_not(a, b, ignorecase) return true end - if M.config.sort.folders_first then - if a.nodes and not b.nodes then - return true - elseif not a.nodes and b.nodes then - return false - end + local early_return = folders_or_files_first(a, b) + if early_return ~= nil then + return early_return end if ignorecase then @@ -152,12 +174,9 @@ function C.modification_time(a, b) return true end - if M.config.sort.folders_first then - if a.nodes and not b.nodes then - return true - elseif not a.nodes and b.nodes then - return false - end + local early_return = folders_or_files_first(a, b) + if early_return ~= nil then + return early_return end local last_modified_a = 0 @@ -180,14 +199,12 @@ function C.suffix(a, b) end -- directories go first - if M.config.sort.folders_first then - 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 + local early_return = folders_or_files_first(a, b, function() + return C.name(a, b) + end) + + if early_return ~= nil then + return early_return end -- dotfiles go second @@ -231,12 +248,9 @@ function C.extension(a, b) return true end - if M.config.sort.folders_first then - if a.nodes and not b.nodes then - return true - elseif not a.nodes and b.nodes then - return false - end + local early_return = folders_or_files_first(a, b) + if early_return ~= nil then + return early_return end if a.extension and not b.extension then @@ -259,12 +273,9 @@ function C.filetype(a, b) local b_ft = vim.filetype.match { filename = b.name } -- directories first - if M.config.sort.folders_first then - if a.nodes and not b.nodes then - return true - elseif not a.nodes and b.nodes then - return false - end + local early_return = folders_or_files_first(a, b) + if early_return ~= nil then + return early_return end -- one is nil, the other wins From e5624a98b98ff50cb516e6f53a0add85564c7a10 Mon Sep 17 00:00:00 2001 From: Azad <49314270+Akmadan23@users.noreply.github.com> Date: Mon, 14 Aug 2023 19:51:32 +0200 Subject: [PATCH 2/4] Refactor `folders_or_files_first` function --- lua/nvim-tree/explorer/sorters.lua | 36 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index dc87272d1d1..7aa0402bbf2 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -24,27 +24,29 @@ local function tbl_slice(t, first, last) end ---Evaluate `sort.folders_first` and `sort.files_first` ----@param a table ----@param b table ----@param third_option_callback function|nil function should return `boolean`. Evaluated only if necessary +---@param a table node +---@param b table node +---@param fallback function|nil function should return `boolean`. Evaluated only if necessary ---@return boolean|nil -local function folders_or_files_first(a, b, third_option_callback) - local x = nil +local function folders_or_files_first(a, b, fallback) + local a_and_not_b, not_a_and_b + + if M.config.sort.files_first then + a_and_not_b = false + not_a_and_b = true + elseif M.config.sort.folders_first then + a_and_not_b = true + not_a_and_b = false + else + return + end if a.nodes and not b.nodes then - x = true + return a_and_not_b elseif not a.nodes and b.nodes then - x = false - elseif a.nodes and b.nodes and third_option_callback ~= nil then - x = third_option_callback() - end - - if x ~= nil then - if M.config.sort.files_first then - return not x - elseif M.config.sort.folders_first then - return x - end + return not_a_and_b + elseif fallback and a.nodes and b.nodes then + return fallback() end end From 0a2d315a9c425546572fc56c9ef37d1ee8643670 Mon Sep 17 00:00:00 2001 From: Azad <49314270+Akmadan23@users.noreply.github.com> Date: Sun, 20 Aug 2023 15:06:00 +0200 Subject: [PATCH 3/4] Improve readability --- lua/nvim-tree/explorer/sorters.lua | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index 7aa0402bbf2..e9ddf8f1efa 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -29,23 +29,18 @@ end ---@param fallback function|nil function should return `boolean`. Evaluated only if necessary ---@return boolean|nil local function folders_or_files_first(a, b, fallback) - local a_and_not_b, not_a_and_b - - if M.config.sort.files_first then - a_and_not_b = false - not_a_and_b = true - elseif M.config.sort.folders_first then - a_and_not_b = true - not_a_and_b = false - else + if not (M.config.sort.folders_first or M.config.sort.files_first) then return end - if a.nodes and not b.nodes then - return a_and_not_b - elseif not a.nodes and b.nodes then - return not_a_and_b + if not a.nodes and b.nodes then + -- file <> folder + return M.config.sort.files_first + elseif a.nodes and not b.nodes then + -- folder <> file + return not M.config.sort.files_first elseif fallback and a.nodes and b.nodes then + -- folder <> folder return fallback() end end From 833dc5b9902909f7efbd6241845203524e8ed559 Mon Sep 17 00:00:00 2001 From: Azad <49314270+Akmadan23@users.noreply.github.com> Date: Sun, 20 Aug 2023 19:35:38 +0200 Subject: [PATCH 4/4] Remove `fallback` from `folders_or_files_first` function --- lua/nvim-tree/explorer/sorters.lua | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index e9ddf8f1efa..f2a259bc0bb 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -26,9 +26,8 @@ end ---Evaluate `sort.folders_first` and `sort.files_first` ---@param a table node ---@param b table node ----@param fallback function|nil function should return `boolean`. Evaluated only if necessary ---@return boolean|nil -local function folders_or_files_first(a, b, fallback) +local function folders_or_files_first(a, b) if not (M.config.sort.folders_first or M.config.sort.files_first) then return end @@ -39,9 +38,6 @@ local function folders_or_files_first(a, b, fallback) elseif a.nodes and not b.nodes then -- folder <> file return not M.config.sort.files_first - elseif fallback and a.nodes and b.nodes then - -- folder <> folder - return fallback() end end @@ -196,12 +192,11 @@ function C.suffix(a, b) end -- directories go first - local early_return = folders_or_files_first(a, b, function() - return C.name(a, b) - end) - + local early_return = folders_or_files_first(a, b) if early_return ~= nil then return early_return + elseif a.nodes and b.nodes then + return C.name(a, b) end -- dotfiles go second