From cc2d8c747546716f5b7ca45c038013544486d106 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Tue, 23 Jul 2024 18:49:39 +0200 Subject: [PATCH 1/6] feat(#2827): Multi Instance: Refactor: nvim-tree.live-filter --- lua/nvim-tree/core.lua | 3 +- lua/nvim-tree/explorer/init.lua | 2 + lua/nvim-tree/{ => explorer}/live-filter.lua | 68 +++++++++++--------- 3 files changed, 42 insertions(+), 31 deletions(-) rename lua/nvim-tree/{ => explorer}/live-filter.lua (72%) diff --git a/lua/nvim-tree/core.lua b/lua/nvim-tree/core.lua index 9a27458275e..50072d40bb5 100644 --- a/lua/nvim-tree/core.lua +++ b/lua/nvim-tree/core.lua @@ -1,6 +1,5 @@ local events = require "nvim-tree.events" local explorer = require "nvim-tree.explorer" -local live_filter = require "nvim-tree.live-filter" local view = require "nvim-tree.view" local log = require "nvim-tree.log" @@ -45,7 +44,7 @@ function M.get_nodes_starting_line() if view.is_root_folder_visible(M.get_cwd()) then offset = offset + 1 end - if live_filter.filter then + if TreeExplorer and TreeExplorer.live_filter.filter then return offset + 1 end return offset diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 25ad242ecf0..391a7b96aa0 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -3,6 +3,7 @@ local notify = require "nvim-tree.notify" local watch = require "nvim-tree.explorer.watch" local explorer_node = require "nvim-tree.explorer.node" local Marks = require "nvim-tree.marks" +local LiveFilter = require "nvim-tree.live-filter" local M = {} @@ -38,6 +39,7 @@ function Explorer.new(path) absolute_path = path, nodes = {}, open = true, + live_filter = LiveFilter:new(M.config), marks = Marks:new(), }, Explorer) explorer.watcher = watch.create_watcher(explorer) diff --git a/lua/nvim-tree/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua similarity index 72% rename from lua/nvim-tree/live-filter.lua rename to lua/nvim-tree/explorer/live-filter.lua index 350043aae6b..fa32916009d 100644 --- a/lua/nvim-tree/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -3,9 +3,16 @@ local utils = require "nvim-tree.utils" local Iterator = require "nvim-tree.iterators.node-iterator" local filters = require "nvim-tree.explorer.filters" -local M = { - filter = nil, -} +local LiveFilter = {} + +function LiveFilter:new(opts) + local o = {} + setmetatable(o, self) + self.__index = self + o.config = vim.deepcopy(opts.live_filter) + o.filter = nil + return o +end local function redraw() require("nvim-tree.renderer").draw() @@ -49,26 +56,27 @@ local function remove_overlay() overlay_bufnr = 0 overlay_winnr = 0 - if M.filter == "" then - M.clear_filter() + local explorer = require("nvim-tree.core").get_explorer() + if explorer and explorer.live_filter.filter == "" then + explorer.live_filter.clear_filter() end end ---@param node Node ---@return boolean -local function matches(node) +local function matches(self, node) if not filters.config.enable then return true end local path = node.absolute_path local name = vim.fn.fnamemodify(path, ":t") - return vim.regex(M.filter):match_str(name) ~= nil + return vim.regex(self.filter):match_str(name) ~= nil end ---@param node_ Node|nil -function M.apply_filter(node_) - if not M.filter or M.filter == "" then +function LiveFilter:apply_filter(node_) + if not self.filter or self.filter == "" then reset_filter(node_) return end @@ -88,7 +96,7 @@ function M.apply_filter(node_) end end - local has_nodes = nodes and (M.always_show_folders or #nodes > filtered_nodes) + local has_nodes = nodes and (self.config.always_show_folders or #nodes > filtered_nodes) local ok, is_match = pcall(matches, node) node.hidden = not (has_nodes or (ok and is_match)) end @@ -98,9 +106,12 @@ end local function record_char() vim.schedule(function() - M.filter = vim.api.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1] - M.apply_filter() - redraw() + local explorer = require("nvim-tree.core").get_explorer() + if explorer then + explorer.live_filter.filter = vim.api.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1] + explorer.live_filter.apply_filter() + redraw() + end end) end @@ -120,17 +131,21 @@ local function configure_buffer_overlay() end ---@return integer -local function calculate_overlay_win_width() +local function calculate_overlay_win_width(explorer) local wininfo = vim.fn.getwininfo(view.get_winnr())[1] if wininfo then - return wininfo.width - wininfo.textoff - #M.prefix + return wininfo.width - wininfo.textoff - #explorer.live_filter.prefix end return 20 end local function create_overlay() + local explorer = require("nvim-tree.core").get_explorer() + if not explorer then + return + end if view.View.float.enable then -- don't close nvim-tree float when focus is changed to filter window vim.api.nvim_clear_autocmds { @@ -145,7 +160,7 @@ local function create_overlay() col = 1, row = 0, relative = "cursor", - width = calculate_overlay_win_width(), + width = calculate_overlay_win_width(explorer), height = 1, border = "none", style = "minimal", @@ -157,28 +172,28 @@ local function create_overlay() vim.api.nvim_buf_set_option(overlay_bufnr, "modifiable", true) ---@diagnostic disable-line: deprecated end - vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { M.filter }) + vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { explorer.live_filter.filter }) vim.cmd "startinsert" - vim.api.nvim_win_set_cursor(overlay_winnr, { 1, #M.filter + 1 }) + vim.api.nvim_win_set_cursor(overlay_winnr, { 1, #explorer.live_filter.filter + 1 }) end -function M.start_filtering() +function LiveFilter:start_filtering() view.View.live_filter.prev_focused_node = require("nvim-tree.lib").get_node_at_cursor() - M.filter = M.filter or "" + self.filter = self.filter or "" redraw() local row = require("nvim-tree.core").get_nodes_starting_line() - 1 - local col = #M.prefix > 0 and #M.prefix - 1 or 1 + local col = #self.prefix > 0 and #self.prefix - 1 or 1 view.set_cursor { row, col } -- needs scheduling to let the cursor move before initializing the window vim.schedule(create_overlay) end -function M.clear_filter() +function LiveFilter:clear_filter() local node = require("nvim-tree.lib").get_node_at_cursor() local last_node = view.View.live_filter.prev_focused_node - M.filter = nil + self.filter = nil reset_filter() redraw() @@ -189,9 +204,4 @@ function M.clear_filter() end end -function M.setup(opts) - M.prefix = opts.live_filter.prefix - M.always_show_folders = opts.live_filter.always_show_folders -end - -return M +return LiveFilter From 9deac32a40abc98764b72ac0e48c2a902fdea668 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Sun, 28 Jul 2024 10:16:02 +0200 Subject: [PATCH 2/6] refactor: all usages going through the explorer --- lua/nvim-tree.lua | 1 - lua/nvim-tree/api.lua | 13 ++++++++++--- lua/nvim-tree/explorer/explore.lua | 3 +-- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/explorer/reload.lua | 3 +-- lua/nvim-tree/renderer/builder.lua | 9 +++++---- lua/nvim-tree/utils.lua | 5 ++++- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 42c4a4f0cc5..be350fd21e7 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -837,7 +837,6 @@ function M.setup(conf) require("nvim-tree.view").setup(opts) require("nvim-tree.lib").setup(opts) require("nvim-tree.renderer").setup(opts) - require("nvim-tree.live-filter").setup(opts) require("nvim-tree.marks").setup(opts) require("nvim-tree.buffers").setup(opts) require("nvim-tree.help").setup(opts) diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index fdc1eb35808..af18320ee76 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -6,7 +6,6 @@ local actions = require "nvim-tree.actions" local appearance_diagnostics = require "nvim-tree.appearance.diagnostics" local events = require "nvim-tree.events" local help = require "nvim-tree.help" -local live_filter = require "nvim-tree.live-filter" local marks_navigation = require "nvim-tree.marks.navigation" local marks_bulk_delete = require "nvim-tree.marks.bulk-delete" local marks_bulk_trash = require "nvim-tree.marks.bulk-trash" @@ -265,8 +264,16 @@ Api.git.reload = wrap(actions.reloaders.reload_git) Api.events.subscribe = events.subscribe Api.events.Event = events.Event -Api.live_filter.start = wrap(live_filter.start_filtering) -Api.live_filter.clear = wrap(live_filter.clear_filter) +Api.live_filter.start = wrap_explorer(function(explorer) + return wrap(function(...) + return explorer.live_filter:start_filtering(...) + end) +end) +Api.live_filter.clear = wrap_explorer(function(explorer) + return wrap(function(...) + return explorer.live_filter:clear_filter(...) + end) +end) Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark")) Api.marks.list = wrap_explorer_member("marks", "get_marks") diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index 3d48f95a583..569d548f58b 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -2,7 +2,6 @@ local utils = require "nvim-tree.utils" local builders = require "nvim-tree.explorer.node-builders" local explorer_node = require "nvim-tree.explorer.node" local git = require "nvim-tree.git" -local live_filter = require "nvim-tree.live-filter" local log = require "nvim-tree.log" local Watcher = require "nvim-tree.watcher" @@ -82,7 +81,7 @@ function M.explore(node, status, parent) end parent.sorters:sort(node.nodes) - live_filter.apply_filter(node) + parent.live_filter:apply_filter(node) log.profile_end(profile) return node.nodes diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 82aa4098d0b..9c4f8e581a7 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -4,7 +4,7 @@ local watch = require "nvim-tree.explorer.watch" local explorer_node = require "nvim-tree.explorer.node" local Filters = require "nvim-tree.explorer.filters" local Marks = require "nvim-tree.marks" -local LiveFilter = require "nvim-tree.live-filter" +local LiveFilter = require "nvim-tree.explorer.live-filter" local Sorters = require "nvim-tree.explorer.sorters" local M = {} diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index 101a22cf000..9cd589ab1fb 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -1,7 +1,6 @@ local utils = require "nvim-tree.utils" local builders = require "nvim-tree.explorer.node-builders" local explorer_node = require "nvim-tree.explorer.node" -local live_filter = require "nvim-tree.live-filter" local git = require "nvim-tree.git" local log = require "nvim-tree.log" @@ -165,7 +164,7 @@ function M.reload(node, git_status) end explorer.sorters:sort(node.nodes) - live_filter.apply_filter(node) + explorer.live_filter:apply_filter(node) log.profile_end(profile) return node.nodes end diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 594ba03a25a..3d657d1748b 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -1,5 +1,4 @@ local core = require "nvim-tree.core" -local live_filter = require "nvim-tree.live-filter" local notify = require "nvim-tree.notify" local utils = require "nvim-tree.utils" local view = require "nvim-tree.view" @@ -352,7 +351,8 @@ end ---@private function Builder:get_nodes_number(nodes) - if not live_filter.filter then + local explorer = core.get_explorer() + if not explorer or not explorer.live_filter.filter then return #nodes end @@ -398,6 +398,7 @@ end ---@private function Builder:build_header() + local explorer = core.get_explorer() if view.is_root_folder_visible(core.get_cwd()) then local root_name = self:format_root_name(M.opts.renderer.root_folder_label) table.insert(self.lines, root_name) @@ -405,8 +406,8 @@ function Builder:build_header() self.index = 1 end - if live_filter.filter then - local filter_line = string.format("%s/%s/", M.opts.live_filter.prefix, live_filter.filter) + if explorer and explorer.live_filter.filter then + local filter_line = string.format("%s/%s/", M.opts.live_filter.prefix, explorer.live_filter.filter) table.insert(self.lines, filter_line) local prefix_length = string.len(M.opts.live_filter.prefix) self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length) diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index 30f34edc44a..2be71d81462 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -112,7 +112,10 @@ function M.find_node(nodes, fn) end) :iterate() i = require("nvim-tree.view").is_root_folder_visible() and i or i - 1 - i = require("nvim-tree.live-filter").filter and i + 1 or i + local explorer = require("nvim-tree.core").get_explorer() + if explorer and explorer.live_filter.filter then + i = i + 1 + end return node, i end From a634a1bb4d4110d0d79ecf6f48662dac649d9c52 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Sun, 28 Jul 2024 11:19:37 +0200 Subject: [PATCH 3/6] fix: api and filtration --- lua/nvim-tree/api.lua | 14 ++++++++------ lua/nvim-tree/explorer/live-filter.lua | 21 +++++++++++---------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index af18320ee76..df3cb1e5415 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -264,15 +264,17 @@ Api.git.reload = wrap(actions.reloaders.reload_git) Api.events.subscribe = events.subscribe Api.events.Event = events.Event -Api.live_filter.start = wrap_explorer(function(explorer) - return wrap(function(...) +Api.live_filter.start = wrap(function(...) + local explorer = core.get_explorer() + if explorer then return explorer.live_filter:start_filtering(...) - end) + end end) -Api.live_filter.clear = wrap_explorer(function(explorer) - return wrap(function(...) +Api.live_filter.clear = wrap(function(...) + local explorer = core.get_explorer() + if explorer then return explorer.live_filter:clear_filter(...) - end) + end end) Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark")) diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index c0773105d4a..0587e5a16dd 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -7,7 +7,8 @@ local LiveFilter = {} function LiveFilter:new(opts, explorer) local o = { explorer = explorer, - config = vim.deepcopy(opts.live_filter), + prefix = opts.live_filter.prefix, + always_show_folders = opts.live_filter.always_show_folders, filter = nil, } setmetatable(o, self) @@ -57,8 +58,8 @@ local function remove_overlay(self) overlay_bufnr = 0 overlay_winnr = 0 - if self.explorer.live_filter.filter == "" then - self.explorer.live_filter.clear_filter() + if self.filter == "" then + self:clear_filter() end end @@ -96,7 +97,7 @@ function LiveFilter:apply_filter(node_) end end - local has_nodes = nodes and (self.config.always_show_folders or #nodes > filtered_nodes) + local has_nodes = nodes and (self.always_show_folders or #nodes > filtered_nodes) local ok, is_match = pcall(matches, self, node) node.hidden = not (has_nodes or (ok and is_match)) end @@ -106,8 +107,8 @@ end local function record_char(self) vim.schedule(function() - self.explorer.live_filter.filter = vim.api.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1] - self.explorer.live_filter.apply_filter() + self.filter = vim.api.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1] + self:apply_filter() redraw() end) end @@ -132,7 +133,7 @@ local function calculate_overlay_win_width(self) local wininfo = vim.fn.getwininfo(view.get_winnr())[1] if wininfo then - return wininfo.width - wininfo.textoff - #self.explorer.live_filter.prefix + return wininfo.width - wininfo.textoff - #self.prefix end return 20 @@ -153,7 +154,7 @@ local function create_overlay(self) col = 1, row = 0, relative = "cursor", - width = calculate_overlay_win_width(self.explorer), + width = calculate_overlay_win_width(self), height = 1, border = "none", style = "minimal", @@ -165,9 +166,9 @@ local function create_overlay(self) vim.api.nvim_buf_set_option(overlay_bufnr, "modifiable", true) ---@diagnostic disable-line: deprecated end - vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { self.explorer.live_filter.filter }) + vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { self.filter }) vim.cmd "startinsert" - vim.api.nvim_win_set_cursor(overlay_winnr, { 1, #self.explorer.live_filter.filter + 1 }) + vim.api.nvim_win_set_cursor(overlay_winnr, { 1, #self.filter + 1 }) end function LiveFilter:start_filtering() From d7504b3963e7ab926e58d07ffa80fb3271e59994 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Sun, 28 Jul 2024 11:26:59 +0200 Subject: [PATCH 4/6] fix: style --- lua/nvim-tree/explorer/live-filter.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index 0587e5a16dd..c6c7fc05672 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -117,11 +117,15 @@ local function configure_buffer_overlay(self) overlay_bufnr = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_attach(overlay_bufnr, true, { - on_lines = function() return record_char(self) end, + on_lines = function() + return record_char(self) + end, }) vim.api.nvim_create_autocmd("InsertLeave", { - callback = function() return remove_overlay(self) end, + callback = function() + return remove_overlay(self) + end, once = true, }) @@ -180,7 +184,9 @@ function LiveFilter:start_filtering() local col = #self.prefix > 0 and #self.prefix - 1 or 1 view.set_cursor { row, col } -- needs scheduling to let the cursor move before initializing the window - vim.schedule(function() return create_overlay(self) end) + vim.schedule(function() + return create_overlay(self) + end) end function LiveFilter:clear_filter() From 32314fd3ee54527c3156a62c15aedd1a31c1c192 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Sun, 4 Aug 2024 11:19:31 +0200 Subject: [PATCH 5/6] Update lua/nvim-tree/api.lua Co-authored-by: Alexander Courtis --- lua/nvim-tree/api.lua | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index df3cb1e5415..89a6a2ef75a 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -264,18 +264,8 @@ Api.git.reload = wrap(actions.reloaders.reload_git) Api.events.subscribe = events.subscribe Api.events.Event = events.Event -Api.live_filter.start = wrap(function(...) - local explorer = core.get_explorer() - if explorer then - return explorer.live_filter:start_filtering(...) - end -end) -Api.live_filter.clear = wrap(function(...) - local explorer = core.get_explorer() - if explorer then - return explorer.live_filter:clear_filter(...) - end -end) +Api.live_filter.start = wrap_explorer_member("live_filter", "start_filtering") +Api.live_filter.clear = wrap_explorer_member("live_filter", "clear_filter") Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark")) Api.marks.list = wrap_explorer_member("marks", "get_marks") From 0f2cda6ce04f106e4d2f0767c7406da143a507a1 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Sun, 4 Aug 2024 11:26:14 +0200 Subject: [PATCH 6/6] docs: add missing live filter luadocs --- lua/nvim-tree/explorer/init.lua | 3 +++ lua/nvim-tree/explorer/live-filter.lua | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 9c4f8e581a7..f260bd17b1c 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -16,6 +16,9 @@ M.reload = require("nvim-tree.explorer.reload").reload ---@field absolute_path string ---@field nodes Node[] ---@field open boolean +---@field filters Filters +---@field live_filter LiveFilter +---@field sorters Sorter ---@field marks Marks local Explorer = {} diff --git a/lua/nvim-tree/explorer/live-filter.lua b/lua/nvim-tree/explorer/live-filter.lua index c6c7fc05672..4baf143b6ca 100644 --- a/lua/nvim-tree/explorer/live-filter.lua +++ b/lua/nvim-tree/explorer/live-filter.lua @@ -2,8 +2,15 @@ local view = require "nvim-tree.view" local utils = require "nvim-tree.utils" local Iterator = require "nvim-tree.iterators.node-iterator" +---@class LiveFilter +---@field explorer Explorer +---@field prefix string +---@field always_show_folders boolean +---@field filter string local LiveFilter = {} +---@param opts table +---@param explorer Explorer function LiveFilter:new(opts, explorer) local o = { explorer = explorer,